mirror of https://github.com/knative/caching.git
upgrade to latest dependencies (#923)
bumping google.golang.org/protobuf 259e665...f09e239: > f09e239 all: release v1.36.5 > ab9efaa protogen: fix name mangling for fields with identical GoCamelCase > e677ef9 all: remove weak field support > 89b5638 all: start v1.36.4-devel bumping golang.org/x/sync 913fb63...fe3591b: > fe3591b sync/errgroup: improve documentation for semaphore limit behavior bumping knative.dev/pkg f62a97f...c8bea7c: > c8bea7c Bump golang.org/x/sync from 0.10.0 to 0.11.0 (# 3147) > 99d475b Bump google.golang.org/protobuf from 1.36.4 to 1.36.5 (# 3148) > 36226ee Update Knative injection-gen to use gengov2 (# 3146) Signed-off-by: Knative Automation <automation@knative.team>
This commit is contained in:
parent
ed50a5c83f
commit
525d9e6e24
7
go.mod
7
go.mod
|
@ -11,7 +11,7 @@ require (
|
||||||
k8s.io/code-generator v0.31.4
|
k8s.io/code-generator v0.31.4
|
||||||
k8s.io/kube-openapi v0.0.0-20240808142205-8e686545bdb8
|
k8s.io/kube-openapi v0.0.0-20240808142205-8e686545bdb8
|
||||||
knative.dev/hack v0.0.0-20250128013659-5f7f0f50e9de
|
knative.dev/hack v0.0.0-20250128013659-5f7f0f50e9de
|
||||||
knative.dev/pkg v0.0.0-20250203163623-f62a97fc6ad4
|
knative.dev/pkg v0.0.0-20250211185550-c8bea7c326ff
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
@ -60,7 +60,7 @@ require (
|
||||||
golang.org/x/mod v0.22.0 // indirect
|
golang.org/x/mod v0.22.0 // indirect
|
||||||
golang.org/x/net v0.34.0 // indirect
|
golang.org/x/net v0.34.0 // indirect
|
||||||
golang.org/x/oauth2 v0.24.0 // indirect
|
golang.org/x/oauth2 v0.24.0 // indirect
|
||||||
golang.org/x/sync v0.10.0 // indirect
|
golang.org/x/sync v0.11.0 // indirect
|
||||||
golang.org/x/sys v0.29.0 // indirect
|
golang.org/x/sys v0.29.0 // indirect
|
||||||
golang.org/x/term v0.28.0 // indirect
|
golang.org/x/term v0.28.0 // indirect
|
||||||
golang.org/x/text v0.21.0 // indirect
|
golang.org/x/text v0.21.0 // indirect
|
||||||
|
@ -71,12 +71,11 @@ require (
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20241202173237-19429a94021a // indirect
|
google.golang.org/genproto/googleapis/api v0.0.0-20241202173237-19429a94021a // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect
|
||||||
google.golang.org/grpc v1.70.0 // indirect
|
google.golang.org/grpc v1.70.0 // indirect
|
||||||
google.golang.org/protobuf v1.36.4 // indirect
|
google.golang.org/protobuf v1.36.5 // indirect
|
||||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
|
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
|
||||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
k8s.io/gengo v0.0.0-20240404160639-a0386bf69313 // indirect
|
|
||||||
k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70 // indirect
|
k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70 // indirect
|
||||||
k8s.io/klog/v2 v2.130.1 // indirect
|
k8s.io/klog/v2 v2.130.1 // indirect
|
||||||
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect
|
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect
|
||||||
|
|
21
go.sum
21
go.sum
|
@ -93,7 +93,6 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V
|
||||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||||
github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA=
|
github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA=
|
||||||
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
||||||
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
|
|
||||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
|
@ -160,7 +159,6 @@ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
|
||||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||||
|
@ -210,7 +208,6 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
|
||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
@ -282,7 +279,6 @@ github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99
|
||||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
|
||||||
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
||||||
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
@ -428,8 +424,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
|
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
|
||||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
@ -525,7 +521,6 @@ golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjs
|
||||||
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||||
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||||
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
|
||||||
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
@ -631,8 +626,8 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
|
||||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
|
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
|
||||||
google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
@ -671,11 +666,8 @@ k8s.io/client-go v0.31.4 h1:t4QEXt4jgHIkKKlx06+W3+1JOwAFU/2OPiOo7H92eRQ=
|
||||||
k8s.io/client-go v0.31.4/go.mod h1:kvuMro4sFYIa8sulL5Gi5GFqUPvfH2O/dXuKstbaaeg=
|
k8s.io/client-go v0.31.4/go.mod h1:kvuMro4sFYIa8sulL5Gi5GFqUPvfH2O/dXuKstbaaeg=
|
||||||
k8s.io/code-generator v0.31.4 h1:Vu+8fKz+239rKiVDHFVHgjQ162cg5iUQPtTyQbwXeQw=
|
k8s.io/code-generator v0.31.4 h1:Vu+8fKz+239rKiVDHFVHgjQ162cg5iUQPtTyQbwXeQw=
|
||||||
k8s.io/code-generator v0.31.4/go.mod h1:yMDt13Kn7m4MMZ4LxB1KBzdZjEyxzdT4b4qXq+lnI90=
|
k8s.io/code-generator v0.31.4/go.mod h1:yMDt13Kn7m4MMZ4LxB1KBzdZjEyxzdT4b4qXq+lnI90=
|
||||||
k8s.io/gengo v0.0.0-20240404160639-a0386bf69313 h1:wBIDZID8ju9pwOiLlV22YYKjFGtiNSWgHf5CnKLRUuM=
|
|
||||||
k8s.io/gengo v0.0.0-20240404160639-a0386bf69313/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
|
|
||||||
k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70 h1:NGrVE502P0s0/1hudf8zjgwki1X/TByhmAoILTarmzo=
|
k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70 h1:NGrVE502P0s0/1hudf8zjgwki1X/TByhmAoILTarmzo=
|
||||||
k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70/go.mod h1:VH3AT8AaQOqiGjMF9p0/IM1Dj+82ZwjfxUP1IxaHE+8=
|
k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70/go.mod h1:VH3AT8AaQOqiGjMF9p0/IM1Dj+82ZwjfxUP1IxaHE+8=
|
||||||
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
|
|
||||||
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
||||||
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||||
k8s.io/kube-openapi v0.0.0-20240808142205-8e686545bdb8 h1:1Wof1cGQgA5pqgo8MxKPtf+qN6Sh/0JzznmeGPm1HnE=
|
k8s.io/kube-openapi v0.0.0-20240808142205-8e686545bdb8 h1:1Wof1cGQgA5pqgo8MxKPtf+qN6Sh/0JzznmeGPm1HnE=
|
||||||
|
@ -684,8 +676,8 @@ k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1
|
||||||
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||||
knative.dev/hack v0.0.0-20250128013659-5f7f0f50e9de h1:9xWkakMP0rpTpEIi9iRfkDsqhe2XbuyJdBkrlPB2Yjs=
|
knative.dev/hack v0.0.0-20250128013659-5f7f0f50e9de h1:9xWkakMP0rpTpEIi9iRfkDsqhe2XbuyJdBkrlPB2Yjs=
|
||||||
knative.dev/hack v0.0.0-20250128013659-5f7f0f50e9de/go.mod h1:R0ritgYtjLDO9527h5vb5X6gfvt5LCrJ55BNbVDsWiY=
|
knative.dev/hack v0.0.0-20250128013659-5f7f0f50e9de/go.mod h1:R0ritgYtjLDO9527h5vb5X6gfvt5LCrJ55BNbVDsWiY=
|
||||||
knative.dev/pkg v0.0.0-20250203163623-f62a97fc6ad4 h1:dHkehXNqUAuRtHr0LjGqBC3Uztuj6LcOrOdqCI4c85s=
|
knative.dev/pkg v0.0.0-20250211185550-c8bea7c326ff h1:cW8JXhIfx4pGUb3+pVHQ6+rT8+GB84I/ovfQFf7s8Gc=
|
||||||
knative.dev/pkg v0.0.0-20250203163623-f62a97fc6ad4/go.mod h1:T4d91cYeEBb9tpz4JqoqA77Px/rhq529heP6NKoknSI=
|
knative.dev/pkg v0.0.0-20250211185550-c8bea7c326ff/go.mod h1:yDbcfhhTsjgKVatbtdPmV5ux9cJ9BJ2Pv2LX3/N1wF0=
|
||||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||||
|
@ -693,6 +685,5 @@ sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMm
|
||||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
|
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
|
||||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
|
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
|
||||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
|
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
|
||||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
|
||||||
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
|
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
|
||||||
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
|
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
|
||||||
|
|
|
@ -118,6 +118,7 @@ func (g *Group) TryGo(f func() error) bool {
|
||||||
|
|
||||||
// SetLimit limits the number of active goroutines in this group to at most n.
|
// SetLimit limits the number of active goroutines in this group to at most n.
|
||||||
// A negative value indicates no limit.
|
// A negative value indicates no limit.
|
||||||
|
// A limit of zero will prevent any new goroutines from being added.
|
||||||
//
|
//
|
||||||
// Any subsequent call to the Go method will block until it can add an active
|
// Any subsequent call to the Go method will block until it can add an active
|
||||||
// goroutine without exceeding the configured limit.
|
// goroutine without exceeding the configured limit.
|
||||||
|
|
|
@ -192,11 +192,6 @@ func (d decoder) unmarshalMessage(m protoreflect.Message, skipTypeURL bool) erro
|
||||||
fd = fieldDescs.ByTextName(name)
|
fd = fieldDescs.ByTextName(name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if flags.ProtoLegacyWeak {
|
|
||||||
if fd != nil && fd.IsWeak() && fd.Message().IsPlaceholder() {
|
|
||||||
fd = nil // reset since the weak reference is not linked in
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if fd == nil {
|
if fd == nil {
|
||||||
// Field is unknown.
|
// Field is unknown.
|
||||||
|
|
|
@ -185,11 +185,6 @@ func (d decoder) unmarshalMessage(m protoreflect.Message, checkDelims bool) erro
|
||||||
} else if xtErr != nil && xtErr != protoregistry.NotFound {
|
} else if xtErr != nil && xtErr != protoregistry.NotFound {
|
||||||
return d.newError(tok.Pos(), "unable to resolve [%s]: %v", tok.RawString(), xtErr)
|
return d.newError(tok.Pos(), "unable to resolve [%s]: %v", tok.RawString(), xtErr)
|
||||||
}
|
}
|
||||||
if flags.ProtoLegacyWeak {
|
|
||||||
if fd != nil && fd.IsWeak() && fd.Message().IsPlaceholder() {
|
|
||||||
fd = nil // reset since the weak reference is not linked in
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle unknown fields.
|
// Handle unknown fields.
|
||||||
if fd == nil {
|
if fd == nil {
|
||||||
|
|
|
@ -26,7 +26,7 @@ var byteType = reflect.TypeOf(byte(0))
|
||||||
// The type is the underlying field type (e.g., a repeated field may be
|
// The type is the underlying field type (e.g., a repeated field may be
|
||||||
// represented by []T, but the Go type passed in is just T).
|
// represented by []T, but the Go type passed in is just T).
|
||||||
// A list of enum value descriptors must be provided for enum fields.
|
// A list of enum value descriptors must be provided for enum fields.
|
||||||
// This does not populate the Enum or Message (except for weak message).
|
// This does not populate the Enum or Message.
|
||||||
//
|
//
|
||||||
// This function is a best effort attempt; parsing errors are ignored.
|
// This function is a best effort attempt; parsing errors are ignored.
|
||||||
func Unmarshal(tag string, goType reflect.Type, evs protoreflect.EnumValueDescriptors) protoreflect.FieldDescriptor {
|
func Unmarshal(tag string, goType reflect.Type, evs protoreflect.EnumValueDescriptors) protoreflect.FieldDescriptor {
|
||||||
|
@ -109,9 +109,6 @@ func Unmarshal(tag string, goType reflect.Type, evs protoreflect.EnumValueDescri
|
||||||
}
|
}
|
||||||
case s == "packed":
|
case s == "packed":
|
||||||
f.L1.EditionFeatures.IsPacked = true
|
f.L1.EditionFeatures.IsPacked = true
|
||||||
case strings.HasPrefix(s, "weak="):
|
|
||||||
f.L1.IsWeak = true
|
|
||||||
f.L1.Message = filedesc.PlaceholderMessage(protoreflect.FullName(s[len("weak="):]))
|
|
||||||
case strings.HasPrefix(s, "def="):
|
case strings.HasPrefix(s, "def="):
|
||||||
// The default tag is special in that everything afterwards is the
|
// The default tag is special in that everything afterwards is the
|
||||||
// default regardless of the presence of commas.
|
// default regardless of the presence of commas.
|
||||||
|
@ -183,9 +180,6 @@ func Marshal(fd protoreflect.FieldDescriptor, enumName string) string {
|
||||||
// the exact same semantics from the previous generator.
|
// the exact same semantics from the previous generator.
|
||||||
tag = append(tag, "json="+jsonName)
|
tag = append(tag, "json="+jsonName)
|
||||||
}
|
}
|
||||||
if fd.IsWeak() {
|
|
||||||
tag = append(tag, "weak="+string(fd.Message().FullName()))
|
|
||||||
}
|
|
||||||
// The previous implementation does not tag extension fields as proto3,
|
// The previous implementation does not tag extension fields as proto3,
|
||||||
// even when the field is defined in a proto3 file. Match that behavior
|
// even when the field is defined in a proto3 file. Match that behavior
|
||||||
// for consistency.
|
// for consistency.
|
||||||
|
|
|
@ -19,7 +19,6 @@ import (
|
||||||
"google.golang.org/protobuf/internal/pragma"
|
"google.golang.org/protobuf/internal/pragma"
|
||||||
"google.golang.org/protobuf/internal/strs"
|
"google.golang.org/protobuf/internal/strs"
|
||||||
"google.golang.org/protobuf/reflect/protoreflect"
|
"google.golang.org/protobuf/reflect/protoreflect"
|
||||||
"google.golang.org/protobuf/reflect/protoregistry"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Edition is an Enum for proto2.Edition
|
// Edition is an Enum for proto2.Edition
|
||||||
|
@ -275,7 +274,6 @@ type (
|
||||||
Kind protoreflect.Kind
|
Kind protoreflect.Kind
|
||||||
StringName stringName
|
StringName stringName
|
||||||
IsProto3Optional bool // promoted from google.protobuf.FieldDescriptorProto
|
IsProto3Optional bool // promoted from google.protobuf.FieldDescriptorProto
|
||||||
IsWeak bool // promoted from google.protobuf.FieldOptions
|
|
||||||
IsLazy bool // promoted from google.protobuf.FieldOptions
|
IsLazy bool // promoted from google.protobuf.FieldOptions
|
||||||
Default defaultValue
|
Default defaultValue
|
||||||
ContainingOneof protoreflect.OneofDescriptor // must be consistent with Message.Oneofs.Fields
|
ContainingOneof protoreflect.OneofDescriptor // must be consistent with Message.Oneofs.Fields
|
||||||
|
@ -369,7 +367,7 @@ func (fd *Field) IsPacked() bool {
|
||||||
return fd.L1.EditionFeatures.IsPacked
|
return fd.L1.EditionFeatures.IsPacked
|
||||||
}
|
}
|
||||||
func (fd *Field) IsExtension() bool { return false }
|
func (fd *Field) IsExtension() bool { return false }
|
||||||
func (fd *Field) IsWeak() bool { return fd.L1.IsWeak }
|
func (fd *Field) IsWeak() bool { return false }
|
||||||
func (fd *Field) IsLazy() bool { return fd.L1.IsLazy }
|
func (fd *Field) IsLazy() bool { return fd.L1.IsLazy }
|
||||||
func (fd *Field) IsList() bool { return fd.Cardinality() == protoreflect.Repeated && !fd.IsMap() }
|
func (fd *Field) IsList() bool { return fd.Cardinality() == protoreflect.Repeated && !fd.IsMap() }
|
||||||
func (fd *Field) IsMap() bool { return fd.Message() != nil && fd.Message().IsMapEntry() }
|
func (fd *Field) IsMap() bool { return fd.Message() != nil && fd.Message().IsMapEntry() }
|
||||||
|
@ -396,11 +394,6 @@ func (fd *Field) Enum() protoreflect.EnumDescriptor {
|
||||||
return fd.L1.Enum
|
return fd.L1.Enum
|
||||||
}
|
}
|
||||||
func (fd *Field) Message() protoreflect.MessageDescriptor {
|
func (fd *Field) Message() protoreflect.MessageDescriptor {
|
||||||
if fd.L1.IsWeak {
|
|
||||||
if d, _ := protoregistry.GlobalFiles.FindDescriptorByName(fd.L1.Message.FullName()); d != nil {
|
|
||||||
return d.(protoreflect.MessageDescriptor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return fd.L1.Message
|
return fd.L1.Message
|
||||||
}
|
}
|
||||||
func (fd *Field) IsMapEntry() bool {
|
func (fd *Field) IsMapEntry() bool {
|
||||||
|
|
|
@ -32,11 +32,6 @@ func (file *File) resolveMessages() {
|
||||||
for j := range md.L2.Fields.List {
|
for j := range md.L2.Fields.List {
|
||||||
fd := &md.L2.Fields.List[j]
|
fd := &md.L2.Fields.List[j]
|
||||||
|
|
||||||
// Weak fields are resolved upon actual use.
|
|
||||||
if fd.L1.IsWeak {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resolve message field dependency.
|
// Resolve message field dependency.
|
||||||
switch fd.L1.Kind {
|
switch fd.L1.Kind {
|
||||||
case protoreflect.EnumKind:
|
case protoreflect.EnumKind:
|
||||||
|
@ -150,8 +145,6 @@ func (fd *File) unmarshalFull(b []byte) {
|
||||||
switch num {
|
switch num {
|
||||||
case genid.FileDescriptorProto_PublicDependency_field_number:
|
case genid.FileDescriptorProto_PublicDependency_field_number:
|
||||||
fd.L2.Imports[v].IsPublic = true
|
fd.L2.Imports[v].IsPublic = true
|
||||||
case genid.FileDescriptorProto_WeakDependency_field_number:
|
|
||||||
fd.L2.Imports[v].IsWeak = true
|
|
||||||
}
|
}
|
||||||
case protowire.BytesType:
|
case protowire.BytesType:
|
||||||
v, m := protowire.ConsumeBytes(b)
|
v, m := protowire.ConsumeBytes(b)
|
||||||
|
@ -502,8 +495,6 @@ func (fd *Field) unmarshalOptions(b []byte) {
|
||||||
switch num {
|
switch num {
|
||||||
case genid.FieldOptions_Packed_field_number:
|
case genid.FieldOptions_Packed_field_number:
|
||||||
fd.L1.EditionFeatures.IsPacked = protowire.DecodeBool(v)
|
fd.L1.EditionFeatures.IsPacked = protowire.DecodeBool(v)
|
||||||
case genid.FieldOptions_Weak_field_number:
|
|
||||||
fd.L1.IsWeak = protowire.DecodeBool(v)
|
|
||||||
case genid.FieldOptions_Lazy_field_number:
|
case genid.FieldOptions_Lazy_field_number:
|
||||||
fd.L1.IsLazy = protowire.DecodeBool(v)
|
fd.L1.IsLazy = protowire.DecodeBool(v)
|
||||||
case FieldOptions_EnforceUTF8:
|
case FieldOptions_EnforceUTF8:
|
||||||
|
|
|
@ -63,7 +63,7 @@ type Builder struct {
|
||||||
// message declarations in "flattened ordering".
|
// message declarations in "flattened ordering".
|
||||||
//
|
//
|
||||||
// Dependencies are Go types for enums or messages referenced by
|
// Dependencies are Go types for enums or messages referenced by
|
||||||
// message fields (excluding weak fields), for parent extended messages of
|
// message fields, for parent extended messages of
|
||||||
// extension fields, for enums or messages referenced by extension fields,
|
// extension fields, for enums or messages referenced by extension fields,
|
||||||
// and for input and output messages referenced by service methods.
|
// and for input and output messages referenced by service methods.
|
||||||
// Dependencies must come after declarations, but the ordering of
|
// Dependencies must come after declarations, but the ordering of
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
package flags
|
package flags
|
||||||
|
|
||||||
// ProtoLegacy specifies whether to enable support for legacy functionality
|
// ProtoLegacy specifies whether to enable support for legacy functionality
|
||||||
// such as MessageSets, weak fields, and various other obscure behavior
|
// such as MessageSets, and various other obscure behavior
|
||||||
// that is necessary to maintain backwards compatibility with proto1 or
|
// that is necessary to maintain backwards compatibility with proto1 or
|
||||||
// the pre-release variants of proto2 and proto3.
|
// the pre-release variants of proto2 and proto3.
|
||||||
//
|
//
|
||||||
|
@ -22,8 +22,3 @@ const ProtoLegacy = protoLegacy
|
||||||
// extension fields at unmarshal time, but defers creating the message
|
// extension fields at unmarshal time, but defers creating the message
|
||||||
// structure until the extension is first accessed.
|
// structure until the extension is first accessed.
|
||||||
const LazyUnmarshalExtensions = ProtoLegacy
|
const LazyUnmarshalExtensions = ProtoLegacy
|
||||||
|
|
||||||
// ProtoLegacyWeak specifies whether to enable support for weak fields.
|
|
||||||
// This flag was split out of ProtoLegacy in preparation for removing
|
|
||||||
// support for weak fields (independent of the other protolegacy features).
|
|
||||||
const ProtoLegacyWeak = ProtoLegacy
|
|
||||||
|
|
|
@ -11,15 +11,10 @@ const (
|
||||||
SizeCache_goname = "sizeCache"
|
SizeCache_goname = "sizeCache"
|
||||||
SizeCacheA_goname = "XXX_sizecache"
|
SizeCacheA_goname = "XXX_sizecache"
|
||||||
|
|
||||||
WeakFields_goname = "weakFields"
|
|
||||||
WeakFieldsA_goname = "XXX_weak"
|
|
||||||
|
|
||||||
UnknownFields_goname = "unknownFields"
|
UnknownFields_goname = "unknownFields"
|
||||||
UnknownFieldsA_goname = "XXX_unrecognized"
|
UnknownFieldsA_goname = "XXX_unrecognized"
|
||||||
|
|
||||||
ExtensionFields_goname = "extensionFields"
|
ExtensionFields_goname = "extensionFields"
|
||||||
ExtensionFieldsA_goname = "XXX_InternalExtensions"
|
ExtensionFieldsA_goname = "XXX_InternalExtensions"
|
||||||
ExtensionFieldsB_goname = "XXX_extensions"
|
ExtensionFieldsB_goname = "XXX_extensions"
|
||||||
|
|
||||||
WeakFieldPrefix_goname = "XXX_weak_"
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -5,15 +5,12 @@
|
||||||
package impl
|
package impl
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"sync"
|
|
||||||
|
|
||||||
"google.golang.org/protobuf/encoding/protowire"
|
"google.golang.org/protobuf/encoding/protowire"
|
||||||
"google.golang.org/protobuf/internal/errors"
|
"google.golang.org/protobuf/internal/errors"
|
||||||
"google.golang.org/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
"google.golang.org/protobuf/reflect/protoreflect"
|
"google.golang.org/protobuf/reflect/protoreflect"
|
||||||
"google.golang.org/protobuf/reflect/protoregistry"
|
|
||||||
"google.golang.org/protobuf/runtime/protoiface"
|
"google.golang.org/protobuf/runtime/protoiface"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -121,78 +118,6 @@ func (mi *MessageInfo) initOneofFieldCoders(od protoreflect.OneofDescriptor, si
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeWeakMessageFieldCoder(fd protoreflect.FieldDescriptor) pointerCoderFuncs {
|
|
||||||
var once sync.Once
|
|
||||||
var messageType protoreflect.MessageType
|
|
||||||
lazyInit := func() {
|
|
||||||
once.Do(func() {
|
|
||||||
messageName := fd.Message().FullName()
|
|
||||||
messageType, _ = protoregistry.GlobalTypes.FindMessageByName(messageName)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return pointerCoderFuncs{
|
|
||||||
size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int {
|
|
||||||
m, ok := p.WeakFields().get(f.num)
|
|
||||||
if !ok {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
lazyInit()
|
|
||||||
if messageType == nil {
|
|
||||||
panic(fmt.Sprintf("weak message %v is not linked in", fd.Message().FullName()))
|
|
||||||
}
|
|
||||||
return sizeMessage(m, f.tagsize, opts)
|
|
||||||
},
|
|
||||||
marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
|
|
||||||
m, ok := p.WeakFields().get(f.num)
|
|
||||||
if !ok {
|
|
||||||
return b, nil
|
|
||||||
}
|
|
||||||
lazyInit()
|
|
||||||
if messageType == nil {
|
|
||||||
panic(fmt.Sprintf("weak message %v is not linked in", fd.Message().FullName()))
|
|
||||||
}
|
|
||||||
return appendMessage(b, m, f.wiretag, opts)
|
|
||||||
},
|
|
||||||
unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
|
|
||||||
fs := p.WeakFields()
|
|
||||||
m, ok := fs.get(f.num)
|
|
||||||
if !ok {
|
|
||||||
lazyInit()
|
|
||||||
if messageType == nil {
|
|
||||||
return unmarshalOutput{}, errUnknown
|
|
||||||
}
|
|
||||||
m = messageType.New().Interface()
|
|
||||||
fs.set(f.num, m)
|
|
||||||
}
|
|
||||||
return consumeMessage(b, m, wtyp, opts)
|
|
||||||
},
|
|
||||||
isInit: func(p pointer, f *coderFieldInfo) error {
|
|
||||||
m, ok := p.WeakFields().get(f.num)
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return proto.CheckInitialized(m)
|
|
||||||
},
|
|
||||||
merge: func(dst, src pointer, f *coderFieldInfo, opts mergeOptions) {
|
|
||||||
sm, ok := src.WeakFields().get(f.num)
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
dm, ok := dst.WeakFields().get(f.num)
|
|
||||||
if !ok {
|
|
||||||
lazyInit()
|
|
||||||
if messageType == nil {
|
|
||||||
panic(fmt.Sprintf("weak message %v is not linked in", fd.Message().FullName()))
|
|
||||||
}
|
|
||||||
dm = messageType.New().Interface()
|
|
||||||
dst.WeakFields().set(f.num, dm)
|
|
||||||
}
|
|
||||||
opts.Merge(dm, sm)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeMessageFieldCoder(fd protoreflect.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
|
func makeMessageFieldCoder(fd protoreflect.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
|
||||||
if mi := getMessageInfo(ft); mi != nil {
|
if mi := getMessageInfo(ft); mi != nil {
|
||||||
funcs := pointerCoderFuncs{
|
funcs := pointerCoderFuncs{
|
||||||
|
|
|
@ -119,9 +119,6 @@ func (mi *MessageInfo) makeCoderMethods(t reflect.Type, si structInfo) {
|
||||||
}
|
}
|
||||||
case isOneof:
|
case isOneof:
|
||||||
fieldOffset = offsetOf(fs)
|
fieldOffset = offsetOf(fs)
|
||||||
case fd.IsWeak():
|
|
||||||
fieldOffset = si.weakOffset
|
|
||||||
funcs = makeWeakMessageFieldCoder(fd)
|
|
||||||
default:
|
default:
|
||||||
fieldOffset = offsetOf(fs)
|
fieldOffset = offsetOf(fs)
|
||||||
childMessage, funcs = fieldCoder(fd, ft)
|
childMessage, funcs = fieldCoder(fd, ft)
|
||||||
|
|
|
@ -46,9 +46,6 @@ func (mi *MessageInfo) makeOpaqueCoderMethods(t reflect.Type, si opaqueStructInf
|
||||||
switch {
|
switch {
|
||||||
case fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic():
|
case fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic():
|
||||||
fieldOffset = offsetOf(fs)
|
fieldOffset = offsetOf(fs)
|
||||||
case fd.IsWeak():
|
|
||||||
fieldOffset = si.weakOffset
|
|
||||||
funcs = makeWeakMessageFieldCoder(fd)
|
|
||||||
case fd.Message() != nil && !fd.IsMap():
|
case fd.Message() != nil && !fd.IsMap():
|
||||||
fieldOffset = offsetOf(fs)
|
fieldOffset = offsetOf(fs)
|
||||||
if fd.IsList() {
|
if fd.IsList() {
|
||||||
|
|
|
@ -131,7 +131,7 @@ func (mi *MessageInfo) skipField(b []byte, f *coderFieldInfo, wtyp protowire.Typ
|
||||||
fmi := f.validation.mi
|
fmi := f.validation.mi
|
||||||
if fmi == nil {
|
if fmi == nil {
|
||||||
fd := mi.Desc.Fields().ByNumber(f.num)
|
fd := mi.Desc.Fields().ByNumber(f.num)
|
||||||
if fd == nil || !fd.IsWeak() {
|
if fd == nil {
|
||||||
return out, ValidationUnknown
|
return out, ValidationUnknown
|
||||||
}
|
}
|
||||||
messageName := fd.Message().FullName()
|
messageName := fd.Message().FullName()
|
||||||
|
|
|
@ -310,12 +310,9 @@ func aberrantAppendField(md *filedesc.Message, goType reflect.Type, tag, tagKey,
|
||||||
fd.L0.Parent = md
|
fd.L0.Parent = md
|
||||||
fd.L0.Index = n
|
fd.L0.Index = n
|
||||||
|
|
||||||
if fd.L1.IsWeak || fd.L1.EditionFeatures.IsPacked {
|
if fd.L1.EditionFeatures.IsPacked {
|
||||||
fd.L1.Options = func() protoreflect.ProtoMessage {
|
fd.L1.Options = func() protoreflect.ProtoMessage {
|
||||||
opts := descopts.Field.ProtoReflect().New()
|
opts := descopts.Field.ProtoReflect().New()
|
||||||
if fd.L1.IsWeak {
|
|
||||||
opts.Set(opts.Descriptor().Fields().ByName("weak"), protoreflect.ValueOfBool(true))
|
|
||||||
}
|
|
||||||
if fd.L1.EditionFeatures.IsPacked {
|
if fd.L1.EditionFeatures.IsPacked {
|
||||||
opts.Set(opts.Descriptor().Fields().ByName("packed"), protoreflect.ValueOfBool(fd.L1.EditionFeatures.IsPacked))
|
opts.Set(opts.Descriptor().Fields().ByName("packed"), protoreflect.ValueOfBool(fd.L1.EditionFeatures.IsPacked))
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,6 @@ import (
|
||||||
|
|
||||||
"google.golang.org/protobuf/internal/genid"
|
"google.golang.org/protobuf/internal/genid"
|
||||||
"google.golang.org/protobuf/reflect/protoreflect"
|
"google.golang.org/protobuf/reflect/protoreflect"
|
||||||
"google.golang.org/protobuf/reflect/protoregistry"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// MessageInfo provides protobuf related functionality for a given Go type
|
// MessageInfo provides protobuf related functionality for a given Go type
|
||||||
|
@ -120,7 +119,6 @@ type (
|
||||||
|
|
||||||
var (
|
var (
|
||||||
sizecacheType = reflect.TypeOf(SizeCache(0))
|
sizecacheType = reflect.TypeOf(SizeCache(0))
|
||||||
weakFieldsType = reflect.TypeOf(WeakFields(nil))
|
|
||||||
unknownFieldsAType = reflect.TypeOf(unknownFieldsA(nil))
|
unknownFieldsAType = reflect.TypeOf(unknownFieldsA(nil))
|
||||||
unknownFieldsBType = reflect.TypeOf(unknownFieldsB(nil))
|
unknownFieldsBType = reflect.TypeOf(unknownFieldsB(nil))
|
||||||
extensionFieldsType = reflect.TypeOf(ExtensionFields(nil))
|
extensionFieldsType = reflect.TypeOf(ExtensionFields(nil))
|
||||||
|
@ -129,8 +127,6 @@ var (
|
||||||
type structInfo struct {
|
type structInfo struct {
|
||||||
sizecacheOffset offset
|
sizecacheOffset offset
|
||||||
sizecacheType reflect.Type
|
sizecacheType reflect.Type
|
||||||
weakOffset offset
|
|
||||||
weakType reflect.Type
|
|
||||||
unknownOffset offset
|
unknownOffset offset
|
||||||
unknownType reflect.Type
|
unknownType reflect.Type
|
||||||
extensionOffset offset
|
extensionOffset offset
|
||||||
|
@ -148,7 +144,6 @@ type structInfo struct {
|
||||||
func (mi *MessageInfo) makeStructInfo(t reflect.Type) structInfo {
|
func (mi *MessageInfo) makeStructInfo(t reflect.Type) structInfo {
|
||||||
si := structInfo{
|
si := structInfo{
|
||||||
sizecacheOffset: invalidOffset,
|
sizecacheOffset: invalidOffset,
|
||||||
weakOffset: invalidOffset,
|
|
||||||
unknownOffset: invalidOffset,
|
unknownOffset: invalidOffset,
|
||||||
extensionOffset: invalidOffset,
|
extensionOffset: invalidOffset,
|
||||||
lazyOffset: invalidOffset,
|
lazyOffset: invalidOffset,
|
||||||
|
@ -168,11 +163,6 @@ fieldLoop:
|
||||||
si.sizecacheOffset = offsetOf(f)
|
si.sizecacheOffset = offsetOf(f)
|
||||||
si.sizecacheType = f.Type
|
si.sizecacheType = f.Type
|
||||||
}
|
}
|
||||||
case genid.WeakFields_goname, genid.WeakFieldsA_goname:
|
|
||||||
if f.Type == weakFieldsType {
|
|
||||||
si.weakOffset = offsetOf(f)
|
|
||||||
si.weakType = f.Type
|
|
||||||
}
|
|
||||||
case genid.UnknownFields_goname, genid.UnknownFieldsA_goname:
|
case genid.UnknownFields_goname, genid.UnknownFieldsA_goname:
|
||||||
if f.Type == unknownFieldsAType || f.Type == unknownFieldsBType {
|
if f.Type == unknownFieldsAType || f.Type == unknownFieldsBType {
|
||||||
si.unknownOffset = offsetOf(f)
|
si.unknownOffset = offsetOf(f)
|
||||||
|
@ -256,9 +246,6 @@ func (mi *MessageInfo) Message(i int) protoreflect.MessageType {
|
||||||
mi.init()
|
mi.init()
|
||||||
fd := mi.Desc.Fields().Get(i)
|
fd := mi.Desc.Fields().Get(i)
|
||||||
switch {
|
switch {
|
||||||
case fd.IsWeak():
|
|
||||||
mt, _ := protoregistry.GlobalTypes.FindMessageByName(fd.Message().FullName())
|
|
||||||
return mt
|
|
||||||
case fd.IsMap():
|
case fd.IsMap():
|
||||||
return mapEntryType{fd.Message(), mi.fieldTypes[fd.Number()]}
|
return mapEntryType{fd.Message(), mi.fieldTypes[fd.Number()]}
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -56,9 +56,6 @@ func opaqueInitHook(mi *MessageInfo) bool {
|
||||||
usePresence, _ := usePresenceForField(si, fd)
|
usePresence, _ := usePresenceForField(si, fd)
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case fd.IsWeak():
|
|
||||||
// Weak fields are no different for opaque.
|
|
||||||
fi = fieldInfoForWeakMessage(fd, si.weakOffset)
|
|
||||||
case fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic():
|
case fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic():
|
||||||
// Oneofs are no different for opaque.
|
// Oneofs are no different for opaque.
|
||||||
fi = fieldInfoForOneof(fd, si.oneofsByName[fd.ContainingOneof().Name()], mi.Exporter, si.oneofWrappersByNumber[fd.Number()])
|
fi = fieldInfoForOneof(fd, si.oneofsByName[fd.ContainingOneof().Name()], mi.Exporter, si.oneofWrappersByNumber[fd.Number()])
|
||||||
|
@ -620,8 +617,6 @@ func usePresenceForField(si opaqueStructInfo, fd protoreflect.FieldDescriptor) (
|
||||||
switch {
|
switch {
|
||||||
case fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic():
|
case fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic():
|
||||||
return false, false
|
return false, false
|
||||||
case fd.IsWeak():
|
|
||||||
return false, false
|
|
||||||
case fd.IsMap():
|
case fd.IsMap():
|
||||||
return false, false
|
return false, false
|
||||||
case fd.Kind() == protoreflect.MessageKind || fd.Kind() == protoreflect.GroupKind:
|
case fd.Kind() == protoreflect.MessageKind || fd.Kind() == protoreflect.GroupKind:
|
||||||
|
|
|
@ -72,8 +72,6 @@ func (mi *MessageInfo) makeKnownFieldsFunc(si structInfo) {
|
||||||
fi = fieldInfoForMap(fd, fs, mi.Exporter)
|
fi = fieldInfoForMap(fd, fs, mi.Exporter)
|
||||||
case fd.IsList():
|
case fd.IsList():
|
||||||
fi = fieldInfoForList(fd, fs, mi.Exporter)
|
fi = fieldInfoForList(fd, fs, mi.Exporter)
|
||||||
case fd.IsWeak():
|
|
||||||
fi = fieldInfoForWeakMessage(fd, si.weakOffset)
|
|
||||||
case fd.Message() != nil:
|
case fd.Message() != nil:
|
||||||
fi = fieldInfoForMessage(fd, fs, mi.Exporter)
|
fi = fieldInfoForMessage(fd, fs, mi.Exporter)
|
||||||
default:
|
default:
|
||||||
|
@ -219,9 +217,6 @@ func (mi *MessageInfo) makeFieldTypes(si structInfo) {
|
||||||
}
|
}
|
||||||
case fd.Message() != nil:
|
case fd.Message() != nil:
|
||||||
ft = fs.Type
|
ft = fs.Type
|
||||||
if fd.IsWeak() {
|
|
||||||
ft = nil
|
|
||||||
}
|
|
||||||
isMessage = true
|
isMessage = true
|
||||||
}
|
}
|
||||||
if isMessage && ft != nil && ft.Kind() != reflect.Ptr {
|
if isMessage && ft != nil && ft.Kind() != reflect.Ptr {
|
||||||
|
|
|
@ -8,11 +8,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sync"
|
|
||||||
|
|
||||||
"google.golang.org/protobuf/internal/flags"
|
|
||||||
"google.golang.org/protobuf/reflect/protoreflect"
|
"google.golang.org/protobuf/reflect/protoreflect"
|
||||||
"google.golang.org/protobuf/reflect/protoregistry"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type fieldInfo struct {
|
type fieldInfo struct {
|
||||||
|
@ -332,79 +329,6 @@ func fieldInfoForScalar(fd protoreflect.FieldDescriptor, fs reflect.StructField,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func fieldInfoForWeakMessage(fd protoreflect.FieldDescriptor, weakOffset offset) fieldInfo {
|
|
||||||
if !flags.ProtoLegacyWeak {
|
|
||||||
panic("no support for proto1 weak fields")
|
|
||||||
}
|
|
||||||
|
|
||||||
var once sync.Once
|
|
||||||
var messageType protoreflect.MessageType
|
|
||||||
lazyInit := func() {
|
|
||||||
once.Do(func() {
|
|
||||||
messageName := fd.Message().FullName()
|
|
||||||
messageType, _ = protoregistry.GlobalTypes.FindMessageByName(messageName)
|
|
||||||
if messageType == nil {
|
|
||||||
panic(fmt.Sprintf("weak message %v for field %v is not linked in", messageName, fd.FullName()))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
num := fd.Number()
|
|
||||||
return fieldInfo{
|
|
||||||
fieldDesc: fd,
|
|
||||||
has: func(p pointer) bool {
|
|
||||||
if p.IsNil() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
_, ok := p.Apply(weakOffset).WeakFields().get(num)
|
|
||||||
return ok
|
|
||||||
},
|
|
||||||
clear: func(p pointer) {
|
|
||||||
p.Apply(weakOffset).WeakFields().clear(num)
|
|
||||||
},
|
|
||||||
get: func(p pointer) protoreflect.Value {
|
|
||||||
lazyInit()
|
|
||||||
if p.IsNil() {
|
|
||||||
return protoreflect.ValueOfMessage(messageType.Zero())
|
|
||||||
}
|
|
||||||
m, ok := p.Apply(weakOffset).WeakFields().get(num)
|
|
||||||
if !ok {
|
|
||||||
return protoreflect.ValueOfMessage(messageType.Zero())
|
|
||||||
}
|
|
||||||
return protoreflect.ValueOfMessage(m.ProtoReflect())
|
|
||||||
},
|
|
||||||
set: func(p pointer, v protoreflect.Value) {
|
|
||||||
lazyInit()
|
|
||||||
m := v.Message()
|
|
||||||
if m.Descriptor() != messageType.Descriptor() {
|
|
||||||
if got, want := m.Descriptor().FullName(), messageType.Descriptor().FullName(); got != want {
|
|
||||||
panic(fmt.Sprintf("field %v has mismatching message descriptor: got %v, want %v", fd.FullName(), got, want))
|
|
||||||
}
|
|
||||||
panic(fmt.Sprintf("field %v has mismatching message descriptor: %v", fd.FullName(), m.Descriptor().FullName()))
|
|
||||||
}
|
|
||||||
p.Apply(weakOffset).WeakFields().set(num, m.Interface())
|
|
||||||
},
|
|
||||||
mutable: func(p pointer) protoreflect.Value {
|
|
||||||
lazyInit()
|
|
||||||
fs := p.Apply(weakOffset).WeakFields()
|
|
||||||
m, ok := fs.get(num)
|
|
||||||
if !ok {
|
|
||||||
m = messageType.New().Interface()
|
|
||||||
fs.set(num, m)
|
|
||||||
}
|
|
||||||
return protoreflect.ValueOfMessage(m.ProtoReflect())
|
|
||||||
},
|
|
||||||
newMessage: func() protoreflect.Message {
|
|
||||||
lazyInit()
|
|
||||||
return messageType.New()
|
|
||||||
},
|
|
||||||
newField: func() protoreflect.Value {
|
|
||||||
lazyInit()
|
|
||||||
return protoreflect.ValueOfMessage(messageType.New())
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func fieldInfoForMessage(fd protoreflect.FieldDescriptor, fs reflect.StructField, x exporter) fieldInfo {
|
func fieldInfoForMessage(fd protoreflect.FieldDescriptor, fs reflect.StructField, x exporter) fieldInfo {
|
||||||
ft := fs.Type
|
ft := fs.Type
|
||||||
conv := NewConverter(ft, fd)
|
conv := NewConverter(ft, fd)
|
||||||
|
|
|
@ -111,7 +111,6 @@ func (p pointer) StringSlice() *[]string { return (*[]string)(p.p
|
||||||
func (p pointer) Bytes() *[]byte { return (*[]byte)(p.p) }
|
func (p pointer) Bytes() *[]byte { return (*[]byte)(p.p) }
|
||||||
func (p pointer) BytesPtr() **[]byte { return (**[]byte)(p.p) }
|
func (p pointer) BytesPtr() **[]byte { return (**[]byte)(p.p) }
|
||||||
func (p pointer) BytesSlice() *[][]byte { return (*[][]byte)(p.p) }
|
func (p pointer) BytesSlice() *[][]byte { return (*[][]byte)(p.p) }
|
||||||
func (p pointer) WeakFields() *weakFields { return (*weakFields)(p.p) }
|
|
||||||
func (p pointer) Extensions() *map[int32]ExtensionField { return (*map[int32]ExtensionField)(p.p) }
|
func (p pointer) Extensions() *map[int32]ExtensionField { return (*map[int32]ExtensionField)(p.p) }
|
||||||
func (p pointer) LazyInfoPtr() **protolazy.XXX_lazyUnmarshalInfo {
|
func (p pointer) LazyInfoPtr() **protolazy.XXX_lazyUnmarshalInfo {
|
||||||
return (**protolazy.XXX_lazyUnmarshalInfo)(p.p)
|
return (**protolazy.XXX_lazyUnmarshalInfo)(p.p)
|
||||||
|
|
|
@ -211,9 +211,7 @@ func newValidationInfo(fd protoreflect.FieldDescriptor, ft reflect.Type) validat
|
||||||
switch fd.Kind() {
|
switch fd.Kind() {
|
||||||
case protoreflect.MessageKind:
|
case protoreflect.MessageKind:
|
||||||
vi.typ = validationTypeMessage
|
vi.typ = validationTypeMessage
|
||||||
if !fd.IsWeak() {
|
vi.mi = getMessageInfo(ft)
|
||||||
vi.mi = getMessageInfo(ft)
|
|
||||||
}
|
|
||||||
case protoreflect.GroupKind:
|
case protoreflect.GroupKind:
|
||||||
vi.typ = validationTypeGroup
|
vi.typ = validationTypeGroup
|
||||||
vi.mi = getMessageInfo(ft)
|
vi.mi = getMessageInfo(ft)
|
||||||
|
@ -320,26 +318,6 @@ State:
|
||||||
}
|
}
|
||||||
if f != nil {
|
if f != nil {
|
||||||
vi = f.validation
|
vi = f.validation
|
||||||
if vi.typ == validationTypeMessage && vi.mi == nil {
|
|
||||||
// Probable weak field.
|
|
||||||
//
|
|
||||||
// TODO: Consider storing the results of this lookup somewhere
|
|
||||||
// rather than recomputing it on every validation.
|
|
||||||
fd := st.mi.Desc.Fields().ByNumber(num)
|
|
||||||
if fd == nil || !fd.IsWeak() {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
messageName := fd.Message().FullName()
|
|
||||||
messageType, err := protoregistry.GlobalTypes.FindMessageByName(messageName)
|
|
||||||
switch err {
|
|
||||||
case nil:
|
|
||||||
vi.mi, _ = messageType.(*MessageInfo)
|
|
||||||
case protoregistry.NotFound:
|
|
||||||
vi.typ = validationTypeBytes
|
|
||||||
default:
|
|
||||||
return out, ValidationUnknown
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// Possible extension field.
|
// Possible extension field.
|
||||||
|
|
|
@ -1,74 +0,0 @@
|
||||||
// Copyright 2019 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 impl
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"google.golang.org/protobuf/reflect/protoreflect"
|
|
||||||
"google.golang.org/protobuf/reflect/protoregistry"
|
|
||||||
)
|
|
||||||
|
|
||||||
// weakFields adds methods to the exported WeakFields type for internal use.
|
|
||||||
//
|
|
||||||
// The exported type is an alias to an unnamed type, so methods can't be
|
|
||||||
// defined directly on it.
|
|
||||||
type weakFields WeakFields
|
|
||||||
|
|
||||||
func (w weakFields) get(num protoreflect.FieldNumber) (protoreflect.ProtoMessage, bool) {
|
|
||||||
m, ok := w[int32(num)]
|
|
||||||
return m, ok
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *weakFields) set(num protoreflect.FieldNumber, m protoreflect.ProtoMessage) {
|
|
||||||
if *w == nil {
|
|
||||||
*w = make(weakFields)
|
|
||||||
}
|
|
||||||
(*w)[int32(num)] = m
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *weakFields) clear(num protoreflect.FieldNumber) {
|
|
||||||
delete(*w, int32(num))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (Export) HasWeak(w WeakFields, num protoreflect.FieldNumber) bool {
|
|
||||||
_, ok := w[int32(num)]
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
func (Export) ClearWeak(w *WeakFields, num protoreflect.FieldNumber) {
|
|
||||||
delete(*w, int32(num))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (Export) GetWeak(w WeakFields, num protoreflect.FieldNumber, name protoreflect.FullName) protoreflect.ProtoMessage {
|
|
||||||
if m, ok := w[int32(num)]; ok {
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
mt, _ := protoregistry.GlobalTypes.FindMessageByName(name)
|
|
||||||
if mt == nil {
|
|
||||||
panic(fmt.Sprintf("message %v for weak field is not linked in", name))
|
|
||||||
}
|
|
||||||
return mt.Zero().Interface()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (Export) SetWeak(w *WeakFields, num protoreflect.FieldNumber, name protoreflect.FullName, m protoreflect.ProtoMessage) {
|
|
||||||
if m != nil {
|
|
||||||
mt, _ := protoregistry.GlobalTypes.FindMessageByName(name)
|
|
||||||
if mt == nil {
|
|
||||||
panic(fmt.Sprintf("message %v for weak field is not linked in", name))
|
|
||||||
}
|
|
||||||
if mt != m.ProtoReflect().Type() {
|
|
||||||
panic(fmt.Sprintf("invalid message type for weak field: got %T, want %T", m, mt.Zero().Interface()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if m == nil || !m.ProtoReflect().IsValid() {
|
|
||||||
delete(*w, int32(num))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if *w == nil {
|
|
||||||
*w = make(weakFields)
|
|
||||||
}
|
|
||||||
(*w)[int32(num)] = m
|
|
||||||
}
|
|
|
@ -52,7 +52,7 @@ import (
|
||||||
const (
|
const (
|
||||||
Major = 1
|
Major = 1
|
||||||
Minor = 36
|
Minor = 36
|
||||||
Patch = 4
|
Patch = 5
|
||||||
PreRelease = ""
|
PreRelease = ""
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@ import (
|
||||||
"google.golang.org/protobuf/encoding/protowire"
|
"google.golang.org/protobuf/encoding/protowire"
|
||||||
"google.golang.org/protobuf/internal/encoding/messageset"
|
"google.golang.org/protobuf/internal/encoding/messageset"
|
||||||
"google.golang.org/protobuf/internal/errors"
|
"google.golang.org/protobuf/internal/errors"
|
||||||
"google.golang.org/protobuf/internal/flags"
|
|
||||||
"google.golang.org/protobuf/internal/genid"
|
"google.golang.org/protobuf/internal/genid"
|
||||||
"google.golang.org/protobuf/internal/pragma"
|
"google.golang.org/protobuf/internal/pragma"
|
||||||
"google.golang.org/protobuf/reflect/protoreflect"
|
"google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
@ -172,10 +171,6 @@ func (o UnmarshalOptions) unmarshalMessageSlow(b []byte, m protoreflect.Message)
|
||||||
var err error
|
var err error
|
||||||
if fd == nil {
|
if fd == nil {
|
||||||
err = errUnknown
|
err = errUnknown
|
||||||
} else if flags.ProtoLegacyWeak {
|
|
||||||
if fd.IsWeak() && fd.Message().IsPlaceholder() {
|
|
||||||
err = errUnknown // weak referent is not linked in
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse the field value.
|
// Parse the field value.
|
||||||
|
|
|
@ -132,17 +132,11 @@ func (o FileOptions) New(fd *descriptorpb.FileDescriptorProto, r Resolver) (prot
|
||||||
}
|
}
|
||||||
f.L2.Imports[i].IsPublic = true
|
f.L2.Imports[i].IsPublic = true
|
||||||
}
|
}
|
||||||
for _, i := range fd.GetWeakDependency() {
|
|
||||||
if !(0 <= i && int(i) < len(f.L2.Imports)) || f.L2.Imports[i].IsWeak {
|
|
||||||
return nil, errors.New("invalid or duplicate weak import index: %d", i)
|
|
||||||
}
|
|
||||||
f.L2.Imports[i].IsWeak = true
|
|
||||||
}
|
|
||||||
imps := importSet{f.Path(): true}
|
imps := importSet{f.Path(): true}
|
||||||
for i, path := range fd.GetDependency() {
|
for i, path := range fd.GetDependency() {
|
||||||
imp := &f.L2.Imports[i]
|
imp := &f.L2.Imports[i]
|
||||||
f, err := r.FindFileByPath(path)
|
f, err := r.FindFileByPath(path)
|
||||||
if err == protoregistry.NotFound && (o.AllowUnresolvable || imp.IsWeak) {
|
if err == protoregistry.NotFound && o.AllowUnresolvable {
|
||||||
f = filedesc.PlaceholderFile(path)
|
f = filedesc.PlaceholderFile(path)
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return nil, errors.New("could not resolve import %q: %v", path, err)
|
return nil, errors.New("could not resolve import %q: %v", path, err)
|
||||||
|
|
|
@ -149,7 +149,6 @@ func (r descsByName) initFieldsFromDescriptorProto(fds []*descriptorpb.FieldDesc
|
||||||
if opts := fd.GetOptions(); opts != nil {
|
if opts := fd.GetOptions(); opts != nil {
|
||||||
opts = proto.Clone(opts).(*descriptorpb.FieldOptions)
|
opts = proto.Clone(opts).(*descriptorpb.FieldOptions)
|
||||||
f.L1.Options = func() protoreflect.ProtoMessage { return opts }
|
f.L1.Options = func() protoreflect.ProtoMessage { return opts }
|
||||||
f.L1.IsWeak = opts.GetWeak()
|
|
||||||
f.L1.IsLazy = opts.GetLazy()
|
f.L1.IsLazy = opts.GetLazy()
|
||||||
if opts.Packed != nil {
|
if opts.Packed != nil {
|
||||||
f.L1.EditionFeatures.IsPacked = opts.GetPacked()
|
f.L1.EditionFeatures.IsPacked = opts.GetPacked()
|
||||||
|
|
|
@ -43,7 +43,7 @@ func (r *resolver) resolveMessageDependencies(ms []filedesc.Message, mds []*desc
|
||||||
o.L1.Fields.List = append(o.L1.Fields.List, f)
|
o.L1.Fields.List = append(o.L1.Fields.List, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
if f.L1.Kind, f.L1.Enum, f.L1.Message, err = r.findTarget(f.Kind(), f.Parent().FullName(), partialName(fd.GetTypeName()), f.IsWeak()); err != nil {
|
if f.L1.Kind, f.L1.Enum, f.L1.Message, err = r.findTarget(f.Kind(), f.Parent().FullName(), partialName(fd.GetTypeName())); err != nil {
|
||||||
return errors.New("message field %q cannot resolve type: %v", f.FullName(), err)
|
return errors.New("message field %q cannot resolve type: %v", f.FullName(), err)
|
||||||
}
|
}
|
||||||
if f.L1.Kind == protoreflect.GroupKind && (f.IsMap() || f.IsMapEntry()) {
|
if f.L1.Kind == protoreflect.GroupKind && (f.IsMap() || f.IsMapEntry()) {
|
||||||
|
@ -73,10 +73,10 @@ func (r *resolver) resolveMessageDependencies(ms []filedesc.Message, mds []*desc
|
||||||
func (r *resolver) resolveExtensionDependencies(xs []filedesc.Extension, xds []*descriptorpb.FieldDescriptorProto) (err error) {
|
func (r *resolver) resolveExtensionDependencies(xs []filedesc.Extension, xds []*descriptorpb.FieldDescriptorProto) (err error) {
|
||||||
for i, xd := range xds {
|
for i, xd := range xds {
|
||||||
x := &xs[i]
|
x := &xs[i]
|
||||||
if x.L1.Extendee, err = r.findMessageDescriptor(x.Parent().FullName(), partialName(xd.GetExtendee()), false); err != nil {
|
if x.L1.Extendee, err = r.findMessageDescriptor(x.Parent().FullName(), partialName(xd.GetExtendee())); err != nil {
|
||||||
return errors.New("extension field %q cannot resolve extendee: %v", x.FullName(), err)
|
return errors.New("extension field %q cannot resolve extendee: %v", x.FullName(), err)
|
||||||
}
|
}
|
||||||
if x.L1.Kind, x.L2.Enum, x.L2.Message, err = r.findTarget(x.Kind(), x.Parent().FullName(), partialName(xd.GetTypeName()), false); err != nil {
|
if x.L1.Kind, x.L2.Enum, x.L2.Message, err = r.findTarget(x.Kind(), x.Parent().FullName(), partialName(xd.GetTypeName())); err != nil {
|
||||||
return errors.New("extension field %q cannot resolve type: %v", x.FullName(), err)
|
return errors.New("extension field %q cannot resolve type: %v", x.FullName(), err)
|
||||||
}
|
}
|
||||||
if xd.DefaultValue != nil {
|
if xd.DefaultValue != nil {
|
||||||
|
@ -95,11 +95,11 @@ func (r *resolver) resolveServiceDependencies(ss []filedesc.Service, sds []*desc
|
||||||
s := &ss[i]
|
s := &ss[i]
|
||||||
for j, md := range sd.GetMethod() {
|
for j, md := range sd.GetMethod() {
|
||||||
m := &s.L2.Methods.List[j]
|
m := &s.L2.Methods.List[j]
|
||||||
m.L1.Input, err = r.findMessageDescriptor(m.Parent().FullName(), partialName(md.GetInputType()), false)
|
m.L1.Input, err = r.findMessageDescriptor(m.Parent().FullName(), partialName(md.GetInputType()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("service method %q cannot resolve input: %v", m.FullName(), err)
|
return errors.New("service method %q cannot resolve input: %v", m.FullName(), err)
|
||||||
}
|
}
|
||||||
m.L1.Output, err = r.findMessageDescriptor(s.FullName(), partialName(md.GetOutputType()), false)
|
m.L1.Output, err = r.findMessageDescriptor(s.FullName(), partialName(md.GetOutputType()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("service method %q cannot resolve output: %v", m.FullName(), err)
|
return errors.New("service method %q cannot resolve output: %v", m.FullName(), err)
|
||||||
}
|
}
|
||||||
|
@ -111,16 +111,16 @@ func (r *resolver) resolveServiceDependencies(ss []filedesc.Service, sds []*desc
|
||||||
// findTarget finds an enum or message descriptor if k is an enum, message,
|
// findTarget finds an enum or message descriptor if k is an enum, message,
|
||||||
// group, or unknown. If unknown, and the name could be resolved, the kind
|
// group, or unknown. If unknown, and the name could be resolved, the kind
|
||||||
// returned kind is set based on the type of the resolved descriptor.
|
// returned kind is set based on the type of the resolved descriptor.
|
||||||
func (r *resolver) findTarget(k protoreflect.Kind, scope protoreflect.FullName, ref partialName, isWeak bool) (protoreflect.Kind, protoreflect.EnumDescriptor, protoreflect.MessageDescriptor, error) {
|
func (r *resolver) findTarget(k protoreflect.Kind, scope protoreflect.FullName, ref partialName) (protoreflect.Kind, protoreflect.EnumDescriptor, protoreflect.MessageDescriptor, error) {
|
||||||
switch k {
|
switch k {
|
||||||
case protoreflect.EnumKind:
|
case protoreflect.EnumKind:
|
||||||
ed, err := r.findEnumDescriptor(scope, ref, isWeak)
|
ed, err := r.findEnumDescriptor(scope, ref)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, nil, nil, err
|
return 0, nil, nil, err
|
||||||
}
|
}
|
||||||
return k, ed, nil, nil
|
return k, ed, nil, nil
|
||||||
case protoreflect.MessageKind, protoreflect.GroupKind:
|
case protoreflect.MessageKind, protoreflect.GroupKind:
|
||||||
md, err := r.findMessageDescriptor(scope, ref, isWeak)
|
md, err := r.findMessageDescriptor(scope, ref)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, nil, nil, err
|
return 0, nil, nil, err
|
||||||
}
|
}
|
||||||
|
@ -129,7 +129,7 @@ func (r *resolver) findTarget(k protoreflect.Kind, scope protoreflect.FullName,
|
||||||
// Handle unspecified kinds (possible with parsers that operate
|
// Handle unspecified kinds (possible with parsers that operate
|
||||||
// on a per-file basis without knowledge of dependencies).
|
// on a per-file basis without knowledge of dependencies).
|
||||||
d, err := r.findDescriptor(scope, ref)
|
d, err := r.findDescriptor(scope, ref)
|
||||||
if err == protoregistry.NotFound && (r.allowUnresolvable || isWeak) {
|
if err == protoregistry.NotFound && r.allowUnresolvable {
|
||||||
return k, filedesc.PlaceholderEnum(ref.FullName()), filedesc.PlaceholderMessage(ref.FullName()), nil
|
return k, filedesc.PlaceholderEnum(ref.FullName()), filedesc.PlaceholderMessage(ref.FullName()), nil
|
||||||
} else if err == protoregistry.NotFound {
|
} else if err == protoregistry.NotFound {
|
||||||
return 0, nil, nil, errors.New("%q not found", ref.FullName())
|
return 0, nil, nil, errors.New("%q not found", ref.FullName())
|
||||||
|
@ -206,9 +206,9 @@ func (r *resolver) findDescriptor(scope protoreflect.FullName, ref partialName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *resolver) findEnumDescriptor(scope protoreflect.FullName, ref partialName, isWeak bool) (protoreflect.EnumDescriptor, error) {
|
func (r *resolver) findEnumDescriptor(scope protoreflect.FullName, ref partialName) (protoreflect.EnumDescriptor, error) {
|
||||||
d, err := r.findDescriptor(scope, ref)
|
d, err := r.findDescriptor(scope, ref)
|
||||||
if err == protoregistry.NotFound && (r.allowUnresolvable || isWeak) {
|
if err == protoregistry.NotFound && r.allowUnresolvable {
|
||||||
return filedesc.PlaceholderEnum(ref.FullName()), nil
|
return filedesc.PlaceholderEnum(ref.FullName()), nil
|
||||||
} else if err == protoregistry.NotFound {
|
} else if err == protoregistry.NotFound {
|
||||||
return nil, errors.New("%q not found", ref.FullName())
|
return nil, errors.New("%q not found", ref.FullName())
|
||||||
|
@ -222,9 +222,9 @@ func (r *resolver) findEnumDescriptor(scope protoreflect.FullName, ref partialNa
|
||||||
return ed, nil
|
return ed, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *resolver) findMessageDescriptor(scope protoreflect.FullName, ref partialName, isWeak bool) (protoreflect.MessageDescriptor, error) {
|
func (r *resolver) findMessageDescriptor(scope protoreflect.FullName, ref partialName) (protoreflect.MessageDescriptor, error) {
|
||||||
d, err := r.findDescriptor(scope, ref)
|
d, err := r.findDescriptor(scope, ref)
|
||||||
if err == protoregistry.NotFound && (r.allowUnresolvable || isWeak) {
|
if err == protoregistry.NotFound && r.allowUnresolvable {
|
||||||
return filedesc.PlaceholderMessage(ref.FullName()), nil
|
return filedesc.PlaceholderMessage(ref.FullName()), nil
|
||||||
} else if err == protoregistry.NotFound {
|
} else if err == protoregistry.NotFound {
|
||||||
return nil, errors.New("%q not found", ref.FullName())
|
return nil, errors.New("%q not found", ref.FullName())
|
||||||
|
|
|
@ -149,12 +149,6 @@ func validateMessageDeclarations(file *filedesc.File, ms []filedesc.Message, mds
|
||||||
return errors.New("message field %q under proto3 optional semantics must be within a single element oneof", f.FullName())
|
return errors.New("message field %q under proto3 optional semantics must be within a single element oneof", f.FullName())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if f.IsWeak() && !flags.ProtoLegacyWeak {
|
|
||||||
return errors.New("message field %q is a weak field, which is a legacy proto1 feature that is no longer supported", f.FullName())
|
|
||||||
}
|
|
||||||
if f.IsWeak() && (!f.HasPresence() || !isOptionalMessage(f) || f.ContainingOneof() != nil) {
|
|
||||||
return errors.New("message field %q may only be weak for an optional message", f.FullName())
|
|
||||||
}
|
|
||||||
if f.IsPacked() && !isPackable(f) {
|
if f.IsPacked() && !isPackable(f) {
|
||||||
return errors.New("message field %q is not packable", f.FullName())
|
return errors.New("message field %q is not packable", f.FullName())
|
||||||
}
|
}
|
||||||
|
@ -199,9 +193,6 @@ func validateMessageDeclarations(file *filedesc.File, ms []filedesc.Message, mds
|
||||||
if f.Cardinality() != protoreflect.Optional {
|
if f.Cardinality() != protoreflect.Optional {
|
||||||
return errors.New("message field %q belongs in a oneof and must be optional", f.FullName())
|
return errors.New("message field %q belongs in a oneof and must be optional", f.FullName())
|
||||||
}
|
}
|
||||||
if f.IsWeak() {
|
|
||||||
return errors.New("message field %q belongs in a oneof and must not be a weak reference", f.FullName())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,9 +245,6 @@ func validateExtensionDeclarations(f *filedesc.File, xs []filedesc.Extension, xd
|
||||||
return errors.New("extension field %q has an invalid number: %d", x.FullName(), x.Number())
|
return errors.New("extension field %q has an invalid number: %d", x.FullName(), x.Number())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if xd.GetOptions().GetWeak() {
|
|
||||||
return errors.New("extension field %q cannot be a weak reference", x.FullName())
|
|
||||||
}
|
|
||||||
if x.IsPacked() && !isPackable(x) {
|
if x.IsPacked() && !isPackable(x) {
|
||||||
return errors.New("extension field %q is not packable", x.FullName())
|
return errors.New("extension field %q is not packable", x.FullName())
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,9 +32,6 @@ func ToFileDescriptorProto(file protoreflect.FileDescriptor) *descriptorpb.FileD
|
||||||
if imp.IsPublic {
|
if imp.IsPublic {
|
||||||
p.PublicDependency = append(p.PublicDependency, int32(i))
|
p.PublicDependency = append(p.PublicDependency, int32(i))
|
||||||
}
|
}
|
||||||
if imp.IsWeak {
|
|
||||||
p.WeakDependency = append(p.WeakDependency, int32(i))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for i, locs := 0, file.SourceLocations(); i < locs.Len(); i++ {
|
for i, locs := 0, file.SourceLocations(); i < locs.Len(); i++ {
|
||||||
loc := locs.Get(i)
|
loc := locs.Get(i)
|
||||||
|
|
|
@ -68,7 +68,7 @@ type Descriptor interface {
|
||||||
// dependency is not resolved, in which case only name information is known.
|
// dependency is not resolved, in which case only name information is known.
|
||||||
//
|
//
|
||||||
// Placeholder types may only be returned by the following accessors
|
// Placeholder types may only be returned by the following accessors
|
||||||
// as a result of unresolved dependencies or weak imports:
|
// as a result of unresolved dependencies:
|
||||||
//
|
//
|
||||||
// ╔═══════════════════════════════════╤═════════════════════╗
|
// ╔═══════════════════════════════════╤═════════════════════╗
|
||||||
// ║ Accessor │ Descriptor ║
|
// ║ Accessor │ Descriptor ║
|
||||||
|
@ -168,11 +168,7 @@ type FileImport struct {
|
||||||
// The current file and the imported file must be within proto package.
|
// The current file and the imported file must be within proto package.
|
||||||
IsPublic bool
|
IsPublic bool
|
||||||
|
|
||||||
// IsWeak reports whether this is a weak import, which does not impose
|
// Deprecated: support for weak fields has been removed.
|
||||||
// a direct dependency on the target file.
|
|
||||||
//
|
|
||||||
// Weak imports are a legacy proto1 feature. Equivalent behavior is
|
|
||||||
// achieved using proto2 extension fields or proto3 Any messages.
|
|
||||||
IsWeak bool
|
IsWeak bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,9 +321,7 @@ type FieldDescriptor interface {
|
||||||
// specified in the source .proto file.
|
// specified in the source .proto file.
|
||||||
HasOptionalKeyword() bool
|
HasOptionalKeyword() bool
|
||||||
|
|
||||||
// IsWeak reports whether this is a weak field, which does not impose a
|
// Deprecated: support for weak fields has been removed.
|
||||||
// direct dependency on the target type.
|
|
||||||
// If true, then Message returns a placeholder type.
|
|
||||||
IsWeak() bool
|
IsWeak() bool
|
||||||
|
|
||||||
// IsPacked reports whether repeated primitive numeric kinds should be
|
// IsPacked reports whether repeated primitive numeric kinds should be
|
||||||
|
|
|
@ -1,202 +0,0 @@
|
||||||
|
|
||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright 2014 The Kubernetes Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
|
@ -1,200 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2015 The Kubernetes Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Package args has common command-line flags for generation programs.
|
|
||||||
package args
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
goflag "flag"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"k8s.io/gengo/generator"
|
|
||||||
"k8s.io/gengo/namer"
|
|
||||||
"k8s.io/gengo/parser"
|
|
||||||
|
|
||||||
"github.com/spf13/pflag"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Default returns a defaulted GeneratorArgs. You may change the defaults
|
|
||||||
// before calling AddFlags.
|
|
||||||
func Default() *GeneratorArgs {
|
|
||||||
return &GeneratorArgs{
|
|
||||||
OutputBase: DefaultSourceTree(),
|
|
||||||
GoHeaderFilePath: filepath.Join(DefaultSourceTree(), "k8s.io/gengo/boilerplate/boilerplate.go.txt"),
|
|
||||||
GeneratedBuildTag: "ignore_autogenerated",
|
|
||||||
GeneratedByCommentTemplate: "// Code generated by GENERATOR_NAME. DO NOT EDIT.",
|
|
||||||
defaultCommandLineFlags: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GeneratorArgs has arguments that are passed to generators.
|
|
||||||
type GeneratorArgs struct {
|
|
||||||
// Which directories to parse.
|
|
||||||
InputDirs []string
|
|
||||||
|
|
||||||
// Source tree to write results to.
|
|
||||||
OutputBase string
|
|
||||||
|
|
||||||
// Package path within the source tree.
|
|
||||||
OutputPackagePath string
|
|
||||||
|
|
||||||
// Output file name.
|
|
||||||
OutputFileBaseName string
|
|
||||||
|
|
||||||
// Where to get copyright header text.
|
|
||||||
GoHeaderFilePath string
|
|
||||||
|
|
||||||
// If GeneratedByCommentTemplate is set, generate a "Code generated by" comment
|
|
||||||
// below the bloilerplate, of the format defined by this string.
|
|
||||||
// Any instances of "GENERATOR_NAME" will be replaced with the name of the code generator.
|
|
||||||
GeneratedByCommentTemplate string
|
|
||||||
|
|
||||||
// If true, only verify, don't write anything.
|
|
||||||
VerifyOnly bool
|
|
||||||
|
|
||||||
// If true, include *_test.go files
|
|
||||||
IncludeTestFiles bool
|
|
||||||
|
|
||||||
// GeneratedBuildTag is the tag used to identify code generated by execution
|
|
||||||
// of this type. Each generator should use a different tag, and different
|
|
||||||
// groups of generators (external API that depends on Kube generations) should
|
|
||||||
// keep tags distinct as well.
|
|
||||||
GeneratedBuildTag string
|
|
||||||
|
|
||||||
// Any custom arguments go here
|
|
||||||
CustomArgs interface{}
|
|
||||||
|
|
||||||
// If specified, trim the prefix from OutputPackagePath before writing files.
|
|
||||||
TrimPathPrefix string
|
|
||||||
|
|
||||||
// Whether to use default command line flags
|
|
||||||
defaultCommandLineFlags bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithoutDefaultFlagParsing disables implicit addition of command line flags and parsing.
|
|
||||||
func (g *GeneratorArgs) WithoutDefaultFlagParsing() *GeneratorArgs {
|
|
||||||
g.defaultCommandLineFlags = false
|
|
||||||
return g
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *GeneratorArgs) AddFlags(fs *pflag.FlagSet) {
|
|
||||||
fs.StringSliceVarP(&g.InputDirs, "input-dirs", "i", g.InputDirs, "Comma-separated list of import paths to get input types from.")
|
|
||||||
fs.StringVarP(&g.OutputBase, "output-base", "o", g.OutputBase, "Output base; defaults to $GOPATH/src/ or ./ if $GOPATH is not set.")
|
|
||||||
fs.StringVarP(&g.OutputPackagePath, "output-package", "p", g.OutputPackagePath, "Base package path.")
|
|
||||||
fs.StringVarP(&g.OutputFileBaseName, "output-file-base", "O", g.OutputFileBaseName, "Base name (without .go suffix) for output files.")
|
|
||||||
fs.StringVarP(&g.GoHeaderFilePath, "go-header-file", "h", g.GoHeaderFilePath, "File containing boilerplate header text. The string YEAR will be replaced with the current 4-digit year.")
|
|
||||||
fs.BoolVar(&g.VerifyOnly, "verify-only", g.VerifyOnly, "If true, only verify existing output, do not write anything.")
|
|
||||||
fs.StringVar(&g.GeneratedBuildTag, "build-tag", g.GeneratedBuildTag, "A Go build tag to use to identify files generated by this command. Should be unique.")
|
|
||||||
fs.StringVar(&g.TrimPathPrefix, "trim-path-prefix", g.TrimPathPrefix, "If set, trim the specified prefix from --output-package when generating files.")
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadGoBoilerplate loads the boilerplate file passed to --go-header-file.
|
|
||||||
func (g *GeneratorArgs) LoadGoBoilerplate() ([]byte, error) {
|
|
||||||
b, err := ioutil.ReadFile(g.GoHeaderFilePath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
b = bytes.Replace(b, []byte("YEAR"), []byte(strconv.Itoa(time.Now().UTC().Year())), -1)
|
|
||||||
|
|
||||||
if g.GeneratedByCommentTemplate != "" {
|
|
||||||
if len(b) != 0 {
|
|
||||||
b = append(b, byte('\n'))
|
|
||||||
}
|
|
||||||
generatorName := filepath.Base(os.Args[0])
|
|
||||||
// Strip the extension from the name to normalize output between *nix and Windows.
|
|
||||||
generatorName = generatorName[:len(generatorName)-len(filepath.Ext(generatorName))]
|
|
||||||
generatedByComment := strings.Replace(g.GeneratedByCommentTemplate, "GENERATOR_NAME", generatorName, -1)
|
|
||||||
s := fmt.Sprintf("%s\n\n", generatedByComment)
|
|
||||||
b = append(b, []byte(s)...)
|
|
||||||
}
|
|
||||||
return b, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewBuilder makes a new parser.Builder and populates it with the input
|
|
||||||
// directories.
|
|
||||||
func (g *GeneratorArgs) NewBuilder() (*parser.Builder, error) {
|
|
||||||
b := parser.New()
|
|
||||||
|
|
||||||
// flag for including *_test.go
|
|
||||||
b.IncludeTestFiles = g.IncludeTestFiles
|
|
||||||
|
|
||||||
// Ignore all auto-generated files.
|
|
||||||
b.AddBuildTags(g.GeneratedBuildTag)
|
|
||||||
|
|
||||||
for _, d := range g.InputDirs {
|
|
||||||
var err error
|
|
||||||
if strings.HasSuffix(d, "/...") {
|
|
||||||
err = b.AddDirRecursive(strings.TrimSuffix(d, "/..."))
|
|
||||||
} else {
|
|
||||||
err = b.AddDir(d)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("unable to add directory %q: %v", d, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return b, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DefaultSourceTree returns the /src directory of the first entry in $GOPATH.
|
|
||||||
// If $GOPATH is empty, it returns "./". Useful as a default output location.
|
|
||||||
func DefaultSourceTree() string {
|
|
||||||
paths := strings.Split(os.Getenv("GOPATH"), string(filepath.ListSeparator))
|
|
||||||
if len(paths) > 0 && len(paths[0]) > 0 {
|
|
||||||
return filepath.Join(paths[0], "src")
|
|
||||||
}
|
|
||||||
return "./"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Execute implements main().
|
|
||||||
// If you don't need any non-default behavior, use as:
|
|
||||||
// args.Default().Execute(...)
|
|
||||||
func (g *GeneratorArgs) Execute(nameSystems namer.NameSystems, defaultSystem string, pkgs func(*generator.Context, *GeneratorArgs) generator.Packages) error {
|
|
||||||
if g.defaultCommandLineFlags {
|
|
||||||
g.AddFlags(pflag.CommandLine)
|
|
||||||
pflag.CommandLine.AddGoFlagSet(goflag.CommandLine)
|
|
||||||
pflag.Parse()
|
|
||||||
}
|
|
||||||
|
|
||||||
b, err := g.NewBuilder()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Failed making a parser: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// pass through the flag on whether to include *_test.go files
|
|
||||||
b.IncludeTestFiles = g.IncludeTestFiles
|
|
||||||
|
|
||||||
c, err := generator.NewContext(b, nameSystems, defaultSystem)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Failed making a context: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.TrimPathPrefix = g.TrimPathPrefix
|
|
||||||
|
|
||||||
c.Verify = g.VerifyOnly
|
|
||||||
packages := pkgs(c, g)
|
|
||||||
if err := c.ExecutePackages(g.OutputBase, packages); err != nil {
|
|
||||||
return fmt.Errorf("Failed executing generator: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,62 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2015 The Kubernetes Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package generator
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
|
|
||||||
"k8s.io/gengo/namer"
|
|
||||||
"k8s.io/gengo/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
GolangFileType = "golang"
|
|
||||||
)
|
|
||||||
|
|
||||||
// DefaultGen implements a do-nothing Generator.
|
|
||||||
//
|
|
||||||
// It can be used to implement static content files.
|
|
||||||
type DefaultGen struct {
|
|
||||||
// OptionalName, if present, will be used for the generator's name, and
|
|
||||||
// the filename (with ".go" appended).
|
|
||||||
OptionalName string
|
|
||||||
|
|
||||||
// OptionalBody, if present, will be used as the return from the "Init"
|
|
||||||
// method. This causes it to be static content for the entire file if
|
|
||||||
// no other generator touches the file.
|
|
||||||
OptionalBody []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d DefaultGen) Name() string { return d.OptionalName }
|
|
||||||
func (d DefaultGen) Filter(*Context, *types.Type) bool { return true }
|
|
||||||
func (d DefaultGen) Namers(*Context) namer.NameSystems { return nil }
|
|
||||||
func (d DefaultGen) Imports(*Context) []string { return []string{} }
|
|
||||||
func (d DefaultGen) PackageVars(*Context) []string { return []string{} }
|
|
||||||
func (d DefaultGen) PackageConsts(*Context) []string { return []string{} }
|
|
||||||
func (d DefaultGen) GenerateType(*Context, *types.Type, io.Writer) error { return nil }
|
|
||||||
func (d DefaultGen) Filename() string { return d.OptionalName + ".go" }
|
|
||||||
func (d DefaultGen) FileType() string { return GolangFileType }
|
|
||||||
func (d DefaultGen) Finalize(*Context, io.Writer) error { return nil }
|
|
||||||
|
|
||||||
func (d DefaultGen) Init(c *Context, w io.Writer) error {
|
|
||||||
_, err := w.Write(d.OptionalBody)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
_ = Generator(DefaultGen{})
|
|
||||||
)
|
|
|
@ -1,75 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2015 The Kubernetes Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package generator
|
|
||||||
|
|
||||||
import (
|
|
||||||
"k8s.io/gengo/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
// DefaultPackage contains a default implementation of Package.
|
|
||||||
type DefaultPackage struct {
|
|
||||||
// Short name of package, used in the "package xxxx" line.
|
|
||||||
PackageName string
|
|
||||||
// Import path of the package, and the location on disk of the package.
|
|
||||||
PackagePath string
|
|
||||||
// The location of the package on disk.
|
|
||||||
Source string
|
|
||||||
|
|
||||||
// Emitted at the top of every file.
|
|
||||||
HeaderText []byte
|
|
||||||
|
|
||||||
// Emitted only for a "doc.go" file; appended to the HeaderText for
|
|
||||||
// that file.
|
|
||||||
PackageDocumentation []byte
|
|
||||||
|
|
||||||
// If non-nil, will be called on "Generators"; otherwise, the static
|
|
||||||
// list will be used. So you should set only one of these two fields.
|
|
||||||
GeneratorFunc func(*Context) []Generator
|
|
||||||
GeneratorList []Generator
|
|
||||||
|
|
||||||
// Optional; filters the types exposed to the generators.
|
|
||||||
FilterFunc func(*Context, *types.Type) bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DefaultPackage) Name() string { return d.PackageName }
|
|
||||||
func (d *DefaultPackage) Path() string { return d.PackagePath }
|
|
||||||
func (d *DefaultPackage) SourcePath() string { return d.Source }
|
|
||||||
|
|
||||||
func (d *DefaultPackage) Filter(c *Context, t *types.Type) bool {
|
|
||||||
if d.FilterFunc != nil {
|
|
||||||
return d.FilterFunc(c, t)
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DefaultPackage) Generators(c *Context) []Generator {
|
|
||||||
if d.GeneratorFunc != nil {
|
|
||||||
return d.GeneratorFunc(c)
|
|
||||||
}
|
|
||||||
return d.GeneratorList
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DefaultPackage) Header(filename string) []byte {
|
|
||||||
if filename == "doc.go" {
|
|
||||||
return append(d.HeaderText, d.PackageDocumentation...)
|
|
||||||
}
|
|
||||||
return d.HeaderText
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
_ = Package(&DefaultPackage{})
|
|
||||||
)
|
|
|
@ -1,31 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2015 The Kubernetes Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Package generator defines an interface for code generators to implement.
|
|
||||||
//
|
|
||||||
// To use this package, you'll implement the "Package" and "Generator"
|
|
||||||
// interfaces; you'll call NewContext to load up the types you want to work
|
|
||||||
// with, and then you'll call one or more of the Execute methods. See the
|
|
||||||
// interface definitions for explanations. All output will have gofmt called on
|
|
||||||
// it automatically, so you do not need to worry about generating correct
|
|
||||||
// indentation.
|
|
||||||
//
|
|
||||||
// This package also exposes SnippetWriter. SnippetWriter reduces to a minimum
|
|
||||||
// the boilerplate involved in setting up a template from go's text/template
|
|
||||||
// package. Additionally, all naming systems in the Context will be added as
|
|
||||||
// functions to the parsed template, so that they can be called directly from
|
|
||||||
// your templates!
|
|
||||||
package generator // import "k8s.io/gengo/generator"
|
|
|
@ -1,50 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2015 The Kubernetes Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package generator
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ErrorTracker tracks errors to the underlying writer, so that you can ignore
|
|
||||||
// them until you're ready to return.
|
|
||||||
type ErrorTracker struct {
|
|
||||||
io.Writer
|
|
||||||
err error
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewErrorTracker makes a new error tracker; note that it implements io.Writer.
|
|
||||||
func NewErrorTracker(w io.Writer) *ErrorTracker {
|
|
||||||
return &ErrorTracker{Writer: w}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write intercepts calls to Write.
|
|
||||||
func (et *ErrorTracker) Write(p []byte) (n int, err error) {
|
|
||||||
if et.err != nil {
|
|
||||||
return 0, et.err
|
|
||||||
}
|
|
||||||
n, err = et.Writer.Write(p)
|
|
||||||
if err != nil {
|
|
||||||
et.err = err
|
|
||||||
}
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error returns nil if no error has occurred, otherwise it returns the error.
|
|
||||||
func (et *ErrorTracker) Error() error {
|
|
||||||
return et.err
|
|
||||||
}
|
|
|
@ -1,329 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2015 The Kubernetes Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package generator
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"golang.org/x/tools/imports"
|
|
||||||
"k8s.io/gengo/namer"
|
|
||||||
"k8s.io/gengo/types"
|
|
||||||
|
|
||||||
"k8s.io/klog/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
func errs2strings(errors []error) []string {
|
|
||||||
strs := make([]string, len(errors))
|
|
||||||
for i := range errors {
|
|
||||||
strs[i] = errors[i].Error()
|
|
||||||
}
|
|
||||||
return strs
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExecutePackages runs the generators for every package in 'packages'. 'outDir'
|
|
||||||
// is the base directory in which to place all the generated packages; it
|
|
||||||
// should be a physical path on disk, not an import path. e.g.:
|
|
||||||
// /path/to/home/path/to/gopath/src/
|
|
||||||
// Each package has its import path already, this will be appended to 'outDir'.
|
|
||||||
func (c *Context) ExecutePackages(outDir string, packages Packages) error {
|
|
||||||
var errors []error
|
|
||||||
for _, p := range packages {
|
|
||||||
if err := c.ExecutePackage(outDir, p); err != nil {
|
|
||||||
errors = append(errors, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(errors) > 0 {
|
|
||||||
return fmt.Errorf("some packages had errors:\n%v\n", strings.Join(errs2strings(errors), "\n"))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type DefaultFileType struct {
|
|
||||||
Format func([]byte) ([]byte, error)
|
|
||||||
Assemble func(io.Writer, *File)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ft DefaultFileType) AssembleFile(f *File, pathname string) error {
|
|
||||||
klog.V(5).Infof("Assembling file %q", pathname)
|
|
||||||
destFile, err := os.Create(pathname)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer destFile.Close()
|
|
||||||
|
|
||||||
b := &bytes.Buffer{}
|
|
||||||
et := NewErrorTracker(b)
|
|
||||||
ft.Assemble(et, f)
|
|
||||||
if et.Error() != nil {
|
|
||||||
return et.Error()
|
|
||||||
}
|
|
||||||
if formatted, err := ft.Format(b.Bytes()); err != nil {
|
|
||||||
err = fmt.Errorf("unable to format file %q (%v).", pathname, err)
|
|
||||||
// Write the file anyway, so they can see what's going wrong and fix the generator.
|
|
||||||
if _, err2 := destFile.Write(b.Bytes()); err2 != nil {
|
|
||||||
return err2
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
} else {
|
|
||||||
_, err = destFile.Write(formatted)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ft DefaultFileType) VerifyFile(f *File, pathname string) error {
|
|
||||||
klog.V(5).Infof("Verifying file %q", pathname)
|
|
||||||
friendlyName := filepath.Join(f.PackageName, f.Name)
|
|
||||||
b := &bytes.Buffer{}
|
|
||||||
et := NewErrorTracker(b)
|
|
||||||
ft.Assemble(et, f)
|
|
||||||
if et.Error() != nil {
|
|
||||||
return et.Error()
|
|
||||||
}
|
|
||||||
formatted, err := ft.Format(b.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("unable to format the output for %q: %v", friendlyName, err)
|
|
||||||
}
|
|
||||||
existing, err := ioutil.ReadFile(pathname)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("unable to read file %q for comparison: %v", friendlyName, err)
|
|
||||||
}
|
|
||||||
if bytes.Compare(formatted, existing) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
// Be nice and find the first place where they differ
|
|
||||||
i := 0
|
|
||||||
for i < len(formatted) && i < len(existing) && formatted[i] == existing[i] {
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
eDiff, fDiff := existing[i:], formatted[i:]
|
|
||||||
if len(eDiff) > 100 {
|
|
||||||
eDiff = eDiff[:100]
|
|
||||||
}
|
|
||||||
if len(fDiff) > 100 {
|
|
||||||
fDiff = fDiff[:100]
|
|
||||||
}
|
|
||||||
return fmt.Errorf("output for %q differs; first existing/expected diff: \n %q\n %q", friendlyName, string(eDiff), string(fDiff))
|
|
||||||
}
|
|
||||||
|
|
||||||
func assembleGolangFile(w io.Writer, f *File) {
|
|
||||||
w.Write(f.Header)
|
|
||||||
fmt.Fprintf(w, "package %v\n\n", f.PackageName)
|
|
||||||
|
|
||||||
if len(f.Imports) > 0 {
|
|
||||||
fmt.Fprint(w, "import (\n")
|
|
||||||
for i := range f.Imports {
|
|
||||||
if strings.Contains(i, "\"") {
|
|
||||||
// they included quotes, or are using the
|
|
||||||
// `name "path/to/pkg"` format.
|
|
||||||
fmt.Fprintf(w, "\t%s\n", i)
|
|
||||||
} else {
|
|
||||||
fmt.Fprintf(w, "\t%q\n", i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fmt.Fprint(w, ")\n\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
if f.Vars.Len() > 0 {
|
|
||||||
fmt.Fprint(w, "var (\n")
|
|
||||||
w.Write(f.Vars.Bytes())
|
|
||||||
fmt.Fprint(w, ")\n\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
if f.Consts.Len() > 0 {
|
|
||||||
fmt.Fprint(w, "const (\n")
|
|
||||||
w.Write(f.Consts.Bytes())
|
|
||||||
fmt.Fprint(w, ")\n\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
w.Write(f.Body.Bytes())
|
|
||||||
}
|
|
||||||
|
|
||||||
func importsWrapper(src []byte) ([]byte, error) {
|
|
||||||
return imports.Process("", src, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewGolangFile() *DefaultFileType {
|
|
||||||
return &DefaultFileType{
|
|
||||||
Format: importsWrapper,
|
|
||||||
Assemble: assembleGolangFile,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// format should be one line only, and not end with \n.
|
|
||||||
func addIndentHeaderComment(b *bytes.Buffer, format string, args ...interface{}) {
|
|
||||||
if b.Len() > 0 {
|
|
||||||
fmt.Fprintf(b, "\n// "+format+"\n", args...)
|
|
||||||
} else {
|
|
||||||
fmt.Fprintf(b, "// "+format+"\n", args...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Context) filteredBy(f func(*Context, *types.Type) bool) *Context {
|
|
||||||
c2 := *c
|
|
||||||
c2.Order = []*types.Type{}
|
|
||||||
for _, t := range c.Order {
|
|
||||||
if f(c, t) {
|
|
||||||
c2.Order = append(c2.Order, t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &c2
|
|
||||||
}
|
|
||||||
|
|
||||||
// make a new context; inheret c.Namers, but add on 'namers'. In case of a name
|
|
||||||
// collision, the namer in 'namers' wins.
|
|
||||||
func (c *Context) addNameSystems(namers namer.NameSystems) *Context {
|
|
||||||
if namers == nil {
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
c2 := *c
|
|
||||||
// Copy the existing name systems so we don't corrupt a parent context
|
|
||||||
c2.Namers = namer.NameSystems{}
|
|
||||||
for k, v := range c.Namers {
|
|
||||||
c2.Namers[k] = v
|
|
||||||
}
|
|
||||||
|
|
||||||
for name, namer := range namers {
|
|
||||||
c2.Namers[name] = namer
|
|
||||||
}
|
|
||||||
return &c2
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExecutePackage executes a single package. 'outDir' is the base directory in
|
|
||||||
// which to place the package; it should be a physical path on disk, not an
|
|
||||||
// import path. e.g.: '/path/to/home/path/to/gopath/src/' The package knows its
|
|
||||||
// import path already, this will be appended to 'outDir'.
|
|
||||||
func (c *Context) ExecutePackage(outDir string, p Package) error {
|
|
||||||
path := filepath.Join(outDir, p.Path())
|
|
||||||
|
|
||||||
// When working outside of GOPATH, we typically won't want to generate the
|
|
||||||
// full path for a package. For example, if our current project's root/base
|
|
||||||
// package is github.com/foo/bar, outDir=., p.Path()=github.com/foo/bar/generated,
|
|
||||||
// then we really want to be writing files to ./generated, not ./github.com/foo/bar/generated.
|
|
||||||
// The following will trim a path prefix (github.com/foo/bar) from p.Path() to arrive at
|
|
||||||
// a relative path that works with projects not in GOPATH.
|
|
||||||
if c.TrimPathPrefix != "" {
|
|
||||||
separator := string(filepath.Separator)
|
|
||||||
if !strings.HasSuffix(c.TrimPathPrefix, separator) {
|
|
||||||
c.TrimPathPrefix += separator
|
|
||||||
}
|
|
||||||
|
|
||||||
path = strings.TrimPrefix(path, c.TrimPathPrefix)
|
|
||||||
}
|
|
||||||
klog.V(5).Infof("Processing package %q, disk location %q", p.Name(), path)
|
|
||||||
// Filter out any types the *package* doesn't care about.
|
|
||||||
packageContext := c.filteredBy(p.Filter)
|
|
||||||
os.MkdirAll(path, 0755)
|
|
||||||
files := map[string]*File{}
|
|
||||||
for _, g := range p.Generators(packageContext) {
|
|
||||||
// Filter out types the *generator* doesn't care about.
|
|
||||||
genContext := packageContext.filteredBy(g.Filter)
|
|
||||||
// Now add any extra name systems defined by this generator
|
|
||||||
genContext = genContext.addNameSystems(g.Namers(genContext))
|
|
||||||
|
|
||||||
fileType := g.FileType()
|
|
||||||
if len(fileType) == 0 {
|
|
||||||
return fmt.Errorf("generator %q must specify a file type", g.Name())
|
|
||||||
}
|
|
||||||
f := files[g.Filename()]
|
|
||||||
if f == nil {
|
|
||||||
// This is the first generator to reference this file, so start it.
|
|
||||||
f = &File{
|
|
||||||
Name: g.Filename(),
|
|
||||||
FileType: fileType,
|
|
||||||
PackageName: p.Name(),
|
|
||||||
PackagePath: p.Path(),
|
|
||||||
PackageSourcePath: p.SourcePath(),
|
|
||||||
Header: p.Header(g.Filename()),
|
|
||||||
Imports: map[string]struct{}{},
|
|
||||||
}
|
|
||||||
files[f.Name] = f
|
|
||||||
} else {
|
|
||||||
if f.FileType != g.FileType() {
|
|
||||||
return fmt.Errorf("file %q already has type %q, but generator %q wants to use type %q", f.Name, f.FileType, g.Name(), g.FileType())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if vars := g.PackageVars(genContext); len(vars) > 0 {
|
|
||||||
addIndentHeaderComment(&f.Vars, "Package-wide variables from generator %q.", g.Name())
|
|
||||||
for _, v := range vars {
|
|
||||||
if _, err := fmt.Fprintf(&f.Vars, "%s\n", v); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if consts := g.PackageConsts(genContext); len(consts) > 0 {
|
|
||||||
addIndentHeaderComment(&f.Consts, "Package-wide consts from generator %q.", g.Name())
|
|
||||||
for _, v := range consts {
|
|
||||||
if _, err := fmt.Fprintf(&f.Consts, "%s\n", v); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := genContext.executeBody(&f.Body, g); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if imports := g.Imports(genContext); len(imports) > 0 {
|
|
||||||
for _, i := range imports {
|
|
||||||
f.Imports[i] = struct{}{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var errors []error
|
|
||||||
for _, f := range files {
|
|
||||||
finalPath := filepath.Join(path, f.Name)
|
|
||||||
assembler, ok := c.FileTypes[f.FileType]
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("the file type %q registered for file %q does not exist in the context", f.FileType, f.Name)
|
|
||||||
}
|
|
||||||
var err error
|
|
||||||
if c.Verify {
|
|
||||||
err = assembler.VerifyFile(f, finalPath)
|
|
||||||
} else {
|
|
||||||
err = assembler.AssembleFile(f, finalPath)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
errors = append(errors, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(errors) > 0 {
|
|
||||||
return fmt.Errorf("errors in package %q:\n%v\n", p.Path(), strings.Join(errs2strings(errors), "\n"))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Context) executeBody(w io.Writer, generator Generator) error {
|
|
||||||
et := NewErrorTracker(w)
|
|
||||||
if err := generator.Init(c, et); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for _, t := range c.Order {
|
|
||||||
if err := generator.GenerateType(c, t, et); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := generator.Finalize(c, et); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return et.Error()
|
|
||||||
}
|
|
|
@ -1,259 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2015 The Kubernetes Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package generator
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"io"
|
|
||||||
|
|
||||||
"k8s.io/gengo/namer"
|
|
||||||
"k8s.io/gengo/parser"
|
|
||||||
"k8s.io/gengo/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Package contains the contract for generating a package.
|
|
||||||
type Package interface {
|
|
||||||
// Name returns the package short name.
|
|
||||||
Name() string
|
|
||||||
// Path returns the package import path.
|
|
||||||
Path() string
|
|
||||||
// SourcePath returns the location of the package on disk.
|
|
||||||
SourcePath() string
|
|
||||||
|
|
||||||
// Filter should return true if this package cares about this type.
|
|
||||||
// Otherwise, this type will be omitted from the type ordering for
|
|
||||||
// this package.
|
|
||||||
Filter(*Context, *types.Type) bool
|
|
||||||
|
|
||||||
// Header should return a header for the file, including comment markers.
|
|
||||||
// Useful for copyright notices and doc strings. Include an
|
|
||||||
// autogeneration notice! Do not include the "package x" line.
|
|
||||||
Header(filename string) []byte
|
|
||||||
|
|
||||||
// Generators returns the list of generators for this package. It is
|
|
||||||
// allowed for more than one generator to write to the same file.
|
|
||||||
// A Context is passed in case the list of generators depends on the
|
|
||||||
// input types.
|
|
||||||
Generators(*Context) []Generator
|
|
||||||
}
|
|
||||||
|
|
||||||
type File struct {
|
|
||||||
Name string
|
|
||||||
FileType string
|
|
||||||
PackageName string
|
|
||||||
Header []byte
|
|
||||||
PackagePath string
|
|
||||||
PackageSourcePath string
|
|
||||||
Imports map[string]struct{}
|
|
||||||
Vars bytes.Buffer
|
|
||||||
Consts bytes.Buffer
|
|
||||||
Body bytes.Buffer
|
|
||||||
}
|
|
||||||
|
|
||||||
type FileType interface {
|
|
||||||
AssembleFile(f *File, path string) error
|
|
||||||
VerifyFile(f *File, path string) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Packages is a list of packages to generate.
|
|
||||||
type Packages []Package
|
|
||||||
|
|
||||||
// Generator is the contract for anything that wants to do auto-generation.
|
|
||||||
// It's expected that the io.Writers passed to the below functions will be
|
|
||||||
// ErrorTrackers; this allows implementations to not check for io errors,
|
|
||||||
// making more readable code.
|
|
||||||
//
|
|
||||||
// The call order for the functions that take a Context is:
|
|
||||||
// 1. Filter() // Subsequent calls see only types that pass this.
|
|
||||||
// 2. Namers() // Subsequent calls see the namers provided by this.
|
|
||||||
// 3. PackageVars()
|
|
||||||
// 4. PackageConsts()
|
|
||||||
// 5. Init()
|
|
||||||
// 6. GenerateType() // Called N times, once per type in the context's Order.
|
|
||||||
// 7. Imports()
|
|
||||||
//
|
|
||||||
// You may have multiple generators for the same file.
|
|
||||||
type Generator interface {
|
|
||||||
// The name of this generator. Will be included in generated comments.
|
|
||||||
Name() string
|
|
||||||
|
|
||||||
// Filter should return true if this generator cares about this type.
|
|
||||||
// (otherwise, GenerateType will not be called.)
|
|
||||||
//
|
|
||||||
// Filter is called before any of the generator's other functions;
|
|
||||||
// subsequent calls will get a context with only the types that passed
|
|
||||||
// this filter.
|
|
||||||
Filter(*Context, *types.Type) bool
|
|
||||||
|
|
||||||
// If this generator needs special namers, return them here. These will
|
|
||||||
// override the original namers in the context if there is a collision.
|
|
||||||
// You may return nil if you don't need special names. These names will
|
|
||||||
// be available in the context passed to the rest of the generator's
|
|
||||||
// functions.
|
|
||||||
//
|
|
||||||
// A use case for this is to return a namer that tracks imports.
|
|
||||||
Namers(*Context) namer.NameSystems
|
|
||||||
|
|
||||||
// Init should write an init function, and any other content that's not
|
|
||||||
// generated per-type. (It's not intended for generator specific
|
|
||||||
// initialization! Do that when your Package constructs the
|
|
||||||
// Generators.)
|
|
||||||
Init(*Context, io.Writer) error
|
|
||||||
|
|
||||||
// Finalize should write finish up functions, and any other content that's not
|
|
||||||
// generated per-type.
|
|
||||||
Finalize(*Context, io.Writer) error
|
|
||||||
|
|
||||||
// PackageVars should emit an array of variable lines. They will be
|
|
||||||
// placed in a var ( ... ) block. There's no need to include a leading
|
|
||||||
// \t or trailing \n.
|
|
||||||
PackageVars(*Context) []string
|
|
||||||
|
|
||||||
// PackageConsts should emit an array of constant lines. They will be
|
|
||||||
// placed in a const ( ... ) block. There's no need to include a leading
|
|
||||||
// \t or trailing \n.
|
|
||||||
PackageConsts(*Context) []string
|
|
||||||
|
|
||||||
// GenerateType should emit the code for a particular type.
|
|
||||||
GenerateType(*Context, *types.Type, io.Writer) error
|
|
||||||
|
|
||||||
// Imports should return a list of necessary imports. They will be
|
|
||||||
// formatted correctly. You do not need to include quotation marks,
|
|
||||||
// return only the package name; alternatively, you can also return
|
|
||||||
// imports in the format `name "path/to/pkg"`. Imports will be called
|
|
||||||
// after Init, PackageVars, PackageConsts, and GenerateType, to allow
|
|
||||||
// you to keep track of what imports you actually need.
|
|
||||||
Imports(*Context) []string
|
|
||||||
|
|
||||||
// Preferred file name of this generator, not including a path. It is
|
|
||||||
// allowed for multiple generators to use the same filename, but it's
|
|
||||||
// up to you to make sure they don't have colliding import names.
|
|
||||||
// TODO: provide per-file import tracking, removing the requirement
|
|
||||||
// that generators coordinate..
|
|
||||||
Filename() string
|
|
||||||
|
|
||||||
// A registered file type in the context to generate this file with. If
|
|
||||||
// the FileType is not found in the context, execution will stop.
|
|
||||||
FileType() string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Context is global context for individual generators to consume.
|
|
||||||
type Context struct {
|
|
||||||
// A map from the naming system to the names for that system. E.g., you
|
|
||||||
// might have public names and several private naming systems.
|
|
||||||
Namers namer.NameSystems
|
|
||||||
|
|
||||||
// All the types, in case you want to look up something.
|
|
||||||
Universe types.Universe
|
|
||||||
|
|
||||||
// Incoming imports, i.e. packages importing the given package.
|
|
||||||
incomingImports map[string][]string
|
|
||||||
|
|
||||||
// Incoming transitive imports, i.e. the transitive closure of IncomingImports
|
|
||||||
incomingTransitiveImports map[string][]string
|
|
||||||
|
|
||||||
// All the user-specified packages. This is after recursive expansion.
|
|
||||||
Inputs []string
|
|
||||||
|
|
||||||
// The canonical ordering of the types (will be filtered by both the
|
|
||||||
// Package's and Generator's Filter methods).
|
|
||||||
Order []*types.Type
|
|
||||||
|
|
||||||
// A set of types this context can process. If this is empty or nil,
|
|
||||||
// the default "golang" filetype will be provided.
|
|
||||||
FileTypes map[string]FileType
|
|
||||||
|
|
||||||
// If true, Execute* calls will just verify that the existing output is
|
|
||||||
// correct. (You may set this after calling NewContext.)
|
|
||||||
Verify bool
|
|
||||||
|
|
||||||
// Allows generators to add packages at runtime.
|
|
||||||
builder *parser.Builder
|
|
||||||
|
|
||||||
// If specified, trim the prefix from a package's path before writing files.
|
|
||||||
TrimPathPrefix string
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewContext generates a context from the given builder, naming systems, and
|
|
||||||
// the naming system you wish to construct the canonical ordering from.
|
|
||||||
func NewContext(b *parser.Builder, nameSystems namer.NameSystems, canonicalOrderName string) (*Context, error) {
|
|
||||||
universe, err := b.FindTypes()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
c := &Context{
|
|
||||||
Namers: namer.NameSystems{},
|
|
||||||
Universe: universe,
|
|
||||||
Inputs: b.FindPackages(),
|
|
||||||
FileTypes: map[string]FileType{
|
|
||||||
GolangFileType: NewGolangFile(),
|
|
||||||
},
|
|
||||||
builder: b,
|
|
||||||
}
|
|
||||||
|
|
||||||
for name, systemNamer := range nameSystems {
|
|
||||||
c.Namers[name] = systemNamer
|
|
||||||
if name == canonicalOrderName {
|
|
||||||
orderer := namer.Orderer{Namer: systemNamer}
|
|
||||||
c.Order = orderer.OrderUniverse(universe)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return c, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// IncomingImports returns the incoming imports for each package. The map is lazily computed.
|
|
||||||
func (ctxt *Context) IncomingImports() map[string][]string {
|
|
||||||
if ctxt.incomingImports == nil {
|
|
||||||
incoming := map[string][]string{}
|
|
||||||
for _, pkg := range ctxt.Universe {
|
|
||||||
for imp := range pkg.Imports {
|
|
||||||
incoming[imp] = append(incoming[imp], pkg.Path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ctxt.incomingImports = incoming
|
|
||||||
}
|
|
||||||
return ctxt.incomingImports
|
|
||||||
}
|
|
||||||
|
|
||||||
// TransitiveIncomingImports returns the transitive closure of the incoming imports for each package.
|
|
||||||
// The map is lazily computed.
|
|
||||||
func (ctxt *Context) TransitiveIncomingImports() map[string][]string {
|
|
||||||
if ctxt.incomingTransitiveImports == nil {
|
|
||||||
ctxt.incomingTransitiveImports = transitiveClosure(ctxt.IncomingImports())
|
|
||||||
}
|
|
||||||
return ctxt.incomingTransitiveImports
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddDir adds a Go package to the context. The specified path must be a single
|
|
||||||
// go package import path. GOPATH, GOROOT, and the location of your go binary
|
|
||||||
// (`which go`) will all be searched, in the normal Go fashion.
|
|
||||||
// Deprecated. Please use AddDirectory.
|
|
||||||
func (ctxt *Context) AddDir(path string) error {
|
|
||||||
ctxt.incomingImports = nil
|
|
||||||
ctxt.incomingTransitiveImports = nil
|
|
||||||
return ctxt.builder.AddDirTo(path, &ctxt.Universe)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddDirectory adds a Go package to the context. The specified path must be a
|
|
||||||
// single go package import path. GOPATH, GOROOT, and the location of your go
|
|
||||||
// binary (`which go`) will all be searched, in the normal Go fashion.
|
|
||||||
func (ctxt *Context) AddDirectory(path string) (*types.Package, error) {
|
|
||||||
ctxt.incomingImports = nil
|
|
||||||
ctxt.incomingTransitiveImports = nil
|
|
||||||
return ctxt.builder.AddDirectoryTo(path, &ctxt.Universe)
|
|
||||||
}
|
|
|
@ -1,89 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2015 The Kubernetes Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package generator
|
|
||||||
|
|
||||||
import (
|
|
||||||
"go/token"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"k8s.io/klog/v2"
|
|
||||||
|
|
||||||
"k8s.io/gengo/namer"
|
|
||||||
"k8s.io/gengo/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewImportTrackerForPackage creates a new import tracker which is aware
|
|
||||||
// of a generator's output package. The tracker will not add import lines
|
|
||||||
// when symbols or types are added from the same package, and LocalNameOf
|
|
||||||
// will return empty string for the output package.
|
|
||||||
//
|
|
||||||
// e.g.:
|
|
||||||
//
|
|
||||||
// tracker := NewImportTrackerForPackage("bar.com/pkg/foo")
|
|
||||||
// tracker.AddSymbol(types.Name{"bar.com/pkg/foo.MyType"})
|
|
||||||
// tracker.AddSymbol(types.Name{"bar.com/pkg/baz.MyType"})
|
|
||||||
// tracker.AddSymbol(types.Name{"bar.com/pkg/baz/baz.MyType"})
|
|
||||||
//
|
|
||||||
// tracker.LocalNameOf("bar.com/pkg/foo") -> ""
|
|
||||||
// tracker.LocalNameOf("bar.com/pkg/baz") -> "baz"
|
|
||||||
// tracker.LocalNameOf("bar.com/pkg/baz/baz") -> "bazbaz"
|
|
||||||
// tracker.ImportLines() -> {`baz "bar.com/pkg/baz"`, `bazbaz "bar.com/pkg/baz/baz"`}
|
|
||||||
func NewImportTrackerForPackage(local string, typesToAdd ...*types.Type) *namer.DefaultImportTracker {
|
|
||||||
tracker := namer.NewDefaultImportTracker(types.Name{Package: local})
|
|
||||||
tracker.IsInvalidType = func(*types.Type) bool { return false }
|
|
||||||
tracker.LocalName = func(name types.Name) string { return golangTrackerLocalName(&tracker, name) }
|
|
||||||
tracker.PrintImport = func(path, name string) string { return name + " \"" + path + "\"" }
|
|
||||||
|
|
||||||
tracker.AddTypes(typesToAdd...)
|
|
||||||
return &tracker
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewImportTracker(typesToAdd ...*types.Type) *namer.DefaultImportTracker {
|
|
||||||
return NewImportTrackerForPackage("", typesToAdd...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func golangTrackerLocalName(tracker namer.ImportTracker, t types.Name) string {
|
|
||||||
path := t.Package
|
|
||||||
|
|
||||||
// Using backslashes in package names causes gengo to produce Go code which
|
|
||||||
// will not compile with the gc compiler. See the comment on GoSeperator.
|
|
||||||
if strings.ContainsRune(path, '\\') {
|
|
||||||
klog.Warningf("Warning: backslash used in import path '%v', this is unsupported.\n", path)
|
|
||||||
}
|
|
||||||
|
|
||||||
dirs := strings.Split(path, namer.GoSeperator)
|
|
||||||
for n := len(dirs) - 1; n >= 0; n-- {
|
|
||||||
// follow kube convention of not having anything between directory names
|
|
||||||
name := strings.Join(dirs[n:], "")
|
|
||||||
name = strings.Replace(name, "_", "", -1)
|
|
||||||
// These characters commonly appear in import paths for go
|
|
||||||
// packages, but aren't legal go names. So we'll sanitize.
|
|
||||||
name = strings.Replace(name, ".", "", -1)
|
|
||||||
name = strings.Replace(name, "-", "", -1)
|
|
||||||
if _, found := tracker.PathOf(name); found {
|
|
||||||
// This name collides with some other package
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the import name is a Go keyword, prefix with an underscore.
|
|
||||||
if token.Lookup(name).IsKeyword() {
|
|
||||||
name = "_" + name
|
|
||||||
}
|
|
||||||
return name
|
|
||||||
}
|
|
||||||
panic("can't find import for " + path)
|
|
||||||
}
|
|
|
@ -1,154 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2015 The Kubernetes Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package generator
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"runtime"
|
|
||||||
"text/template"
|
|
||||||
)
|
|
||||||
|
|
||||||
// SnippetWriter is an attempt to make the template library usable.
|
|
||||||
// Methods are chainable, and you don't have to check Error() until you're all
|
|
||||||
// done.
|
|
||||||
type SnippetWriter struct {
|
|
||||||
w io.Writer
|
|
||||||
context *Context
|
|
||||||
// Left & right delimiters. text/template defaults to "{{" and "}}"
|
|
||||||
// which is totally unusable for go code based templates.
|
|
||||||
left, right string
|
|
||||||
funcMap template.FuncMap
|
|
||||||
err error
|
|
||||||
}
|
|
||||||
|
|
||||||
// w is the destination; left and right are the delimiters; @ and $ are both
|
|
||||||
// reasonable choices.
|
|
||||||
//
|
|
||||||
// c is used to make a function for every naming system, to which you can pass
|
|
||||||
// a type and get the corresponding name.
|
|
||||||
func NewSnippetWriter(w io.Writer, c *Context, left, right string) *SnippetWriter {
|
|
||||||
sw := &SnippetWriter{
|
|
||||||
w: w,
|
|
||||||
context: c,
|
|
||||||
left: left,
|
|
||||||
right: right,
|
|
||||||
funcMap: template.FuncMap{},
|
|
||||||
}
|
|
||||||
for name, namer := range c.Namers {
|
|
||||||
sw.funcMap[name] = namer.Name
|
|
||||||
}
|
|
||||||
return sw
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do parses format and runs args through it. You can have arbitrary logic in
|
|
||||||
// the format (see the text/template documentation), but consider running many
|
|
||||||
// short templates with ordinary go logic in between--this may be more
|
|
||||||
// readable. Do is chainable. Any error causes every other call to do to be
|
|
||||||
// ignored, and the error will be returned by Error(). So you can check it just
|
|
||||||
// once, at the end of your function.
|
|
||||||
//
|
|
||||||
// 'args' can be quite literally anything; read the text/template documentation
|
|
||||||
// for details. Maps and structs work particularly nicely. Conveniently, the
|
|
||||||
// types package is designed to have structs that are easily referencable from
|
|
||||||
// the template language.
|
|
||||||
//
|
|
||||||
// Example:
|
|
||||||
//
|
|
||||||
// sw := generator.NewSnippetWriter(outBuffer, context, "$", "$")
|
|
||||||
// sw.Do(`The public type name is: $.type|public$`, map[string]interface{}{"type": t})
|
|
||||||
// return sw.Error()
|
|
||||||
//
|
|
||||||
// Where:
|
|
||||||
// * "$" starts a template directive
|
|
||||||
// * "." references the entire thing passed as args
|
|
||||||
// * "type" therefore sees a map and looks up the key "type"
|
|
||||||
// * "|" means "pass the thing on the left to the thing on the right"
|
|
||||||
// * "public" is the name of a naming system, so the SnippetWriter has given
|
|
||||||
// the template a function called "public" that takes a *types.Type and
|
|
||||||
// returns the naming system's name. E.g., if the type is "string" this might
|
|
||||||
// return "String".
|
|
||||||
// * the second "$" ends the template directive.
|
|
||||||
//
|
|
||||||
// The map is actually not necessary. The below does the same thing:
|
|
||||||
//
|
|
||||||
// sw.Do(`The public type name is: $.|public$`, t)
|
|
||||||
//
|
|
||||||
// You may or may not find it more readable to use the map with a descriptive
|
|
||||||
// key, but if you want to pass more than one arg, the map or a custom struct
|
|
||||||
// becomes a requirement. You can do arbitrary logic inside these templates,
|
|
||||||
// but you should consider doing the logic in go and stitching them together
|
|
||||||
// for the sake of your readers.
|
|
||||||
//
|
|
||||||
// TODO: Change Do() to optionally take a list of pairs of parameters (key, value)
|
|
||||||
// and have it construct a combined map with that and args.
|
|
||||||
func (s *SnippetWriter) Do(format string, args interface{}) *SnippetWriter {
|
|
||||||
if s.err != nil {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
// Name the template by source file:line so it can be found when
|
|
||||||
// there's an error.
|
|
||||||
_, file, line, _ := runtime.Caller(1)
|
|
||||||
tmpl, err := template.
|
|
||||||
New(fmt.Sprintf("%s:%d", file, line)).
|
|
||||||
Delims(s.left, s.right).
|
|
||||||
Funcs(s.funcMap).
|
|
||||||
Parse(format)
|
|
||||||
if err != nil {
|
|
||||||
s.err = err
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
err = tmpl.Execute(s.w, args)
|
|
||||||
if err != nil {
|
|
||||||
s.err = err
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// Args exists to make it convenient to construct arguments for
|
|
||||||
// SnippetWriter.Do.
|
|
||||||
type Args map[interface{}]interface{}
|
|
||||||
|
|
||||||
// With makes a copy of a and adds the given key, value pair.
|
|
||||||
func (a Args) With(key, value interface{}) Args {
|
|
||||||
a2 := Args{key: value}
|
|
||||||
for k, v := range a {
|
|
||||||
a2[k] = v
|
|
||||||
}
|
|
||||||
return a2
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithArgs makes a copy of a and adds the given arguments.
|
|
||||||
func (a Args) WithArgs(rhs Args) Args {
|
|
||||||
a2 := Args{}
|
|
||||||
for k, v := range rhs {
|
|
||||||
a2[k] = v
|
|
||||||
}
|
|
||||||
for k, v := range a {
|
|
||||||
a2[k] = v
|
|
||||||
}
|
|
||||||
return a2
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SnippetWriter) Out() io.Writer {
|
|
||||||
return s.w
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error returns any encountered error.
|
|
||||||
func (s *SnippetWriter) Error() error {
|
|
||||||
return s.err
|
|
||||||
}
|
|
|
@ -1,65 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2019 The Kubernetes Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package generator
|
|
||||||
|
|
||||||
import "sort"
|
|
||||||
|
|
||||||
type edge struct {
|
|
||||||
from string
|
|
||||||
to string
|
|
||||||
}
|
|
||||||
|
|
||||||
func transitiveClosure(in map[string][]string) map[string][]string {
|
|
||||||
adj := make(map[edge]bool)
|
|
||||||
imports := make(map[string]struct{})
|
|
||||||
for from, tos := range in {
|
|
||||||
for _, to := range tos {
|
|
||||||
adj[edge{from, to}] = true
|
|
||||||
imports[to] = struct{}{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Warshal's algorithm
|
|
||||||
for k := range in {
|
|
||||||
for i := range in {
|
|
||||||
if !adj[edge{i, k}] {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for j := range imports {
|
|
||||||
if adj[edge{i, j}] {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if adj[edge{k, j}] {
|
|
||||||
adj[edge{i, j}] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out := make(map[string][]string, len(in))
|
|
||||||
for i := range in {
|
|
||||||
for j := range imports {
|
|
||||||
if adj[edge{i, j}] {
|
|
||||||
out[i] = append(out[i], j)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sort.Strings(out[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
return out
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2015 The Kubernetes Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Package namer has support for making different type naming systems.
|
|
||||||
//
|
|
||||||
// This is because sometimes you want to refer to the literal type, sometimes
|
|
||||||
// you want to make a name for the thing you're generating, and you want to
|
|
||||||
// make the name based on the type. For example, if you have `type foo string`,
|
|
||||||
// you want to be able to generate something like `func FooPrinter(f *foo) {
|
|
||||||
// Print(string(*f)) }`; that is, you want to refer to a public name, a literal
|
|
||||||
// name, and the underlying literal name.
|
|
||||||
//
|
|
||||||
// This package supports the idea of a "Namer" and a set of "NameSystems" to
|
|
||||||
// support these use cases.
|
|
||||||
//
|
|
||||||
// Additionally, a "RawNamer" can optionally keep track of what needs to be
|
|
||||||
// imported.
|
|
||||||
package namer // import "k8s.io/gengo/namer"
|
|
|
@ -1,121 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2015 The Kubernetes Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package namer
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sort"
|
|
||||||
|
|
||||||
"k8s.io/gengo/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ImportTracker may be passed to a namer.RawNamer, to track the imports needed
|
|
||||||
// for the types it names.
|
|
||||||
//
|
|
||||||
// TODO: pay attention to the package name (instead of renaming every package).
|
|
||||||
type DefaultImportTracker struct {
|
|
||||||
pathToName map[string]string
|
|
||||||
// forbidden names are in here. (e.g. "go" is a directory in which
|
|
||||||
// there is code, but "go" is not a legal name for a package, so we put
|
|
||||||
// it here to prevent us from naming any package "go")
|
|
||||||
nameToPath map[string]string
|
|
||||||
local types.Name
|
|
||||||
|
|
||||||
// Returns true if a given types is an invalid type and should be ignored.
|
|
||||||
IsInvalidType func(*types.Type) bool
|
|
||||||
// Returns the final local name for the given name
|
|
||||||
LocalName func(types.Name) string
|
|
||||||
// Returns the "import" line for a given (path, name).
|
|
||||||
PrintImport func(string, string) string
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewDefaultImportTracker(local types.Name) DefaultImportTracker {
|
|
||||||
return DefaultImportTracker{
|
|
||||||
pathToName: map[string]string{},
|
|
||||||
nameToPath: map[string]string{},
|
|
||||||
local: local,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tracker *DefaultImportTracker) AddTypes(types ...*types.Type) {
|
|
||||||
for _, t := range types {
|
|
||||||
tracker.AddType(t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func (tracker *DefaultImportTracker) AddSymbol(symbol types.Name) {
|
|
||||||
if tracker.local.Package == symbol.Package {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(symbol.Package) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
path := symbol.Path
|
|
||||||
if len(path) == 0 {
|
|
||||||
path = symbol.Package
|
|
||||||
}
|
|
||||||
if _, ok := tracker.pathToName[path]; ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
name := tracker.LocalName(symbol)
|
|
||||||
tracker.nameToPath[name] = path
|
|
||||||
tracker.pathToName[path] = name
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tracker *DefaultImportTracker) AddType(t *types.Type) {
|
|
||||||
if tracker.local.Package == t.Name.Package {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if tracker.IsInvalidType(t) {
|
|
||||||
if t.Kind == types.Builtin {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if _, ok := tracker.nameToPath[t.Name.Package]; !ok {
|
|
||||||
tracker.nameToPath[t.Name.Package] = ""
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
tracker.AddSymbol(t.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tracker *DefaultImportTracker) ImportLines() []string {
|
|
||||||
importPaths := []string{}
|
|
||||||
for path := range tracker.pathToName {
|
|
||||||
importPaths = append(importPaths, path)
|
|
||||||
}
|
|
||||||
sort.Strings(importPaths)
|
|
||||||
out := []string{}
|
|
||||||
for _, path := range importPaths {
|
|
||||||
out = append(out, tracker.PrintImport(path, tracker.pathToName[path]))
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// LocalNameOf returns the name you would use to refer to the package at the
|
|
||||||
// specified path within the body of a file.
|
|
||||||
func (tracker *DefaultImportTracker) LocalNameOf(path string) string {
|
|
||||||
return tracker.pathToName[path]
|
|
||||||
}
|
|
||||||
|
|
||||||
// PathOf returns the path that a given localName is referring to within the
|
|
||||||
// body of a file.
|
|
||||||
func (tracker *DefaultImportTracker) PathOf(localName string) (string, bool) {
|
|
||||||
name, ok := tracker.nameToPath[localName]
|
|
||||||
return name, ok
|
|
||||||
}
|
|
|
@ -1,395 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2015 The Kubernetes Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package namer
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"path/filepath"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"k8s.io/gengo/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// GoSeperator is used to split go import paths.
|
|
||||||
// Forward slash is used instead of filepath.Seperator because it is the
|
|
||||||
// only universally-accepted path delimiter and the only delimiter not
|
|
||||||
// potentially forbidden by Go compilers. (In particular gc does not allow
|
|
||||||
// the use of backslashes in import paths.)
|
|
||||||
// See https://golang.org/ref/spec#Import_declarations.
|
|
||||||
// See also https://github.com/kubernetes/gengo/issues/83#issuecomment-367040772.
|
|
||||||
GoSeperator = "/"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Returns whether a name is a private Go name.
|
|
||||||
func IsPrivateGoName(name string) bool {
|
|
||||||
return len(name) == 0 || strings.ToLower(name[:1]) == name[:1]
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewPublicNamer is a helper function that returns a namer that makes
|
|
||||||
// CamelCase names. See the NameStrategy struct for an explanation of the
|
|
||||||
// arguments to this constructor.
|
|
||||||
func NewPublicNamer(prependPackageNames int, ignoreWords ...string) *NameStrategy {
|
|
||||||
n := &NameStrategy{
|
|
||||||
Join: Joiner(IC, IC),
|
|
||||||
IgnoreWords: map[string]bool{},
|
|
||||||
PrependPackageNames: prependPackageNames,
|
|
||||||
}
|
|
||||||
for _, w := range ignoreWords {
|
|
||||||
n.IgnoreWords[w] = true
|
|
||||||
}
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewPrivateNamer is a helper function that returns a namer that makes
|
|
||||||
// camelCase names. See the NameStrategy struct for an explanation of the
|
|
||||||
// arguments to this constructor.
|
|
||||||
func NewPrivateNamer(prependPackageNames int, ignoreWords ...string) *NameStrategy {
|
|
||||||
n := &NameStrategy{
|
|
||||||
Join: Joiner(IL, IC),
|
|
||||||
IgnoreWords: map[string]bool{},
|
|
||||||
PrependPackageNames: prependPackageNames,
|
|
||||||
}
|
|
||||||
for _, w := range ignoreWords {
|
|
||||||
n.IgnoreWords[w] = true
|
|
||||||
}
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewRawNamer will return a Namer that makes a name by which you would
|
|
||||||
// directly refer to a type, optionally keeping track of the import paths
|
|
||||||
// necessary to reference the names it provides. Tracker may be nil.
|
|
||||||
// The 'pkg' is the full package name, in which the Namer is used - all
|
|
||||||
// types from that package will be referenced by just type name without
|
|
||||||
// referencing the package.
|
|
||||||
//
|
|
||||||
// For example, if the type is map[string]int, a raw namer will literally
|
|
||||||
// return "map[string]int".
|
|
||||||
//
|
|
||||||
// Or if the type, in package foo, is "type Bar struct { ... }", then the raw
|
|
||||||
// namer will return "foo.Bar" as the name of the type, and if 'tracker' was
|
|
||||||
// not nil, will record that package foo needs to be imported.
|
|
||||||
func NewRawNamer(pkg string, tracker ImportTracker) *rawNamer {
|
|
||||||
return &rawNamer{pkg: pkg, tracker: tracker}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Names is a map from Type to name, as defined by some Namer.
|
|
||||||
type Names map[*types.Type]string
|
|
||||||
|
|
||||||
// Namer takes a type, and assigns a name.
|
|
||||||
//
|
|
||||||
// The purpose of this complexity is so that you can assign coherent
|
|
||||||
// side-by-side systems of names for the types. For example, you might want a
|
|
||||||
// public interface, a private implementation struct, and also to reference
|
|
||||||
// literally the type name.
|
|
||||||
//
|
|
||||||
// Note that it is safe to call your own Name() function recursively to find
|
|
||||||
// the names of keys, elements, etc. This is because anonymous types can't have
|
|
||||||
// cycles in their names, and named types don't require the sort of recursion
|
|
||||||
// that would be problematic.
|
|
||||||
type Namer interface {
|
|
||||||
Name(*types.Type) string
|
|
||||||
}
|
|
||||||
|
|
||||||
// NameSystems is a map of a system name to a namer for that system.
|
|
||||||
type NameSystems map[string]Namer
|
|
||||||
|
|
||||||
// NameStrategy is a general Namer. The easiest way to use it is to copy the
|
|
||||||
// Public/PrivateNamer variables, and modify the members you wish to change.
|
|
||||||
//
|
|
||||||
// The Name method produces a name for the given type, of the forms:
|
|
||||||
// Anonymous types: <Prefix><Type description><Suffix>
|
|
||||||
// Named types: <Prefix><Optional Prepended Package name(s)><Original name><Suffix>
|
|
||||||
//
|
|
||||||
// In all cases, every part of the name is run through the capitalization
|
|
||||||
// functions.
|
|
||||||
//
|
|
||||||
// The IgnoreWords map can be set if you have directory names that are
|
|
||||||
// semantically meaningless for naming purposes, e.g. "proto".
|
|
||||||
//
|
|
||||||
// Prefix and Suffix can be used to disambiguate parallel systems of type
|
|
||||||
// names. For example, if you want to generate an interface and an
|
|
||||||
// implementation, you might want to suffix one with "Interface" and the other
|
|
||||||
// with "Implementation". Another common use-- if you want to generate private
|
|
||||||
// types, and one of your source types could be "string", you can't use the
|
|
||||||
// default lowercase private namer. You'll have to add a suffix or prefix.
|
|
||||||
type NameStrategy struct {
|
|
||||||
Prefix, Suffix string
|
|
||||||
Join func(pre string, parts []string, post string) string
|
|
||||||
|
|
||||||
// Add non-meaningful package directory names here (e.g. "proto") and
|
|
||||||
// they will be ignored.
|
|
||||||
IgnoreWords map[string]bool
|
|
||||||
|
|
||||||
// If > 0, prepend exactly that many package directory names (or as
|
|
||||||
// many as there are). Package names listed in "IgnoreWords" will be
|
|
||||||
// ignored.
|
|
||||||
//
|
|
||||||
// For example, if Ignore words lists "proto" and type Foo is in
|
|
||||||
// pkg/server/frobbing/proto, then a value of 1 will give a type name
|
|
||||||
// of FrobbingFoo, 2 gives ServerFrobbingFoo, etc.
|
|
||||||
PrependPackageNames int
|
|
||||||
|
|
||||||
// A cache of names thus far assigned by this namer.
|
|
||||||
Names
|
|
||||||
}
|
|
||||||
|
|
||||||
// IC ensures the first character is uppercase.
|
|
||||||
func IC(in string) string {
|
|
||||||
if in == "" {
|
|
||||||
return in
|
|
||||||
}
|
|
||||||
return strings.ToUpper(in[:1]) + in[1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
// IL ensures the first character is lowercase.
|
|
||||||
func IL(in string) string {
|
|
||||||
if in == "" {
|
|
||||||
return in
|
|
||||||
}
|
|
||||||
return strings.ToLower(in[:1]) + in[1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Joiner lets you specify functions that preprocess the various components of
|
|
||||||
// a name before joining them. You can construct e.g. camelCase or CamelCase or
|
|
||||||
// any other way of joining words. (See the IC and IL convenience functions.)
|
|
||||||
func Joiner(first, others func(string) string) func(pre string, in []string, post string) string {
|
|
||||||
return func(pre string, in []string, post string) string {
|
|
||||||
tmp := []string{others(pre)}
|
|
||||||
for i := range in {
|
|
||||||
tmp = append(tmp, others(in[i]))
|
|
||||||
}
|
|
||||||
tmp = append(tmp, others(post))
|
|
||||||
return first(strings.Join(tmp, ""))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ns *NameStrategy) removePrefixAndSuffix(s string) string {
|
|
||||||
// The join function may have changed capitalization.
|
|
||||||
lowerIn := strings.ToLower(s)
|
|
||||||
lowerP := strings.ToLower(ns.Prefix)
|
|
||||||
lowerS := strings.ToLower(ns.Suffix)
|
|
||||||
b, e := 0, len(s)
|
|
||||||
if strings.HasPrefix(lowerIn, lowerP) {
|
|
||||||
b = len(ns.Prefix)
|
|
||||||
}
|
|
||||||
if strings.HasSuffix(lowerIn, lowerS) {
|
|
||||||
e -= len(ns.Suffix)
|
|
||||||
}
|
|
||||||
return s[b:e]
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
importPathNameSanitizer = strings.NewReplacer("-", "_", ".", "")
|
|
||||||
)
|
|
||||||
|
|
||||||
// filters out unwanted directory names and sanitizes remaining names.
|
|
||||||
func (ns *NameStrategy) filterDirs(path string) []string {
|
|
||||||
allDirs := strings.Split(path, GoSeperator)
|
|
||||||
dirs := make([]string, 0, len(allDirs))
|
|
||||||
for _, p := range allDirs {
|
|
||||||
if ns.IgnoreWords == nil || !ns.IgnoreWords[p] {
|
|
||||||
dirs = append(dirs, importPathNameSanitizer.Replace(p))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return dirs
|
|
||||||
}
|
|
||||||
|
|
||||||
// See the comment on NameStrategy.
|
|
||||||
func (ns *NameStrategy) Name(t *types.Type) string {
|
|
||||||
if ns.Names == nil {
|
|
||||||
ns.Names = Names{}
|
|
||||||
}
|
|
||||||
if s, ok := ns.Names[t]; ok {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
if t.Name.Package != "" {
|
|
||||||
dirs := append(ns.filterDirs(t.Name.Package), t.Name.Name)
|
|
||||||
i := ns.PrependPackageNames + 1
|
|
||||||
dn := len(dirs)
|
|
||||||
if i > dn {
|
|
||||||
i = dn
|
|
||||||
}
|
|
||||||
name := ns.Join(ns.Prefix, dirs[dn-i:], ns.Suffix)
|
|
||||||
ns.Names[t] = name
|
|
||||||
return name
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only anonymous types remain.
|
|
||||||
var name string
|
|
||||||
switch t.Kind {
|
|
||||||
case types.Builtin:
|
|
||||||
name = ns.Join(ns.Prefix, []string{t.Name.Name}, ns.Suffix)
|
|
||||||
case types.Map:
|
|
||||||
name = ns.Join(ns.Prefix, []string{
|
|
||||||
"Map",
|
|
||||||
ns.removePrefixAndSuffix(ns.Name(t.Key)),
|
|
||||||
"To",
|
|
||||||
ns.removePrefixAndSuffix(ns.Name(t.Elem)),
|
|
||||||
}, ns.Suffix)
|
|
||||||
case types.Slice:
|
|
||||||
name = ns.Join(ns.Prefix, []string{
|
|
||||||
"Slice",
|
|
||||||
ns.removePrefixAndSuffix(ns.Name(t.Elem)),
|
|
||||||
}, ns.Suffix)
|
|
||||||
case types.Array:
|
|
||||||
name = ns.Join(ns.Prefix, []string{
|
|
||||||
"Array",
|
|
||||||
ns.removePrefixAndSuffix(fmt.Sprintf("%d", t.Len)),
|
|
||||||
ns.removePrefixAndSuffix(ns.Name(t.Elem)),
|
|
||||||
}, ns.Suffix)
|
|
||||||
case types.Pointer:
|
|
||||||
name = ns.Join(ns.Prefix, []string{
|
|
||||||
"Pointer",
|
|
||||||
ns.removePrefixAndSuffix(ns.Name(t.Elem)),
|
|
||||||
}, ns.Suffix)
|
|
||||||
case types.Struct:
|
|
||||||
names := []string{"Struct"}
|
|
||||||
for _, m := range t.Members {
|
|
||||||
names = append(names, ns.removePrefixAndSuffix(ns.Name(m.Type)))
|
|
||||||
}
|
|
||||||
name = ns.Join(ns.Prefix, names, ns.Suffix)
|
|
||||||
case types.Chan:
|
|
||||||
name = ns.Join(ns.Prefix, []string{
|
|
||||||
"Chan",
|
|
||||||
ns.removePrefixAndSuffix(ns.Name(t.Elem)),
|
|
||||||
}, ns.Suffix)
|
|
||||||
case types.Interface:
|
|
||||||
// TODO: add to name test
|
|
||||||
names := []string{"Interface"}
|
|
||||||
for _, m := range t.Methods {
|
|
||||||
// TODO: include function signature
|
|
||||||
names = append(names, m.Name.Name)
|
|
||||||
}
|
|
||||||
name = ns.Join(ns.Prefix, names, ns.Suffix)
|
|
||||||
case types.Func:
|
|
||||||
// TODO: add to name test
|
|
||||||
parts := []string{"Func"}
|
|
||||||
for _, pt := range t.Signature.Parameters {
|
|
||||||
parts = append(parts, ns.removePrefixAndSuffix(ns.Name(pt)))
|
|
||||||
}
|
|
||||||
parts = append(parts, "Returns")
|
|
||||||
for _, rt := range t.Signature.Results {
|
|
||||||
parts = append(parts, ns.removePrefixAndSuffix(ns.Name(rt)))
|
|
||||||
}
|
|
||||||
name = ns.Join(ns.Prefix, parts, ns.Suffix)
|
|
||||||
default:
|
|
||||||
name = "unnameable_" + string(t.Kind)
|
|
||||||
}
|
|
||||||
ns.Names[t] = name
|
|
||||||
return name
|
|
||||||
}
|
|
||||||
|
|
||||||
// ImportTracker allows a raw namer to keep track of the packages needed for
|
|
||||||
// import. You can implement yourself or use the one in the generation package.
|
|
||||||
type ImportTracker interface {
|
|
||||||
AddType(*types.Type)
|
|
||||||
AddSymbol(types.Name)
|
|
||||||
LocalNameOf(packagePath string) string
|
|
||||||
PathOf(localName string) (string, bool)
|
|
||||||
ImportLines() []string
|
|
||||||
}
|
|
||||||
|
|
||||||
type rawNamer struct {
|
|
||||||
pkg string
|
|
||||||
tracker ImportTracker
|
|
||||||
Names
|
|
||||||
}
|
|
||||||
|
|
||||||
// Name makes a name the way you'd write it to literally refer to type t,
|
|
||||||
// making ordinary assumptions about how you've imported t's package (or using
|
|
||||||
// r.tracker to specifically track the package imports).
|
|
||||||
func (r *rawNamer) Name(t *types.Type) string {
|
|
||||||
if r.Names == nil {
|
|
||||||
r.Names = Names{}
|
|
||||||
}
|
|
||||||
if name, ok := r.Names[t]; ok {
|
|
||||||
return name
|
|
||||||
}
|
|
||||||
if t.Name.Package != "" {
|
|
||||||
var name string
|
|
||||||
if r.tracker != nil {
|
|
||||||
r.tracker.AddType(t)
|
|
||||||
if t.Name.Package == r.pkg {
|
|
||||||
name = t.Name.Name
|
|
||||||
} else {
|
|
||||||
name = r.tracker.LocalNameOf(t.Name.Package) + "." + t.Name.Name
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if t.Name.Package == r.pkg {
|
|
||||||
name = t.Name.Name
|
|
||||||
} else {
|
|
||||||
name = filepath.Base(t.Name.Package) + "." + t.Name.Name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
r.Names[t] = name
|
|
||||||
return name
|
|
||||||
}
|
|
||||||
var name string
|
|
||||||
switch t.Kind {
|
|
||||||
case types.Builtin:
|
|
||||||
name = t.Name.Name
|
|
||||||
case types.Map:
|
|
||||||
name = "map[" + r.Name(t.Key) + "]" + r.Name(t.Elem)
|
|
||||||
case types.Slice:
|
|
||||||
name = "[]" + r.Name(t.Elem)
|
|
||||||
case types.Array:
|
|
||||||
l := strconv.Itoa(int(t.Len))
|
|
||||||
name = "[" + l + "]" + r.Name(t.Elem)
|
|
||||||
case types.Pointer:
|
|
||||||
name = "*" + r.Name(t.Elem)
|
|
||||||
case types.Struct:
|
|
||||||
elems := []string{}
|
|
||||||
for _, m := range t.Members {
|
|
||||||
elems = append(elems, m.Name+" "+r.Name(m.Type))
|
|
||||||
}
|
|
||||||
name = "struct{" + strings.Join(elems, "; ") + "}"
|
|
||||||
case types.Chan:
|
|
||||||
// TODO: include directionality
|
|
||||||
name = "chan " + r.Name(t.Elem)
|
|
||||||
case types.Interface:
|
|
||||||
// TODO: add to name test
|
|
||||||
elems := []string{}
|
|
||||||
for _, m := range t.Methods {
|
|
||||||
// TODO: include function signature
|
|
||||||
elems = append(elems, m.Name.Name)
|
|
||||||
}
|
|
||||||
name = "interface{" + strings.Join(elems, "; ") + "}"
|
|
||||||
case types.Func:
|
|
||||||
// TODO: add to name test
|
|
||||||
params := []string{}
|
|
||||||
for _, pt := range t.Signature.Parameters {
|
|
||||||
params = append(params, r.Name(pt))
|
|
||||||
}
|
|
||||||
results := []string{}
|
|
||||||
for _, rt := range t.Signature.Results {
|
|
||||||
results = append(results, r.Name(rt))
|
|
||||||
}
|
|
||||||
name = "func(" + strings.Join(params, ",") + ")"
|
|
||||||
if len(results) == 1 {
|
|
||||||
name += " " + results[0]
|
|
||||||
} else if len(results) > 1 {
|
|
||||||
name += " (" + strings.Join(results, ",") + ")"
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
name = "unnameable_" + string(t.Kind)
|
|
||||||
}
|
|
||||||
r.Names[t] = name
|
|
||||||
return name
|
|
||||||
}
|
|
|
@ -1,72 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2015 The Kubernetes Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package namer
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sort"
|
|
||||||
|
|
||||||
"k8s.io/gengo/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Orderer produces an ordering of types given a Namer.
|
|
||||||
type Orderer struct {
|
|
||||||
Namer
|
|
||||||
}
|
|
||||||
|
|
||||||
// OrderUniverse assigns a name to every type in the Universe, including Types,
|
|
||||||
// Functions and Variables, and returns a list sorted by those names.
|
|
||||||
func (o *Orderer) OrderUniverse(u types.Universe) []*types.Type {
|
|
||||||
list := tList{
|
|
||||||
namer: o.Namer,
|
|
||||||
}
|
|
||||||
for _, p := range u {
|
|
||||||
for _, t := range p.Types {
|
|
||||||
list.types = append(list.types, t)
|
|
||||||
}
|
|
||||||
for _, f := range p.Functions {
|
|
||||||
list.types = append(list.types, f)
|
|
||||||
}
|
|
||||||
for _, v := range p.Variables {
|
|
||||||
list.types = append(list.types, v)
|
|
||||||
}
|
|
||||||
for _, v := range p.Constants {
|
|
||||||
list.types = append(list.types, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sort.Sort(list)
|
|
||||||
return list.types
|
|
||||||
}
|
|
||||||
|
|
||||||
// OrderTypes assigns a name to every type, and returns a list sorted by those
|
|
||||||
// names.
|
|
||||||
func (o *Orderer) OrderTypes(typeList []*types.Type) []*types.Type {
|
|
||||||
list := tList{
|
|
||||||
namer: o.Namer,
|
|
||||||
types: typeList,
|
|
||||||
}
|
|
||||||
sort.Sort(list)
|
|
||||||
return list.types
|
|
||||||
}
|
|
||||||
|
|
||||||
type tList struct {
|
|
||||||
namer Namer
|
|
||||||
types []*types.Type
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t tList) Len() int { return len(t.types) }
|
|
||||||
func (t tList) Less(i, j int) bool { return t.namer.Name(t.types[i]) < t.namer.Name(t.types[j]) }
|
|
||||||
func (t tList) Swap(i, j int) { t.types[i], t.types[j] = t.types[j], t.types[i] }
|
|
|
@ -1,120 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2015 The Kubernetes Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package namer
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"k8s.io/gengo/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
var consonants = "bcdfghjklmnpqrstvwxyz"
|
|
||||||
|
|
||||||
type pluralNamer struct {
|
|
||||||
// key is the case-sensitive type name, value is the case-insensitive
|
|
||||||
// intended output.
|
|
||||||
exceptions map[string]string
|
|
||||||
finalize func(string) string
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewPublicPluralNamer returns a namer that returns the plural form of the input
|
|
||||||
// type's name, starting with a uppercase letter.
|
|
||||||
func NewPublicPluralNamer(exceptions map[string]string) *pluralNamer {
|
|
||||||
return &pluralNamer{exceptions, IC}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewPrivatePluralNamer returns a namer that returns the plural form of the input
|
|
||||||
// type's name, starting with a lowercase letter.
|
|
||||||
func NewPrivatePluralNamer(exceptions map[string]string) *pluralNamer {
|
|
||||||
return &pluralNamer{exceptions, IL}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewAllLowercasePluralNamer returns a namer that returns the plural form of the input
|
|
||||||
// type's name, with all letters in lowercase.
|
|
||||||
func NewAllLowercasePluralNamer(exceptions map[string]string) *pluralNamer {
|
|
||||||
return &pluralNamer{exceptions, strings.ToLower}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Name returns the plural form of the type's name. If the type's name is found
|
|
||||||
// in the exceptions map, the map value is returned.
|
|
||||||
func (r *pluralNamer) Name(t *types.Type) string {
|
|
||||||
singular := t.Name.Name
|
|
||||||
var plural string
|
|
||||||
var ok bool
|
|
||||||
if plural, ok = r.exceptions[singular]; ok {
|
|
||||||
return r.finalize(plural)
|
|
||||||
}
|
|
||||||
if len(singular) < 2 {
|
|
||||||
return r.finalize(singular)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch rune(singular[len(singular)-1]) {
|
|
||||||
case 's', 'x', 'z':
|
|
||||||
plural = esPlural(singular)
|
|
||||||
case 'y':
|
|
||||||
sl := rune(singular[len(singular)-2])
|
|
||||||
if isConsonant(sl) {
|
|
||||||
plural = iesPlural(singular)
|
|
||||||
} else {
|
|
||||||
plural = sPlural(singular)
|
|
||||||
}
|
|
||||||
case 'h':
|
|
||||||
sl := rune(singular[len(singular)-2])
|
|
||||||
if sl == 'c' || sl == 's' {
|
|
||||||
plural = esPlural(singular)
|
|
||||||
} else {
|
|
||||||
plural = sPlural(singular)
|
|
||||||
}
|
|
||||||
case 'e':
|
|
||||||
sl := rune(singular[len(singular)-2])
|
|
||||||
if sl == 'f' {
|
|
||||||
plural = vesPlural(singular[:len(singular)-1])
|
|
||||||
} else {
|
|
||||||
plural = sPlural(singular)
|
|
||||||
}
|
|
||||||
case 'f':
|
|
||||||
plural = vesPlural(singular)
|
|
||||||
default:
|
|
||||||
plural = sPlural(singular)
|
|
||||||
}
|
|
||||||
return r.finalize(plural)
|
|
||||||
}
|
|
||||||
|
|
||||||
func iesPlural(singular string) string {
|
|
||||||
return singular[:len(singular)-1] + "ies"
|
|
||||||
}
|
|
||||||
|
|
||||||
func vesPlural(singular string) string {
|
|
||||||
return singular[:len(singular)-1] + "ves"
|
|
||||||
}
|
|
||||||
|
|
||||||
func esPlural(singular string) string {
|
|
||||||
return singular + "es"
|
|
||||||
}
|
|
||||||
|
|
||||||
func sPlural(singular string) string {
|
|
||||||
return singular + "s"
|
|
||||||
}
|
|
||||||
|
|
||||||
func isConsonant(char rune) bool {
|
|
||||||
for _, c := range consonants {
|
|
||||||
if char == c {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2015 The Kubernetes Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Package parser provides code to parse go files, type-check them, extract the
|
|
||||||
// types.
|
|
||||||
package parser // import "k8s.io/gengo/parser"
|
|
|
@ -1,925 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2015 The Kubernetes Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package parser
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"go/ast"
|
|
||||||
"go/build"
|
|
||||||
"go/constant"
|
|
||||||
"go/parser"
|
|
||||||
"go/token"
|
|
||||||
tc "go/types"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"path"
|
|
||||||
"path/filepath"
|
|
||||||
"regexp"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"k8s.io/gengo/types"
|
|
||||||
"k8s.io/klog/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
// This clarifies when a pkg path has been canonicalized.
|
|
||||||
type importPathString string
|
|
||||||
|
|
||||||
// Builder lets you add all the go files in all the packages that you care
|
|
||||||
// about, then constructs the type source data.
|
|
||||||
type Builder struct {
|
|
||||||
context *build.Context
|
|
||||||
|
|
||||||
// If true, include *_test.go
|
|
||||||
IncludeTestFiles bool
|
|
||||||
|
|
||||||
// Map of package names to more canonical information about the package.
|
|
||||||
// This might hold the same value for multiple names, e.g. if someone
|
|
||||||
// referenced ./pkg/name or in the case of vendoring, which canonicalizes
|
|
||||||
// differently that what humans would type.
|
|
||||||
//
|
|
||||||
// This must only be accessed via getLoadedBuildPackage and setLoadedBuildPackage
|
|
||||||
buildPackages map[importPathString]*build.Package
|
|
||||||
|
|
||||||
fset *token.FileSet
|
|
||||||
// map of package path to list of parsed files
|
|
||||||
parsed map[importPathString][]parsedFile
|
|
||||||
// map of package path to absolute path (to prevent overlap)
|
|
||||||
absPaths map[importPathString]string
|
|
||||||
|
|
||||||
// Set by typeCheckPackage(), used by importPackage() and friends.
|
|
||||||
typeCheckedPackages map[importPathString]*tc.Package
|
|
||||||
|
|
||||||
// Map of package path to whether the user requested it or it was from
|
|
||||||
// an import.
|
|
||||||
userRequested map[importPathString]bool
|
|
||||||
|
|
||||||
// All comments from everywhere in every parsed file.
|
|
||||||
endLineToCommentGroup map[fileLine]*ast.CommentGroup
|
|
||||||
|
|
||||||
// map of package to list of packages it imports.
|
|
||||||
importGraph map[importPathString]map[string]struct{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// parsedFile is for tracking files with name
|
|
||||||
type parsedFile struct {
|
|
||||||
name string
|
|
||||||
file *ast.File
|
|
||||||
}
|
|
||||||
|
|
||||||
// key type for finding comments.
|
|
||||||
type fileLine struct {
|
|
||||||
file string
|
|
||||||
line int
|
|
||||||
}
|
|
||||||
|
|
||||||
// New constructs a new builder.
|
|
||||||
func New() *Builder {
|
|
||||||
c := build.Default
|
|
||||||
if c.GOROOT == "" {
|
|
||||||
if p, err := exec.Command("which", "go").CombinedOutput(); err == nil {
|
|
||||||
// The returned string will have some/path/bin/go, so remove the last two elements.
|
|
||||||
c.GOROOT = filepath.Dir(filepath.Dir(strings.Trim(string(p), "\n")))
|
|
||||||
} else {
|
|
||||||
klog.Warningf("Warning: $GOROOT not set, and unable to run `which go` to find it: %v\n", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Force this to off, since we don't properly parse CGo. All symbols must
|
|
||||||
// have non-CGo equivalents.
|
|
||||||
c.CgoEnabled = false
|
|
||||||
return &Builder{
|
|
||||||
context: &c,
|
|
||||||
buildPackages: map[importPathString]*build.Package{},
|
|
||||||
typeCheckedPackages: map[importPathString]*tc.Package{},
|
|
||||||
fset: token.NewFileSet(),
|
|
||||||
parsed: map[importPathString][]parsedFile{},
|
|
||||||
absPaths: map[importPathString]string{},
|
|
||||||
userRequested: map[importPathString]bool{},
|
|
||||||
endLineToCommentGroup: map[fileLine]*ast.CommentGroup{},
|
|
||||||
importGraph: map[importPathString]map[string]struct{}{},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddBuildTags adds the specified build tags to the parse context.
|
|
||||||
func (b *Builder) AddBuildTags(tags ...string) {
|
|
||||||
b.context.BuildTags = append(b.context.BuildTags, tags...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Builder) getLoadedBuildPackage(importPath string) (*build.Package, bool) {
|
|
||||||
canonicalized := canonicalizeImportPath(importPath)
|
|
||||||
if string(canonicalized) != importPath {
|
|
||||||
klog.V(5).Infof("getLoadedBuildPackage: %s normalized to %s", importPath, canonicalized)
|
|
||||||
}
|
|
||||||
buildPkg, ok := b.buildPackages[canonicalized]
|
|
||||||
return buildPkg, ok
|
|
||||||
}
|
|
||||||
func (b *Builder) setLoadedBuildPackage(importPath string, buildPkg *build.Package) {
|
|
||||||
canonicalizedImportPath := canonicalizeImportPath(importPath)
|
|
||||||
if string(canonicalizedImportPath) != importPath {
|
|
||||||
klog.V(5).Infof("setLoadedBuildPackage: importPath %s normalized to %s", importPath, canonicalizedImportPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
canonicalizedBuildPkgImportPath := canonicalizeImportPath(buildPkg.ImportPath)
|
|
||||||
if string(canonicalizedBuildPkgImportPath) != buildPkg.ImportPath {
|
|
||||||
klog.V(5).Infof("setLoadedBuildPackage: buildPkg.ImportPath %s normalized to %s", buildPkg.ImportPath, canonicalizedBuildPkgImportPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
if canonicalizedImportPath != canonicalizedBuildPkgImportPath {
|
|
||||||
klog.V(5).Infof("setLoadedBuildPackage: normalized importPath (%s) differs from buildPkg.ImportPath (%s)", canonicalizedImportPath, canonicalizedBuildPkgImportPath)
|
|
||||||
}
|
|
||||||
b.buildPackages[canonicalizedImportPath] = buildPkg
|
|
||||||
b.buildPackages[canonicalizedBuildPkgImportPath] = buildPkg
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get package information from the go/build package. Automatically excludes
|
|
||||||
// e.g. test files and files for other platforms-- there is quite a bit of
|
|
||||||
// logic of that nature in the build package.
|
|
||||||
func (b *Builder) importBuildPackage(dir string) (*build.Package, error) {
|
|
||||||
if buildPkg, ok := b.getLoadedBuildPackage(dir); ok {
|
|
||||||
return buildPkg, nil
|
|
||||||
}
|
|
||||||
// This validates the `package foo // github.com/bar/foo` comments.
|
|
||||||
buildPkg, err := b.importWithMode(dir, build.ImportComment)
|
|
||||||
if err != nil {
|
|
||||||
if _, ok := err.(*build.NoGoError); !ok {
|
|
||||||
return nil, fmt.Errorf("unable to import %q: %v", dir, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if buildPkg == nil {
|
|
||||||
// Might be an empty directory. Try to just find the dir.
|
|
||||||
buildPkg, err = b.importWithMode(dir, build.FindOnly)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remember it under the user-provided name.
|
|
||||||
klog.V(5).Infof("saving buildPackage %s", dir)
|
|
||||||
b.setLoadedBuildPackage(dir, buildPkg)
|
|
||||||
|
|
||||||
return buildPkg, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddFileForTest adds a file to the set, without verifying that the provided
|
|
||||||
// pkg actually exists on disk. The pkg must be of the form "canonical/pkg/path"
|
|
||||||
// and the path must be the absolute path to the file. Because this bypasses
|
|
||||||
// the normal recursive finding of package dependencies (on disk), test should
|
|
||||||
// sort their test files topologically first, so all deps are resolved by the
|
|
||||||
// time we need them.
|
|
||||||
func (b *Builder) AddFileForTest(pkg string, path string, src []byte) error {
|
|
||||||
if err := b.addFile(importPathString(pkg), path, src, true); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err := b.typeCheckPackage(importPathString(pkg), true); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// addFile adds a file to the set. The pkgPath must be of the form
|
|
||||||
// "canonical/pkg/path" and the path must be the absolute path to the file. A
|
|
||||||
// flag indicates whether this file was user-requested or just from following
|
|
||||||
// the import graph.
|
|
||||||
func (b *Builder) addFile(pkgPath importPathString, path string, src []byte, userRequested bool) error {
|
|
||||||
for _, p := range b.parsed[pkgPath] {
|
|
||||||
if path == p.name {
|
|
||||||
klog.V(5).Infof("addFile %s %s already parsed, skipping", pkgPath, path)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
klog.V(6).Infof("addFile %s %s", pkgPath, path)
|
|
||||||
p, err := parser.ParseFile(b.fset, path, src, parser.DeclarationErrors|parser.ParseComments)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is redundant with addDir, but some tests call AddFileForTest, which
|
|
||||||
// call into here without calling addDir.
|
|
||||||
b.userRequested[pkgPath] = userRequested || b.userRequested[pkgPath]
|
|
||||||
|
|
||||||
b.parsed[pkgPath] = append(b.parsed[pkgPath], parsedFile{path, p})
|
|
||||||
for _, c := range p.Comments {
|
|
||||||
position := b.fset.Position(c.End())
|
|
||||||
b.endLineToCommentGroup[fileLine{position.Filename, position.Line}] = c
|
|
||||||
}
|
|
||||||
|
|
||||||
// We have to get the packages from this specific file, in case the
|
|
||||||
// user added individual files instead of entire directories.
|
|
||||||
if b.importGraph[pkgPath] == nil {
|
|
||||||
b.importGraph[pkgPath] = map[string]struct{}{}
|
|
||||||
}
|
|
||||||
for _, im := range p.Imports {
|
|
||||||
importedPath := strings.Trim(im.Path.Value, `"`)
|
|
||||||
b.importGraph[pkgPath][importedPath] = struct{}{}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddDir adds an entire directory, scanning it for go files. 'dir' should have
|
|
||||||
// a single go package in it. GOPATH, GOROOT, and the location of your go
|
|
||||||
// binary (`which go`) will all be searched if dir doesn't literally resolve.
|
|
||||||
func (b *Builder) AddDir(dir string) error {
|
|
||||||
_, err := b.importPackage(dir, true)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddDirRecursive is just like AddDir, but it also recursively adds
|
|
||||||
// subdirectories; it returns an error only if the path couldn't be resolved;
|
|
||||||
// any directories recursed into without go source are ignored.
|
|
||||||
func (b *Builder) AddDirRecursive(dir string) error {
|
|
||||||
// Add the root.
|
|
||||||
if _, err := b.importPackage(dir, true); err != nil {
|
|
||||||
klog.Warningf("Ignoring directory %v: %v", dir, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// filepath.Walk does not follow symlinks. We therefore evaluate symlinks and use that with
|
|
||||||
// filepath.Walk.
|
|
||||||
buildPkg, ok := b.getLoadedBuildPackage(dir)
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("no loaded build package for %s", dir)
|
|
||||||
}
|
|
||||||
realPath, err := filepath.EvalSymlinks(buildPkg.Dir)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fn := func(filePath string, info os.FileInfo, err error) error {
|
|
||||||
if info != nil && info.IsDir() {
|
|
||||||
rel := filepath.ToSlash(strings.TrimPrefix(filePath, realPath))
|
|
||||||
if rel != "" {
|
|
||||||
// Make a pkg path.
|
|
||||||
buildPkg, ok := b.getLoadedBuildPackage(dir)
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("no loaded build package for %s", dir)
|
|
||||||
}
|
|
||||||
pkg := path.Join(string(canonicalizeImportPath(buildPkg.ImportPath)), rel)
|
|
||||||
|
|
||||||
// Add it.
|
|
||||||
if _, err := b.importPackage(pkg, true); err != nil {
|
|
||||||
klog.Warningf("Ignoring child directory %v: %v", pkg, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if err := filepath.Walk(realPath, fn); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddDirTo adds an entire directory to a given Universe. Unlike AddDir, this
|
|
||||||
// processes the package immediately, which makes it safe to use from within a
|
|
||||||
// generator (rather than just at init time. 'dir' must be a single go package.
|
|
||||||
// GOPATH, GOROOT, and the location of your go binary (`which go`) will all be
|
|
||||||
// searched if dir doesn't literally resolve.
|
|
||||||
// Deprecated. Please use AddDirectoryTo.
|
|
||||||
func (b *Builder) AddDirTo(dir string, u *types.Universe) error {
|
|
||||||
// We want all types from this package, as if they were directly added
|
|
||||||
// by the user. They WERE added by the user, in effect.
|
|
||||||
if _, err := b.importPackage(dir, true); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
pkg, ok := b.getLoadedBuildPackage(dir)
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("no such package: %q", dir)
|
|
||||||
}
|
|
||||||
return b.findTypesIn(canonicalizeImportPath(pkg.ImportPath), u)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddDirectoryTo adds an entire directory to a given Universe. Unlike AddDir,
|
|
||||||
// this processes the package immediately, which makes it safe to use from
|
|
||||||
// within a generator (rather than just at init time. 'dir' must be a single go
|
|
||||||
// package. GOPATH, GOROOT, and the location of your go binary (`which go`)
|
|
||||||
// will all be searched if dir doesn't literally resolve.
|
|
||||||
func (b *Builder) AddDirectoryTo(dir string, u *types.Universe) (*types.Package, error) {
|
|
||||||
// We want all types from this package, as if they were directly added
|
|
||||||
// by the user. They WERE added by the user, in effect.
|
|
||||||
if _, err := b.importPackage(dir, true); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
pkg, ok := b.getLoadedBuildPackage(dir)
|
|
||||||
if !ok || pkg == nil {
|
|
||||||
return nil, fmt.Errorf("no such package: %q", dir)
|
|
||||||
}
|
|
||||||
path := canonicalizeImportPath(pkg.ImportPath)
|
|
||||||
if err := b.findTypesIn(path, u); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return u.Package(string(path)), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// The implementation of AddDir. A flag indicates whether this directory was
|
|
||||||
// user-requested or just from following the import graph.
|
|
||||||
func (b *Builder) addDir(dir string, userRequested bool) error {
|
|
||||||
klog.V(5).Infof("addDir %s", dir)
|
|
||||||
buildPkg, err := b.importBuildPackage(dir)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
canonicalPackage := canonicalizeImportPath(buildPkg.ImportPath)
|
|
||||||
pkgPath := canonicalPackage
|
|
||||||
if dir != string(canonicalPackage) {
|
|
||||||
klog.V(5).Infof("addDir %s, canonical path is %s", dir, pkgPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sanity check the pkg dir has not changed.
|
|
||||||
if prev, found := b.absPaths[pkgPath]; found {
|
|
||||||
if buildPkg.Dir != prev {
|
|
||||||
return fmt.Errorf("package %q (%s) previously resolved to %s", pkgPath, buildPkg.Dir, prev)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
b.absPaths[pkgPath] = buildPkg.Dir
|
|
||||||
}
|
|
||||||
|
|
||||||
files := []string{}
|
|
||||||
files = append(files, buildPkg.GoFiles...)
|
|
||||||
if b.IncludeTestFiles {
|
|
||||||
files = append(files, buildPkg.TestGoFiles...)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, file := range files {
|
|
||||||
if !strings.HasSuffix(file, ".go") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
absPath := filepath.Join(buildPkg.Dir, file)
|
|
||||||
data, err := ioutil.ReadFile(absPath)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("while loading %q: %v", absPath, err)
|
|
||||||
}
|
|
||||||
err = b.addFile(pkgPath, absPath, data, userRequested)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("while parsing %q: %v", absPath, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// regexErrPackageNotFound helps test the expected error for not finding a package.
|
|
||||||
var regexErrPackageNotFound = regexp.MustCompile(`^unable to import ".*?":.*`)
|
|
||||||
|
|
||||||
func isErrPackageNotFound(err error) bool {
|
|
||||||
return regexErrPackageNotFound.MatchString(err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
// importPackage is a function that will be called by the type check package when it
|
|
||||||
// needs to import a go package. 'path' is the import path.
|
|
||||||
func (b *Builder) importPackage(dir string, userRequested bool) (*tc.Package, error) {
|
|
||||||
klog.V(5).Infof("importPackage %s", dir)
|
|
||||||
|
|
||||||
var pkgPath = importPathString(dir)
|
|
||||||
|
|
||||||
// Get the canonical path if we can.
|
|
||||||
if buildPkg, _ := b.getLoadedBuildPackage(dir); buildPkg != nil {
|
|
||||||
canonicalPackage := canonicalizeImportPath(buildPkg.ImportPath)
|
|
||||||
klog.V(5).Infof("importPackage %s, canonical path is %s", dir, canonicalPackage)
|
|
||||||
pkgPath = canonicalPackage
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have not seen this before, process it now.
|
|
||||||
ignoreError := false
|
|
||||||
if _, found := b.parsed[pkgPath]; !found {
|
|
||||||
// Ignore errors in paths that we're importing solely because
|
|
||||||
// they're referenced by other packages.
|
|
||||||
ignoreError = true
|
|
||||||
|
|
||||||
// Add it.
|
|
||||||
if err := b.addDir(dir, userRequested); err != nil {
|
|
||||||
if isErrPackageNotFound(err) {
|
|
||||||
klog.V(6).Info(err)
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the canonical path now that it has been added.
|
|
||||||
if buildPkg, _ := b.getLoadedBuildPackage(dir); buildPkg != nil {
|
|
||||||
canonicalPackage := canonicalizeImportPath(buildPkg.ImportPath)
|
|
||||||
klog.V(5).Infof("importPackage %s, canonical path is %s", dir, canonicalPackage)
|
|
||||||
pkgPath = canonicalPackage
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If it was previously known, just check that the user-requestedness hasn't
|
|
||||||
// changed.
|
|
||||||
b.userRequested[pkgPath] = userRequested || b.userRequested[pkgPath]
|
|
||||||
|
|
||||||
// Run the type checker. We may end up doing this to pkgs that are already
|
|
||||||
// done, or are in the queue to be done later, but it will short-circuit,
|
|
||||||
// and we can't miss pkgs that are only depended on.
|
|
||||||
pkg, err := b.typeCheckPackage(pkgPath, !ignoreError)
|
|
||||||
if err != nil {
|
|
||||||
switch {
|
|
||||||
case ignoreError && pkg != nil:
|
|
||||||
klog.V(4).Infof("type checking encountered some issues in %q, but ignoring.\n", pkgPath)
|
|
||||||
case !ignoreError && pkg != nil:
|
|
||||||
klog.V(3).Infof("type checking encountered some errors in %q\n", pkgPath)
|
|
||||||
return nil, err
|
|
||||||
default:
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return pkg, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type importAdapter struct {
|
|
||||||
b *Builder
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a importAdapter) Import(path string) (*tc.Package, error) {
|
|
||||||
return a.b.importPackage(path, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
// typeCheckPackage will attempt to return the package even if there are some
|
|
||||||
// errors, so you may check whether the package is nil or not even if you get
|
|
||||||
// an error.
|
|
||||||
func (b *Builder) typeCheckPackage(pkgPath importPathString, logErr bool) (*tc.Package, error) {
|
|
||||||
klog.V(5).Infof("typeCheckPackage %s", pkgPath)
|
|
||||||
if pkg, ok := b.typeCheckedPackages[pkgPath]; ok {
|
|
||||||
if pkg != nil {
|
|
||||||
klog.V(6).Infof("typeCheckPackage %s already done", pkgPath)
|
|
||||||
return pkg, nil
|
|
||||||
}
|
|
||||||
// We store a nil right before starting work on a package. So
|
|
||||||
// if we get here and it's present and nil, that means there's
|
|
||||||
// another invocation of this function on the call stack
|
|
||||||
// already processing this package.
|
|
||||||
return nil, fmt.Errorf("circular dependency for %q", pkgPath)
|
|
||||||
}
|
|
||||||
parsedFiles, ok := b.parsed[pkgPath]
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("No files for pkg %q", pkgPath)
|
|
||||||
}
|
|
||||||
files := make([]*ast.File, len(parsedFiles))
|
|
||||||
for i := range parsedFiles {
|
|
||||||
files[i] = parsedFiles[i].file
|
|
||||||
}
|
|
||||||
b.typeCheckedPackages[pkgPath] = nil
|
|
||||||
c := tc.Config{
|
|
||||||
IgnoreFuncBodies: true,
|
|
||||||
// Note that importAdapter can call b.importPackage which calls this
|
|
||||||
// method. So there can't be cycles in the import graph.
|
|
||||||
Importer: importAdapter{b},
|
|
||||||
Error: func(err error) {
|
|
||||||
if logErr {
|
|
||||||
klog.V(2).Infof("type checker: %v\n", err)
|
|
||||||
} else {
|
|
||||||
klog.V(3).Infof("type checker: %v\n", err)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
pkg, err := c.Check(string(pkgPath), b.fset, files, nil)
|
|
||||||
b.typeCheckedPackages[pkgPath] = pkg // record the result whether or not there was an error
|
|
||||||
return pkg, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// FindPackages fetches a list of the user-imported packages.
|
|
||||||
// Note that you need to call b.FindTypes() first.
|
|
||||||
func (b *Builder) FindPackages() []string {
|
|
||||||
// Iterate packages in a predictable order.
|
|
||||||
pkgPaths := []string{}
|
|
||||||
for k := range b.typeCheckedPackages {
|
|
||||||
pkgPaths = append(pkgPaths, string(k))
|
|
||||||
}
|
|
||||||
sort.Strings(pkgPaths)
|
|
||||||
|
|
||||||
result := []string{}
|
|
||||||
for _, pkgPath := range pkgPaths {
|
|
||||||
if b.userRequested[importPathString(pkgPath)] {
|
|
||||||
// Since walkType is recursive, all types that are in packages that
|
|
||||||
// were directly mentioned will be included. We don't need to
|
|
||||||
// include all types in all transitive packages, though.
|
|
||||||
result = append(result, pkgPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// FindTypes finalizes the package imports, and searches through all the
|
|
||||||
// packages for types.
|
|
||||||
func (b *Builder) FindTypes() (types.Universe, error) {
|
|
||||||
// Take a snapshot of pkgs to iterate, since this will recursively mutate
|
|
||||||
// b.parsed. Iterate in a predictable order.
|
|
||||||
pkgPaths := []string{}
|
|
||||||
for pkgPath := range b.parsed {
|
|
||||||
pkgPaths = append(pkgPaths, string(pkgPath))
|
|
||||||
}
|
|
||||||
sort.Strings(pkgPaths)
|
|
||||||
|
|
||||||
u := types.Universe{}
|
|
||||||
for _, pkgPath := range pkgPaths {
|
|
||||||
if err := b.findTypesIn(importPathString(pkgPath), &u); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return u, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// addCommentsToType takes any accumulated comment lines prior to obj and
|
|
||||||
// attaches them to the type t.
|
|
||||||
func (b *Builder) addCommentsToType(obj tc.Object, t *types.Type) {
|
|
||||||
c1 := b.priorCommentLines(obj.Pos(), 1)
|
|
||||||
// c1.Text() is safe if c1 is nil
|
|
||||||
t.CommentLines = splitLines(c1.Text())
|
|
||||||
if c1 == nil {
|
|
||||||
t.SecondClosestCommentLines = splitLines(b.priorCommentLines(obj.Pos(), 2).Text())
|
|
||||||
} else {
|
|
||||||
t.SecondClosestCommentLines = splitLines(b.priorCommentLines(c1.List[0].Slash, 2).Text())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// findTypesIn finalizes the package import and searches through the package
|
|
||||||
// for types.
|
|
||||||
func (b *Builder) findTypesIn(pkgPath importPathString, u *types.Universe) error {
|
|
||||||
klog.V(5).Infof("findTypesIn %s", pkgPath)
|
|
||||||
pkg := b.typeCheckedPackages[pkgPath]
|
|
||||||
if pkg == nil {
|
|
||||||
return fmt.Errorf("findTypesIn(%s): package is not known", pkgPath)
|
|
||||||
}
|
|
||||||
if !b.userRequested[pkgPath] {
|
|
||||||
// Since walkType is recursive, all types that the
|
|
||||||
// packages they asked for depend on will be included.
|
|
||||||
// But we don't need to include all types in all
|
|
||||||
// *packages* they depend on.
|
|
||||||
klog.V(5).Infof("findTypesIn %s: package is not user requested", pkgPath)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// We're keeping this package. This call will create the record.
|
|
||||||
u.Package(string(pkgPath)).Name = pkg.Name()
|
|
||||||
u.Package(string(pkgPath)).Path = pkg.Path()
|
|
||||||
u.Package(string(pkgPath)).SourcePath = b.absPaths[pkgPath]
|
|
||||||
|
|
||||||
for _, f := range b.parsed[pkgPath] {
|
|
||||||
if _, fileName := filepath.Split(f.name); fileName == "doc.go" {
|
|
||||||
tp := u.Package(string(pkgPath))
|
|
||||||
// findTypesIn might be called multiple times. Clean up tp.Comments
|
|
||||||
// to avoid repeatedly fill same comments to it.
|
|
||||||
tp.Comments = []string{}
|
|
||||||
for i := range f.file.Comments {
|
|
||||||
tp.Comments = append(tp.Comments, splitLines(f.file.Comments[i].Text())...)
|
|
||||||
}
|
|
||||||
if f.file.Doc != nil {
|
|
||||||
tp.DocComments = splitLines(f.file.Doc.Text())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
s := pkg.Scope()
|
|
||||||
for _, n := range s.Names() {
|
|
||||||
obj := s.Lookup(n)
|
|
||||||
tn, ok := obj.(*tc.TypeName)
|
|
||||||
if ok {
|
|
||||||
t := b.walkType(*u, nil, tn.Type())
|
|
||||||
b.addCommentsToType(obj, t)
|
|
||||||
}
|
|
||||||
tf, ok := obj.(*tc.Func)
|
|
||||||
// We only care about functions, not concrete/abstract methods.
|
|
||||||
if ok && tf.Type() != nil && tf.Type().(*tc.Signature).Recv() == nil {
|
|
||||||
t := b.addFunction(*u, nil, tf)
|
|
||||||
b.addCommentsToType(obj, t)
|
|
||||||
}
|
|
||||||
tv, ok := obj.(*tc.Var)
|
|
||||||
if ok && !tv.IsField() {
|
|
||||||
t := b.addVariable(*u, nil, tv)
|
|
||||||
b.addCommentsToType(obj, t)
|
|
||||||
}
|
|
||||||
tconst, ok := obj.(*tc.Const)
|
|
||||||
if ok {
|
|
||||||
t := b.addConstant(*u, nil, tconst)
|
|
||||||
b.addCommentsToType(obj, t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
importedPkgs := []string{}
|
|
||||||
for k := range b.importGraph[pkgPath] {
|
|
||||||
importedPkgs = append(importedPkgs, string(k))
|
|
||||||
}
|
|
||||||
sort.Strings(importedPkgs)
|
|
||||||
for _, p := range importedPkgs {
|
|
||||||
u.AddImports(string(pkgPath), p)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Builder) importWithMode(dir string, mode build.ImportMode) (*build.Package, error) {
|
|
||||||
// This is a bit of a hack. The srcDir argument to Import() should
|
|
||||||
// properly be the dir of the file which depends on the package to be
|
|
||||||
// imported, so that vendoring can work properly and local paths can
|
|
||||||
// resolve. We assume that there is only one level of vendoring, and that
|
|
||||||
// the CWD is inside the GOPATH, so this should be safe. Nobody should be
|
|
||||||
// using local (relative) paths except on the CLI, so CWD is also
|
|
||||||
// sufficient.
|
|
||||||
cwd, err := os.Getwd()
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("unable to get current directory: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// normalize to drop /vendor/ if present
|
|
||||||
dir = string(canonicalizeImportPath(dir))
|
|
||||||
|
|
||||||
buildPkg, err := b.context.Import(filepath.ToSlash(dir), cwd, mode)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return buildPkg, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// if there's a comment on the line `lines` before pos, return its text, otherwise "".
|
|
||||||
func (b *Builder) priorCommentLines(pos token.Pos, lines int) *ast.CommentGroup {
|
|
||||||
position := b.fset.Position(pos)
|
|
||||||
key := fileLine{position.Filename, position.Line - lines}
|
|
||||||
return b.endLineToCommentGroup[key]
|
|
||||||
}
|
|
||||||
|
|
||||||
func splitLines(str string) []string {
|
|
||||||
return strings.Split(strings.TrimRight(str, "\n"), "\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
func tcFuncNameToName(in string) types.Name {
|
|
||||||
name := strings.TrimPrefix(in, "func ")
|
|
||||||
nameParts := strings.Split(name, "(")
|
|
||||||
return tcNameToName(nameParts[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
func tcVarNameToName(in string) types.Name {
|
|
||||||
nameParts := strings.Split(in, " ")
|
|
||||||
// nameParts[0] is "var".
|
|
||||||
// nameParts[2:] is the type of the variable, we ignore it for now.
|
|
||||||
return tcNameToName(nameParts[1])
|
|
||||||
}
|
|
||||||
|
|
||||||
func tcNameToName(in string) types.Name {
|
|
||||||
// Detect anonymous type names. (These may have '.' characters because
|
|
||||||
// embedded types may have packages, so we detect them specially.)
|
|
||||||
if strings.HasPrefix(in, "struct{") ||
|
|
||||||
strings.HasPrefix(in, "<-chan") ||
|
|
||||||
strings.HasPrefix(in, "chan<-") ||
|
|
||||||
strings.HasPrefix(in, "chan ") ||
|
|
||||||
strings.HasPrefix(in, "func(") ||
|
|
||||||
strings.HasPrefix(in, "func (") ||
|
|
||||||
strings.HasPrefix(in, "*") ||
|
|
||||||
strings.HasPrefix(in, "map[") ||
|
|
||||||
strings.HasPrefix(in, "[") {
|
|
||||||
return types.Name{Name: in}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, if there are '.' characters present, the name has a
|
|
||||||
// package path in front.
|
|
||||||
nameParts := strings.Split(in, ".")
|
|
||||||
name := types.Name{Name: in}
|
|
||||||
if n := len(nameParts); n >= 2 {
|
|
||||||
// The final "." is the name of the type--previous ones must
|
|
||||||
// have been in the package path.
|
|
||||||
name.Package, name.Name = strings.Join(nameParts[:n-1], "."), nameParts[n-1]
|
|
||||||
}
|
|
||||||
return name
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Builder) convertSignature(u types.Universe, t *tc.Signature) *types.Signature {
|
|
||||||
signature := &types.Signature{}
|
|
||||||
for i := 0; i < t.Params().Len(); i++ {
|
|
||||||
signature.Parameters = append(signature.Parameters, b.walkType(u, nil, t.Params().At(i).Type()))
|
|
||||||
signature.ParameterNames = append(signature.ParameterNames, t.Params().At(i).Name())
|
|
||||||
}
|
|
||||||
for i := 0; i < t.Results().Len(); i++ {
|
|
||||||
signature.Results = append(signature.Results, b.walkType(u, nil, t.Results().At(i).Type()))
|
|
||||||
signature.ResultNames = append(signature.ResultNames, t.Results().At(i).Name())
|
|
||||||
}
|
|
||||||
if r := t.Recv(); r != nil {
|
|
||||||
signature.Receiver = b.walkType(u, nil, r.Type())
|
|
||||||
}
|
|
||||||
signature.Variadic = t.Variadic()
|
|
||||||
return signature
|
|
||||||
}
|
|
||||||
|
|
||||||
// walkType adds the type, and any necessary child types.
|
|
||||||
func (b *Builder) walkType(u types.Universe, useName *types.Name, in tc.Type) *types.Type {
|
|
||||||
// Most of the cases are underlying types of the named type.
|
|
||||||
name := tcNameToName(in.String())
|
|
||||||
if useName != nil {
|
|
||||||
name = *useName
|
|
||||||
}
|
|
||||||
|
|
||||||
switch t := in.(type) {
|
|
||||||
case *tc.Struct:
|
|
||||||
out := u.Type(name)
|
|
||||||
if out.Kind != types.Unknown {
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
out.Kind = types.Struct
|
|
||||||
for i := 0; i < t.NumFields(); i++ {
|
|
||||||
f := t.Field(i)
|
|
||||||
m := types.Member{
|
|
||||||
Name: f.Name(),
|
|
||||||
Embedded: f.Anonymous(),
|
|
||||||
Tags: t.Tag(i),
|
|
||||||
Type: b.walkType(u, nil, f.Type()),
|
|
||||||
CommentLines: splitLines(b.priorCommentLines(f.Pos(), 1).Text()),
|
|
||||||
}
|
|
||||||
out.Members = append(out.Members, m)
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
case *tc.Map:
|
|
||||||
out := u.Type(name)
|
|
||||||
if out.Kind != types.Unknown {
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
out.Kind = types.Map
|
|
||||||
out.Elem = b.walkType(u, nil, t.Elem())
|
|
||||||
out.Key = b.walkType(u, nil, t.Key())
|
|
||||||
return out
|
|
||||||
case *tc.Pointer:
|
|
||||||
out := u.Type(name)
|
|
||||||
if out.Kind != types.Unknown {
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
out.Kind = types.Pointer
|
|
||||||
out.Elem = b.walkType(u, nil, t.Elem())
|
|
||||||
return out
|
|
||||||
case *tc.Slice:
|
|
||||||
out := u.Type(name)
|
|
||||||
if out.Kind != types.Unknown {
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
out.Kind = types.Slice
|
|
||||||
out.Elem = b.walkType(u, nil, t.Elem())
|
|
||||||
return out
|
|
||||||
case *tc.Array:
|
|
||||||
out := u.Type(name)
|
|
||||||
if out.Kind != types.Unknown {
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
out.Kind = types.Array
|
|
||||||
out.Elem = b.walkType(u, nil, t.Elem())
|
|
||||||
out.Len = in.(*tc.Array).Len()
|
|
||||||
return out
|
|
||||||
case *tc.Chan:
|
|
||||||
out := u.Type(name)
|
|
||||||
if out.Kind != types.Unknown {
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
out.Kind = types.Chan
|
|
||||||
out.Elem = b.walkType(u, nil, t.Elem())
|
|
||||||
// TODO: need to store direction, otherwise raw type name
|
|
||||||
// cannot be properly written.
|
|
||||||
return out
|
|
||||||
case *tc.Basic:
|
|
||||||
out := u.Type(types.Name{
|
|
||||||
Package: "",
|
|
||||||
Name: t.Name(),
|
|
||||||
})
|
|
||||||
if out.Kind != types.Unknown {
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
out.Kind = types.Unsupported
|
|
||||||
return out
|
|
||||||
case *tc.Signature:
|
|
||||||
out := u.Type(name)
|
|
||||||
if out.Kind != types.Unknown {
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
out.Kind = types.Func
|
|
||||||
out.Signature = b.convertSignature(u, t)
|
|
||||||
return out
|
|
||||||
case *tc.Interface:
|
|
||||||
out := u.Type(name)
|
|
||||||
if out.Kind != types.Unknown {
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
out.Kind = types.Interface
|
|
||||||
t.Complete()
|
|
||||||
for i := 0; i < t.NumMethods(); i++ {
|
|
||||||
if out.Methods == nil {
|
|
||||||
out.Methods = map[string]*types.Type{}
|
|
||||||
}
|
|
||||||
method := t.Method(i)
|
|
||||||
name := tcNameToName(method.String())
|
|
||||||
mt := b.walkType(u, &name, method.Type())
|
|
||||||
mt.CommentLines = splitLines(b.priorCommentLines(method.Pos(), 1).Text())
|
|
||||||
out.Methods[method.Name()] = mt
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
case *tc.Named:
|
|
||||||
var out *types.Type
|
|
||||||
switch t.Underlying().(type) {
|
|
||||||
case *tc.Named, *tc.Basic, *tc.Map, *tc.Slice:
|
|
||||||
name := tcNameToName(t.String())
|
|
||||||
out = u.Type(name)
|
|
||||||
if out.Kind != types.Unknown {
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
out.Kind = types.Alias
|
|
||||||
out.Underlying = b.walkType(u, nil, t.Underlying())
|
|
||||||
default:
|
|
||||||
// tc package makes everything "named" with an
|
|
||||||
// underlying anonymous type--we remove that annoying
|
|
||||||
// "feature" for users. This flattens those types
|
|
||||||
// together.
|
|
||||||
name := tcNameToName(t.String())
|
|
||||||
if out := u.Type(name); out.Kind != types.Unknown {
|
|
||||||
return out // short circuit if we've already made this.
|
|
||||||
}
|
|
||||||
out = b.walkType(u, &name, t.Underlying())
|
|
||||||
}
|
|
||||||
// If the underlying type didn't already add methods, add them.
|
|
||||||
// (Interface types will have already added methods.)
|
|
||||||
if len(out.Methods) == 0 {
|
|
||||||
for i := 0; i < t.NumMethods(); i++ {
|
|
||||||
if out.Methods == nil {
|
|
||||||
out.Methods = map[string]*types.Type{}
|
|
||||||
}
|
|
||||||
method := t.Method(i)
|
|
||||||
name := tcNameToName(method.String())
|
|
||||||
mt := b.walkType(u, &name, method.Type())
|
|
||||||
mt.CommentLines = splitLines(b.priorCommentLines(method.Pos(), 1).Text())
|
|
||||||
out.Methods[method.Name()] = mt
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
default:
|
|
||||||
out := u.Type(name)
|
|
||||||
if out.Kind != types.Unknown {
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
out.Kind = types.Unsupported
|
|
||||||
klog.Warningf("Making unsupported type entry %q for: %#v\n", out, t)
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Builder) addFunction(u types.Universe, useName *types.Name, in *tc.Func) *types.Type {
|
|
||||||
name := tcFuncNameToName(in.String())
|
|
||||||
if useName != nil {
|
|
||||||
name = *useName
|
|
||||||
}
|
|
||||||
out := u.Function(name)
|
|
||||||
out.Kind = types.DeclarationOf
|
|
||||||
out.Underlying = b.walkType(u, nil, in.Type())
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Builder) addVariable(u types.Universe, useName *types.Name, in *tc.Var) *types.Type {
|
|
||||||
name := tcVarNameToName(in.String())
|
|
||||||
if useName != nil {
|
|
||||||
name = *useName
|
|
||||||
}
|
|
||||||
out := u.Variable(name)
|
|
||||||
out.Kind = types.DeclarationOf
|
|
||||||
out.Underlying = b.walkType(u, nil, in.Type())
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Builder) addConstant(u types.Universe, useName *types.Name, in *tc.Const) *types.Type {
|
|
||||||
name := tcVarNameToName(in.String())
|
|
||||||
if useName != nil {
|
|
||||||
name = *useName
|
|
||||||
}
|
|
||||||
out := u.Constant(name)
|
|
||||||
out.Kind = types.DeclarationOf
|
|
||||||
out.Underlying = b.walkType(u, nil, in.Type())
|
|
||||||
|
|
||||||
var constval string
|
|
||||||
|
|
||||||
// For strings, we use `StringVal()` to get the un-truncated,
|
|
||||||
// un-quoted string. For other values, `.String()` is preferable to
|
|
||||||
// get something relatively human readable (especially since for
|
|
||||||
// floating point types, `ExactString()` will generate numeric
|
|
||||||
// expressions using `big.(*Float).Text()`.
|
|
||||||
switch in.Val().Kind() {
|
|
||||||
case constant.String:
|
|
||||||
constval = constant.StringVal(in.Val())
|
|
||||||
default:
|
|
||||||
constval = in.Val().String()
|
|
||||||
}
|
|
||||||
|
|
||||||
out.ConstValue = &constval
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// canonicalizeImportPath takes an import path and returns the actual package.
|
|
||||||
// It doesn't support nested vendoring.
|
|
||||||
func canonicalizeImportPath(importPath string) importPathString {
|
|
||||||
if !strings.Contains(importPath, "/vendor/") {
|
|
||||||
return importPathString(importPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
return importPathString(importPath[strings.Index(importPath, "/vendor/")+len("/vendor/"):])
|
|
||||||
}
|
|
|
@ -1,82 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2015 The Kubernetes Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Package types contains go type information, packaged in a way that makes
|
|
||||||
// auto-generation convenient, whether by template or straight go functions.
|
|
||||||
package types
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ExtractCommentTags parses comments for lines of the form:
|
|
||||||
//
|
|
||||||
// 'marker' + "key=value".
|
|
||||||
//
|
|
||||||
// Values are optional; "" is the default. A tag can be specified more than
|
|
||||||
// one time and all values are returned. If the resulting map has an entry for
|
|
||||||
// a key, the value (a slice) is guaranteed to have at least 1 element.
|
|
||||||
//
|
|
||||||
// Example: if you pass "+" for 'marker', and the following lines are in
|
|
||||||
// the comments:
|
|
||||||
// +foo=value1
|
|
||||||
// +bar
|
|
||||||
// +foo=value2
|
|
||||||
// +baz="qux"
|
|
||||||
// Then this function will return:
|
|
||||||
// map[string][]string{"foo":{"value1, "value2"}, "bar": {""}, "baz": {"qux"}}
|
|
||||||
func ExtractCommentTags(marker string, lines []string) map[string][]string {
|
|
||||||
out := map[string][]string{}
|
|
||||||
for _, line := range lines {
|
|
||||||
line = strings.Trim(line, " ")
|
|
||||||
if len(line) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !strings.HasPrefix(line, marker) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// TODO: we could support multiple values per key if we split on spaces
|
|
||||||
kv := strings.SplitN(line[len(marker):], "=", 2)
|
|
||||||
if len(kv) == 2 {
|
|
||||||
out[kv[0]] = append(out[kv[0]], kv[1])
|
|
||||||
} else if len(kv) == 1 {
|
|
||||||
out[kv[0]] = append(out[kv[0]], "")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExtractSingleBoolCommentTag parses comments for lines of the form:
|
|
||||||
//
|
|
||||||
// 'marker' + "key=value1"
|
|
||||||
//
|
|
||||||
// If the tag is not found, the default value is returned. Values are asserted
|
|
||||||
// to be boolean ("true" or "false"), and any other value will cause an error
|
|
||||||
// to be returned. If the key has multiple values, the first one will be used.
|
|
||||||
func ExtractSingleBoolCommentTag(marker string, key string, defaultVal bool, lines []string) (bool, error) {
|
|
||||||
values := ExtractCommentTags(marker, lines)[key]
|
|
||||||
if values == nil {
|
|
||||||
return defaultVal, nil
|
|
||||||
}
|
|
||||||
if values[0] == "true" {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
if values[0] == "false" {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
return false, fmt.Errorf("tag value for %q is not boolean: %q", key, values[0])
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2015 The Kubernetes Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Package types contains go type information, packaged in a way that makes
|
|
||||||
// auto-generation convenient, whether by template or straight go functions.
|
|
||||||
package types // import "k8s.io/gengo/types"
|
|
|
@ -1,57 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2015 The Kubernetes Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package types
|
|
||||||
|
|
||||||
// FlattenMembers recursively takes any embedded members and puts them in the
|
|
||||||
// top level, correctly hiding them if the top level hides them. There must not
|
|
||||||
// be a cycle-- that implies infinite members.
|
|
||||||
//
|
|
||||||
// This is useful for e.g. computing all the valid keys in a json struct,
|
|
||||||
// properly considering any configuration of embedded structs.
|
|
||||||
func FlattenMembers(m []Member) []Member {
|
|
||||||
embedded := []Member{}
|
|
||||||
normal := []Member{}
|
|
||||||
type nameInfo struct {
|
|
||||||
top bool
|
|
||||||
i int
|
|
||||||
}
|
|
||||||
names := map[string]nameInfo{}
|
|
||||||
for i := range m {
|
|
||||||
if m[i].Embedded && m[i].Type.Kind == Struct {
|
|
||||||
embedded = append(embedded, m[i])
|
|
||||||
} else {
|
|
||||||
normal = append(normal, m[i])
|
|
||||||
names[m[i].Name] = nameInfo{true, len(normal) - 1}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for i := range embedded {
|
|
||||||
for _, e := range FlattenMembers(embedded[i].Type.Members) {
|
|
||||||
if info, found := names[e.Name]; found {
|
|
||||||
if info.top {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if n := normal[info.i]; n.Name == e.Name && n.Type == e.Type {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
panic("conflicting members")
|
|
||||||
}
|
|
||||||
normal = append(normal, e)
|
|
||||||
names[e.Name] = nameInfo{false, len(normal) - 1}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return normal
|
|
||||||
}
|
|
|
@ -1,537 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2015 The Kubernetes Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package types
|
|
||||||
|
|
||||||
import "strings"
|
|
||||||
|
|
||||||
// Ref makes a reference to the given type. It can only be used for e.g.
|
|
||||||
// passing to namers.
|
|
||||||
func Ref(packageName, typeName string) *Type {
|
|
||||||
return &Type{Name: Name{
|
|
||||||
Name: typeName,
|
|
||||||
Package: packageName,
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
|
|
||||||
// A type name may have a package qualifier.
|
|
||||||
type Name struct {
|
|
||||||
// Empty if embedded or builtin. This is the package path unless Path is specified.
|
|
||||||
Package string
|
|
||||||
// The type name.
|
|
||||||
Name string
|
|
||||||
// An optional location of the type definition for languages that can have disjoint
|
|
||||||
// packages and paths.
|
|
||||||
Path string
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns the name formatted as a string.
|
|
||||||
func (n Name) String() string {
|
|
||||||
if n.Package == "" {
|
|
||||||
return n.Name
|
|
||||||
}
|
|
||||||
return n.Package + "." + n.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseFullyQualifiedName parses a name like k8s.io/kubernetes/pkg/api.Pod into a Name.
|
|
||||||
func ParseFullyQualifiedName(fqn string) Name {
|
|
||||||
cs := strings.Split(fqn, ".")
|
|
||||||
pkg := ""
|
|
||||||
if len(cs) > 1 {
|
|
||||||
pkg = strings.Join(cs[0:len(cs)-1], ".")
|
|
||||||
}
|
|
||||||
return Name{
|
|
||||||
Name: cs[len(cs)-1],
|
|
||||||
Package: pkg,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The possible classes of types.
|
|
||||||
type Kind string
|
|
||||||
|
|
||||||
const (
|
|
||||||
// Builtin is a primitive, like bool, string, int.
|
|
||||||
Builtin Kind = "Builtin"
|
|
||||||
Struct Kind = "Struct"
|
|
||||||
Map Kind = "Map"
|
|
||||||
Slice Kind = "Slice"
|
|
||||||
Pointer Kind = "Pointer"
|
|
||||||
|
|
||||||
// Alias is an alias of another type, e.g. in:
|
|
||||||
// type Foo string
|
|
||||||
// type Bar Foo
|
|
||||||
// Bar is an alias of Foo.
|
|
||||||
//
|
|
||||||
// In the real go type system, Foo is a "Named" string; but to simplify
|
|
||||||
// generation, this type system will just say that Foo *is* a builtin.
|
|
||||||
// We then need "Alias" as a way for us to say that Bar *is* a Foo.
|
|
||||||
Alias Kind = "Alias"
|
|
||||||
|
|
||||||
// Interface is any type that could have differing types at run time.
|
|
||||||
Interface Kind = "Interface"
|
|
||||||
|
|
||||||
// Array is just like slice, but has a fixed length.
|
|
||||||
Array Kind = "Array"
|
|
||||||
|
|
||||||
// The remaining types are included for completeness, but are not well
|
|
||||||
// supported.
|
|
||||||
Chan Kind = "Chan"
|
|
||||||
Func Kind = "Func"
|
|
||||||
|
|
||||||
// DeclarationOf is different from other Kinds; it indicates that instead of
|
|
||||||
// representing an actual Type, the type is a declaration of an instance of
|
|
||||||
// a type. E.g., a top-level function, variable, or constant. See the
|
|
||||||
// comment for Type.Name for more detail.
|
|
||||||
DeclarationOf Kind = "DeclarationOf"
|
|
||||||
Unknown Kind = ""
|
|
||||||
Unsupported Kind = "Unsupported"
|
|
||||||
|
|
||||||
// Protobuf is protobuf type.
|
|
||||||
Protobuf Kind = "Protobuf"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Package holds package-level information.
|
|
||||||
// Fields are public, as everything in this package, to enable consumption by
|
|
||||||
// templates (for example). But it is strongly encouraged for code to build by
|
|
||||||
// using the provided functions.
|
|
||||||
type Package struct {
|
|
||||||
// Canonical name of this package-- its path.
|
|
||||||
Path string
|
|
||||||
|
|
||||||
// The location this package was loaded from
|
|
||||||
SourcePath string
|
|
||||||
|
|
||||||
// Short name of this package; the name that appears in the
|
|
||||||
// 'package x' line.
|
|
||||||
Name string
|
|
||||||
|
|
||||||
// The comment right above the package declaration in doc.go, if any.
|
|
||||||
DocComments []string
|
|
||||||
|
|
||||||
// All comments from doc.go, if any.
|
|
||||||
// TODO: remove Comments and use DocComments everywhere.
|
|
||||||
Comments []string
|
|
||||||
|
|
||||||
// Types within this package, indexed by their name (*not* including
|
|
||||||
// package name).
|
|
||||||
Types map[string]*Type
|
|
||||||
|
|
||||||
// Functions within this package, indexed by their name (*not* including
|
|
||||||
// package name).
|
|
||||||
Functions map[string]*Type
|
|
||||||
|
|
||||||
// Global variables within this package, indexed by their name (*not* including
|
|
||||||
// package name).
|
|
||||||
Variables map[string]*Type
|
|
||||||
|
|
||||||
// Global constants within this package, indexed by their name (*not* including
|
|
||||||
// package name).
|
|
||||||
Constants map[string]*Type
|
|
||||||
|
|
||||||
// Packages imported by this package, indexed by (canonicalized)
|
|
||||||
// package path.
|
|
||||||
Imports map[string]*Package
|
|
||||||
}
|
|
||||||
|
|
||||||
// Has returns true if the given name references a type known to this package.
|
|
||||||
func (p *Package) Has(name string) bool {
|
|
||||||
_, has := p.Types[name]
|
|
||||||
return has
|
|
||||||
}
|
|
||||||
|
|
||||||
// Type gets the given Type in this Package. If the Type is not already
|
|
||||||
// defined, this will add it and return the new Type value. The caller is
|
|
||||||
// expected to finish initialization.
|
|
||||||
func (p *Package) Type(typeName string) *Type {
|
|
||||||
if t, ok := p.Types[typeName]; ok {
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
if p.Path == "" {
|
|
||||||
// Import the standard builtin types!
|
|
||||||
if t, ok := builtins.Types[typeName]; ok {
|
|
||||||
p.Types[typeName] = t
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
t := &Type{Name: Name{Package: p.Path, Name: typeName}}
|
|
||||||
p.Types[typeName] = t
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function gets the given function Type in this Package. If the function is
|
|
||||||
// not already defined, this will add it. If a function is added, it's the
|
|
||||||
// caller's responsibility to finish construction of the function by setting
|
|
||||||
// Underlying to the correct type.
|
|
||||||
func (p *Package) Function(funcName string) *Type {
|
|
||||||
if t, ok := p.Functions[funcName]; ok {
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
t := &Type{Name: Name{Package: p.Path, Name: funcName}}
|
|
||||||
t.Kind = DeclarationOf
|
|
||||||
p.Functions[funcName] = t
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
|
|
||||||
// Variable gets the given variable Type in this Package. If the variable is
|
|
||||||
// not already defined, this will add it. If a variable is added, it's the caller's
|
|
||||||
// responsibility to finish construction of the variable by setting Underlying
|
|
||||||
// to the correct type.
|
|
||||||
func (p *Package) Variable(varName string) *Type {
|
|
||||||
if t, ok := p.Variables[varName]; ok {
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
t := &Type{Name: Name{Package: p.Path, Name: varName}}
|
|
||||||
t.Kind = DeclarationOf
|
|
||||||
p.Variables[varName] = t
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
|
|
||||||
// Constant gets the given constant Type in this Package. If the constant is
|
|
||||||
// not already defined, this will add it. If a constant is added, it's the caller's
|
|
||||||
// responsibility to finish construction of the constant by setting Underlying
|
|
||||||
// to the correct type.
|
|
||||||
func (p *Package) Constant(constName string) *Type {
|
|
||||||
if t, ok := p.Constants[constName]; ok {
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
t := &Type{Name: Name{Package: p.Path, Name: constName}}
|
|
||||||
t.Kind = DeclarationOf
|
|
||||||
p.Constants[constName] = t
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasImport returns true if p imports packageName. Package names include the
|
|
||||||
// package directory.
|
|
||||||
func (p *Package) HasImport(packageName string) bool {
|
|
||||||
_, has := p.Imports[packageName]
|
|
||||||
return has
|
|
||||||
}
|
|
||||||
|
|
||||||
// Universe is a map of all packages. The key is the package name, but you
|
|
||||||
// should use Package(), Type(), Function(), or Variable() instead of direct
|
|
||||||
// access.
|
|
||||||
type Universe map[string]*Package
|
|
||||||
|
|
||||||
// Type returns the canonical type for the given fully-qualified name. Builtin
|
|
||||||
// types will always be found, even if they haven't been explicitly added to
|
|
||||||
// the map. If a non-existing type is requested, this will create (a marker for)
|
|
||||||
// it.
|
|
||||||
func (u Universe) Type(n Name) *Type {
|
|
||||||
return u.Package(n.Package).Type(n.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function returns the canonical function for the given fully-qualified name.
|
|
||||||
// If a non-existing function is requested, this will create (a marker for) it.
|
|
||||||
// If a marker is created, it's the caller's responsibility to finish
|
|
||||||
// construction of the function by setting Underlying to the correct type.
|
|
||||||
func (u Universe) Function(n Name) *Type {
|
|
||||||
return u.Package(n.Package).Function(n.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Variable returns the canonical variable for the given fully-qualified name.
|
|
||||||
// If a non-existing variable is requested, this will create (a marker for) it.
|
|
||||||
// If a marker is created, it's the caller's responsibility to finish
|
|
||||||
// construction of the variable by setting Underlying to the correct type.
|
|
||||||
func (u Universe) Variable(n Name) *Type {
|
|
||||||
return u.Package(n.Package).Variable(n.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Constant returns the canonical constant for the given fully-qualified name.
|
|
||||||
// If a non-existing constant is requested, this will create (a marker for) it.
|
|
||||||
// If a marker is created, it's the caller's responsibility to finish
|
|
||||||
// construction of the constant by setting Underlying to the correct type.
|
|
||||||
func (u Universe) Constant(n Name) *Type {
|
|
||||||
return u.Package(n.Package).Constant(n.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddImports registers import lines for packageName. May be called multiple times.
|
|
||||||
// You are responsible for canonicalizing all package paths.
|
|
||||||
func (u Universe) AddImports(packagePath string, importPaths ...string) {
|
|
||||||
p := u.Package(packagePath)
|
|
||||||
for _, i := range importPaths {
|
|
||||||
p.Imports[i] = u.Package(i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Package returns the Package for the given path.
|
|
||||||
// If a non-existing package is requested, this will create (a marker for) it.
|
|
||||||
// If a marker is created, it's the caller's responsibility to finish
|
|
||||||
// construction of the package.
|
|
||||||
func (u Universe) Package(packagePath string) *Package {
|
|
||||||
if p, ok := u[packagePath]; ok {
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
p := &Package{
|
|
||||||
Path: packagePath,
|
|
||||||
Types: map[string]*Type{},
|
|
||||||
Functions: map[string]*Type{},
|
|
||||||
Variables: map[string]*Type{},
|
|
||||||
Constants: map[string]*Type{},
|
|
||||||
Imports: map[string]*Package{},
|
|
||||||
}
|
|
||||||
u[packagePath] = p
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// Type represents a subset of possible go types.
|
|
||||||
type Type struct {
|
|
||||||
// There are two general categories of types, those explicitly named
|
|
||||||
// and those anonymous. Named ones will have a non-empty package in the
|
|
||||||
// name field.
|
|
||||||
//
|
|
||||||
// An exception: If Kind == DeclarationOf, then this name is the name of a
|
|
||||||
// top-level function, variable, or const, and the type can be found in Underlying.
|
|
||||||
// We do this to allow the naming system to work against these objects, even
|
|
||||||
// though they aren't strictly speaking types.
|
|
||||||
Name Name
|
|
||||||
|
|
||||||
// The general kind of this type.
|
|
||||||
Kind Kind
|
|
||||||
|
|
||||||
// If there are comment lines immediately before the type definition,
|
|
||||||
// they will be recorded here.
|
|
||||||
CommentLines []string
|
|
||||||
|
|
||||||
// If there are comment lines preceding the `CommentLines`, they will be
|
|
||||||
// recorded here. There are two cases:
|
|
||||||
// ---
|
|
||||||
// SecondClosestCommentLines
|
|
||||||
// a blank line
|
|
||||||
// CommentLines
|
|
||||||
// type definition
|
|
||||||
// ---
|
|
||||||
//
|
|
||||||
// or
|
|
||||||
// ---
|
|
||||||
// SecondClosestCommentLines
|
|
||||||
// a blank line
|
|
||||||
// type definition
|
|
||||||
// ---
|
|
||||||
SecondClosestCommentLines []string
|
|
||||||
|
|
||||||
// If Kind == Struct
|
|
||||||
Members []Member
|
|
||||||
|
|
||||||
// If Kind == Map, Slice, Pointer, or Chan
|
|
||||||
Elem *Type
|
|
||||||
|
|
||||||
// If Kind == Map, this is the map's key type.
|
|
||||||
Key *Type
|
|
||||||
|
|
||||||
// If Kind == Alias, this is the underlying type.
|
|
||||||
// If Kind == DeclarationOf, this is the type of the declaration.
|
|
||||||
Underlying *Type
|
|
||||||
|
|
||||||
// If Kind == Interface, this is the set of all required functions.
|
|
||||||
// Otherwise, if this is a named type, this is the list of methods that
|
|
||||||
// type has. (All elements will have Kind=="Func")
|
|
||||||
Methods map[string]*Type
|
|
||||||
|
|
||||||
// If Kind == func, this is the signature of the function.
|
|
||||||
Signature *Signature
|
|
||||||
|
|
||||||
// ConstValue contains a stringified constant value if
|
|
||||||
// Kind == DeclarationOf and this is a constant value
|
|
||||||
// declaration. For string constants, this field contains
|
|
||||||
// the entire, un-quoted value. For other types, it contains
|
|
||||||
// a human-readable literal.
|
|
||||||
ConstValue *string
|
|
||||||
|
|
||||||
// TODO: Add:
|
|
||||||
// * channel direction
|
|
||||||
|
|
||||||
// If Kind == Array
|
|
||||||
Len int64
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns the name of the type.
|
|
||||||
func (t *Type) String() string {
|
|
||||||
return t.Name.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsPrimitive returns whether the type is a built-in type or is an alias to a
|
|
||||||
// built-in type. For example: strings and aliases of strings are primitives,
|
|
||||||
// structs are not.
|
|
||||||
func (t *Type) IsPrimitive() bool {
|
|
||||||
if t.Kind == Builtin || (t.Kind == Alias && t.Underlying.Kind == Builtin) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsAssignable returns whether the type is deep-assignable. For example,
|
|
||||||
// slices and maps and pointers are shallow copies, but ints and strings are
|
|
||||||
// complete.
|
|
||||||
func (t *Type) IsAssignable() bool {
|
|
||||||
if t.IsPrimitive() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if t.Kind == Struct {
|
|
||||||
for _, m := range t.Members {
|
|
||||||
if !m.Type.IsAssignable() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsAnonymousStruct returns true if the type is an anonymous struct or an alias
|
|
||||||
// to an anonymous struct.
|
|
||||||
func (t *Type) IsAnonymousStruct() bool {
|
|
||||||
return (t.Kind == Struct && t.Name.Name == "struct{}") || (t.Kind == Alias && t.Underlying.IsAnonymousStruct())
|
|
||||||
}
|
|
||||||
|
|
||||||
// A single struct member
|
|
||||||
type Member struct {
|
|
||||||
// The name of the member.
|
|
||||||
Name string
|
|
||||||
|
|
||||||
// If the member is embedded (anonymous) this will be true, and the
|
|
||||||
// Name will be the type name.
|
|
||||||
Embedded bool
|
|
||||||
|
|
||||||
// If there are comment lines immediately before the member in the type
|
|
||||||
// definition, they will be recorded here.
|
|
||||||
CommentLines []string
|
|
||||||
|
|
||||||
// If there are tags along with this member, they will be saved here.
|
|
||||||
Tags string
|
|
||||||
|
|
||||||
// The type of this member.
|
|
||||||
Type *Type
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns the name and type of the member.
|
|
||||||
func (m Member) String() string {
|
|
||||||
return m.Name + " " + m.Type.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Signature is a function's signature.
|
|
||||||
type Signature struct {
|
|
||||||
// If a method of some type, this is the type it's a member of.
|
|
||||||
Receiver *Type
|
|
||||||
Parameters []*Type
|
|
||||||
ParameterNames []string
|
|
||||||
Results []*Type
|
|
||||||
ResultNames []string
|
|
||||||
|
|
||||||
// True if the last in parameter is of the form ...T.
|
|
||||||
Variadic bool
|
|
||||||
|
|
||||||
// If there are comment lines immediately before this
|
|
||||||
// signature/method/function declaration, they will be recorded here.
|
|
||||||
CommentLines []string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Built in types.
|
|
||||||
var (
|
|
||||||
String = &Type{
|
|
||||||
Name: Name{Name: "string"},
|
|
||||||
Kind: Builtin,
|
|
||||||
}
|
|
||||||
Int64 = &Type{
|
|
||||||
Name: Name{Name: "int64"},
|
|
||||||
Kind: Builtin,
|
|
||||||
}
|
|
||||||
Int32 = &Type{
|
|
||||||
Name: Name{Name: "int32"},
|
|
||||||
Kind: Builtin,
|
|
||||||
}
|
|
||||||
Int16 = &Type{
|
|
||||||
Name: Name{Name: "int16"},
|
|
||||||
Kind: Builtin,
|
|
||||||
}
|
|
||||||
Int = &Type{
|
|
||||||
Name: Name{Name: "int"},
|
|
||||||
Kind: Builtin,
|
|
||||||
}
|
|
||||||
Uint64 = &Type{
|
|
||||||
Name: Name{Name: "uint64"},
|
|
||||||
Kind: Builtin,
|
|
||||||
}
|
|
||||||
Uint32 = &Type{
|
|
||||||
Name: Name{Name: "uint32"},
|
|
||||||
Kind: Builtin,
|
|
||||||
}
|
|
||||||
Uint16 = &Type{
|
|
||||||
Name: Name{Name: "uint16"},
|
|
||||||
Kind: Builtin,
|
|
||||||
}
|
|
||||||
Uint = &Type{
|
|
||||||
Name: Name{Name: "uint"},
|
|
||||||
Kind: Builtin,
|
|
||||||
}
|
|
||||||
Uintptr = &Type{
|
|
||||||
Name: Name{Name: "uintptr"},
|
|
||||||
Kind: Builtin,
|
|
||||||
}
|
|
||||||
Float64 = &Type{
|
|
||||||
Name: Name{Name: "float64"},
|
|
||||||
Kind: Builtin,
|
|
||||||
}
|
|
||||||
Float32 = &Type{
|
|
||||||
Name: Name{Name: "float32"},
|
|
||||||
Kind: Builtin,
|
|
||||||
}
|
|
||||||
Float = &Type{
|
|
||||||
Name: Name{Name: "float"},
|
|
||||||
Kind: Builtin,
|
|
||||||
}
|
|
||||||
Bool = &Type{
|
|
||||||
Name: Name{Name: "bool"},
|
|
||||||
Kind: Builtin,
|
|
||||||
}
|
|
||||||
Byte = &Type{
|
|
||||||
Name: Name{Name: "byte"},
|
|
||||||
Kind: Builtin,
|
|
||||||
}
|
|
||||||
|
|
||||||
builtins = &Package{
|
|
||||||
Types: map[string]*Type{
|
|
||||||
"bool": Bool,
|
|
||||||
"string": String,
|
|
||||||
"int": Int,
|
|
||||||
"int64": Int64,
|
|
||||||
"int32": Int32,
|
|
||||||
"int16": Int16,
|
|
||||||
"int8": Byte,
|
|
||||||
"uint": Uint,
|
|
||||||
"uint64": Uint64,
|
|
||||||
"uint32": Uint32,
|
|
||||||
"uint16": Uint16,
|
|
||||||
"uint8": Byte,
|
|
||||||
"uintptr": Uintptr,
|
|
||||||
"byte": Byte,
|
|
||||||
"float": Float,
|
|
||||||
"float64": Float64,
|
|
||||||
"float32": Float32,
|
|
||||||
},
|
|
||||||
Imports: map[string]*Package{},
|
|
||||||
Path: "",
|
|
||||||
Name: "",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func IsInteger(t *Type) bool {
|
|
||||||
switch t {
|
|
||||||
case Int, Int64, Int32, Int16, Uint, Uint64, Uint32, Uint16, Byte:
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2019 The Knative Authors.
|
Copyright 2019 The Knative Authors
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -18,55 +18,83 @@ package args
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"k8s.io/gengo/v2"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
"k8s.io/gengo/args"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// CustomArgs is used by the gengo framework to pass args specific to this generator.
|
// Args is used by the gengo framework to pass args specific to this generator.
|
||||||
type CustomArgs struct {
|
type Args struct {
|
||||||
|
InputDirs []string
|
||||||
|
OutputPackagePath string
|
||||||
|
OutputDir string
|
||||||
|
GoHeaderFilePath string
|
||||||
|
|
||||||
VersionedClientSetPackage string
|
VersionedClientSetPackage string
|
||||||
ExternalVersionsInformersPackage string
|
ExternalVersionsInformersPackage string
|
||||||
ListersPackage string
|
ListersPackage string
|
||||||
ForceKinds string
|
ForceKinds string
|
||||||
ListerHasPointerElem bool
|
ListerHasPointerElem bool
|
||||||
DisableInformerInit bool
|
DisableInformerInit bool
|
||||||
|
|
||||||
|
// PluralExceptions define a list of pluralizer exceptions in Type:PluralType format.
|
||||||
|
// The default list is "Endpoints:Endpoints"
|
||||||
|
PluralExceptions []string
|
||||||
|
|
||||||
|
Boilerplate []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDefaults returns default arguments for the generator.
|
func New() *Args {
|
||||||
func NewDefaults() (*args.GeneratorArgs, *CustomArgs) {
|
return &Args{}
|
||||||
genericArgs := args.Default().WithoutDefaultFlagParsing()
|
|
||||||
customArgs := &CustomArgs{}
|
|
||||||
genericArgs.CustomArgs = customArgs
|
|
||||||
return genericArgs, customArgs
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddFlags add the generator flags to the flag set.
|
// AddFlags add the generator flags to the flag set.
|
||||||
func (ca *CustomArgs) AddFlags(fs *pflag.FlagSet) {
|
func (a *Args) AddFlags(fs *pflag.FlagSet) {
|
||||||
fs.StringVar(&ca.VersionedClientSetPackage, "versioned-clientset-package", ca.VersionedClientSetPackage, "the full package name for the versioned injection clientset to use")
|
fs.StringSliceVarP(&a.InputDirs, "input-dirs", "i", a.InputDirs, "Comma-separated list of import paths to get input types from.")
|
||||||
fs.StringVar(&ca.ExternalVersionsInformersPackage, "external-versions-informers-package", ca.ExternalVersionsInformersPackage, "the full package name for the external versions injection informer to use")
|
fs.StringVarP(&a.OutputPackagePath, "output-package", "p", a.OutputPackagePath, "Base package path.")
|
||||||
fs.StringVar(&ca.ListersPackage, "listers-package", ca.ListersPackage, "the full package name for client listers to use")
|
fs.StringVarP(&a.OutputDir, "output-dir", "o", a.OutputDir, "Output directory.")
|
||||||
fs.StringVar(&ca.ForceKinds, "force-genreconciler-kinds", ca.ForceKinds, `force kinds will override the genreconciler tag setting for the given set of kinds, comma separated: "Foo,Bar,Baz"`)
|
fs.StringVarP(&a.GoHeaderFilePath, "go-header-file", "h", a.GoHeaderFilePath, "File containing boilerplate header text. The string YEAR will be replaced with the current 4-digit year.")
|
||||||
|
|
||||||
fs.BoolVar(&ca.ListerHasPointerElem, "lister-has-pointer-elem", false, "")
|
fs.StringVar(&a.VersionedClientSetPackage, "versioned-clientset-package", a.VersionedClientSetPackage, "the full package name for the versioned injection clientset to use")
|
||||||
|
fs.StringVar(&a.ExternalVersionsInformersPackage, "external-versions-informers-package", a.ExternalVersionsInformersPackage, "the full package name for the external versions injection informer to use")
|
||||||
|
fs.StringVar(&a.ListersPackage, "listers-package", a.ListersPackage, "the full package name for client listers to use")
|
||||||
|
fs.StringVar(&a.ForceKinds, "force-genreconciler-kinds", a.ForceKinds, `force kinds will override the genreconciler tag setting for the given set of kinds, comma separated: "Foo,Bar,Baz"`)
|
||||||
|
|
||||||
|
fs.BoolVar(&a.ListerHasPointerElem, "lister-has-pointer-elem", false, "")
|
||||||
fs.MarkDeprecated("lister-has-pointer-elem", "this flag has no effect")
|
fs.MarkDeprecated("lister-has-pointer-elem", "this flag has no effect")
|
||||||
|
|
||||||
fs.BoolVar(&ca.DisableInformerInit, "disable-informer-init", false, "disable generating the init function for the informer")
|
fs.BoolVar(&a.DisableInformerInit, "disable-informer-init", false, "disable generating the init function for the informer")
|
||||||
|
fs.StringSliceVar(&a.PluralExceptions, "plural-exceptions", a.PluralExceptions,
|
||||||
|
"list of comma separated plural exception definitions in Type:PluralizedType format")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate checks the given arguments.
|
// Validate checks the given arguments.
|
||||||
func Validate(genericArgs *args.GeneratorArgs) error {
|
func (a *Args) Validate() error {
|
||||||
customArgs := genericArgs.CustomArgs.(*CustomArgs)
|
var err error
|
||||||
|
a.Boilerplate, err = gengo.GoBoilerplate(a.GoHeaderFilePath, "", gengo.StdGeneratedBy)
|
||||||
|
if err != nil {
|
||||||
|
klog.Fatalf("Failed loading boilerplate: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
if len(genericArgs.OutputPackagePath) == 0 {
|
if len(a.OutputPackagePath) == 0 {
|
||||||
return errors.New("output package cannot be empty")
|
return errors.New("output package cannot be empty")
|
||||||
}
|
}
|
||||||
if len(customArgs.VersionedClientSetPackage) == 0 {
|
if len(a.VersionedClientSetPackage) == 0 {
|
||||||
return errors.New("versioned clientset package cannot be empty")
|
return errors.New("versioned clientset package cannot be empty")
|
||||||
}
|
}
|
||||||
if len(customArgs.ExternalVersionsInformersPackage) == 0 {
|
if len(a.ExternalVersionsInformersPackage) == 0 {
|
||||||
return errors.New("external versions informers package cannot be empty")
|
return errors.New("external versions informers package cannot be empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *Args) GetOutputDir() string {
|
||||||
|
return filepath.Clean(a.OutputDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Args) GetOutputPackagePath() string {
|
||||||
|
return filepath.Clean(a.OutputPackagePath)
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2019 The Knative Authors.
|
Copyright 2019 The Knative Authors
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -14,21 +14,35 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package generators
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
"k8s.io/gengo/generator"
|
"k8s.io/gengo/v2/generator"
|
||||||
"k8s.io/gengo/namer"
|
"k8s.io/gengo/v2/namer"
|
||||||
"k8s.io/gengo/types"
|
"k8s.io/gengo/v2/types"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
|
"knative.dev/pkg/codegen/cmd/injection-gen/args"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// New creates a new clientGenerator with the given args
|
||||||
|
func New(args *args.Args) *clientGenerator {
|
||||||
|
return &clientGenerator{
|
||||||
|
GoGenerator: generator.GoGenerator{
|
||||||
|
OutputFilename: "client.go",
|
||||||
|
},
|
||||||
|
outputPackage: filepath.Join(args.OutputPackagePath, "client"),
|
||||||
|
imports: generator.NewImportTracker(),
|
||||||
|
clientSetPackage: args.VersionedClientSetPackage,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// clientGenerator produces a file of listers for a given GroupVersion and
|
// clientGenerator produces a file of listers for a given GroupVersion and
|
||||||
// type.
|
// type.
|
||||||
type clientGenerator struct {
|
type clientGenerator struct {
|
||||||
generator.DefaultGen
|
generator.GoGenerator
|
||||||
|
|
||||||
outputPackage string
|
outputPackage string
|
||||||
imports namer.ImportTracker
|
imports namer.ImportTracker
|
||||||
|
@ -36,6 +50,10 @@ type clientGenerator struct {
|
||||||
filtered bool
|
filtered bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *clientGenerator) OutputPackagePath() string {
|
||||||
|
return g.outputPackage
|
||||||
|
}
|
||||||
|
|
||||||
var _ generator.Generator = (*clientGenerator)(nil)
|
var _ generator.Generator = (*clientGenerator)(nil)
|
||||||
|
|
||||||
func (g *clientGenerator) Filter(c *generator.Context, t *types.Type) bool {
|
func (g *clientGenerator) Filter(c *generator.Context, t *types.Type) bool {
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2019 The Knative Authors.
|
Copyright 2019 The Knative Authors
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -14,21 +14,36 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package generators
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
"k8s.io/gengo/generator"
|
"k8s.io/gengo/v2/generator"
|
||||||
"k8s.io/gengo/namer"
|
"k8s.io/gengo/v2/namer"
|
||||||
"k8s.io/gengo/types"
|
"k8s.io/gengo/v2/types"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
|
"knative.dev/pkg/codegen/cmd/injection-gen/args"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func NewFake(args *args.Args) *fakeClientGenerator {
|
||||||
|
client := New(args)
|
||||||
|
return &fakeClientGenerator{
|
||||||
|
GoGenerator: generator.GoGenerator{
|
||||||
|
OutputFilename: "fake.go",
|
||||||
|
},
|
||||||
|
clientInjectionPkg: client.OutputPackagePath(),
|
||||||
|
fakeClientPkg: filepath.Join(args.VersionedClientSetPackage, "fake"),
|
||||||
|
imports: generator.NewImportTracker(),
|
||||||
|
outputPackage: filepath.Join(args.OutputPackagePath, "client", "fake"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// fakeClientGenerator produces a file of listers for a given GroupVersion and
|
// fakeClientGenerator produces a file of listers for a given GroupVersion and
|
||||||
// type.
|
// type.
|
||||||
type fakeClientGenerator struct {
|
type fakeClientGenerator struct {
|
||||||
generator.DefaultGen
|
generator.GoGenerator
|
||||||
outputPackage string
|
outputPackage string
|
||||||
imports namer.ImportTracker
|
imports namer.ImportTracker
|
||||||
filtered bool
|
filtered bool
|
||||||
|
@ -37,6 +52,10 @@ type fakeClientGenerator struct {
|
||||||
clientInjectionPkg string
|
clientInjectionPkg string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *fakeClientGenerator) OutputPackagePath() string {
|
||||||
|
return g.outputPackage
|
||||||
|
}
|
||||||
|
|
||||||
var _ generator.Generator = (*fakeClientGenerator)(nil)
|
var _ generator.Generator = (*fakeClientGenerator)(nil)
|
||||||
|
|
||||||
func (g *fakeClientGenerator) Filter(c *generator.Context, t *types.Type) bool {
|
func (g *fakeClientGenerator) Filter(c *generator.Context, t *types.Type) bool {
|
60
vendor/knative.dev/pkg/codegen/cmd/injection-gen/generators/client/targets.go
vendored
Normal file
60
vendor/knative.dev/pkg/codegen/cmd/injection-gen/generators/client/targets.go
vendored
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
Copyright 2025 The Knative Authors
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"k8s.io/gengo/v2/generator"
|
||||||
|
"k8s.io/gengo/v2/types"
|
||||||
|
"knative.dev/pkg/codegen/cmd/injection-gen/args"
|
||||||
|
"knative.dev/pkg/codegen/cmd/injection-gen/tags"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Targets(args *args.Args) []generator.Target {
|
||||||
|
packagePath := filepath.Join(args.GetOutputPackagePath(), "client")
|
||||||
|
packageDir := filepath.Join(args.GetOutputDir(), "client")
|
||||||
|
|
||||||
|
return []generator.Target{
|
||||||
|
&generator.SimpleTarget{
|
||||||
|
PkgName: "client",
|
||||||
|
PkgPath: packagePath,
|
||||||
|
PkgDir: packageDir,
|
||||||
|
HeaderComment: args.Boilerplate,
|
||||||
|
GeneratorsFunc: func(c *generator.Context) []generator.Generator {
|
||||||
|
return []generator.Generator{New(args)}
|
||||||
|
},
|
||||||
|
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
||||||
|
tags := tags.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||||
|
return tags.NeedsInformerInjection()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&generator.SimpleTarget{
|
||||||
|
PkgName: "fake",
|
||||||
|
PkgPath: filepath.Join(packagePath, "fake"),
|
||||||
|
PkgDir: filepath.Join(packageDir, "fake"),
|
||||||
|
HeaderComment: args.Boilerplate,
|
||||||
|
GeneratorsFunc: func(c *generator.Context) []generator.Generator {
|
||||||
|
return []generator.Generator{NewFake(args)}
|
||||||
|
},
|
||||||
|
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
||||||
|
tags := tags.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||||
|
return tags.NeedsInformerInjection()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2019 The Knative Authors.
|
Copyright 2019 The Knative Authors
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -14,22 +14,24 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package generators
|
package duck
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
|
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
|
||||||
"k8s.io/gengo/generator"
|
"k8s.io/gengo/v2/generator"
|
||||||
"k8s.io/gengo/namer"
|
"k8s.io/gengo/v2/namer"
|
||||||
"k8s.io/gengo/types"
|
"k8s.io/gengo/v2/types"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
|
gennamer "knative.dev/pkg/codegen/cmd/injection-gen/namer"
|
||||||
)
|
)
|
||||||
|
|
||||||
// duckGenerator produces logic to register a duck.InformerFactory for a particular
|
// duckGenerator produces logic to register a duck.InformerFactory for a particular
|
||||||
// type onto context.
|
// type onto context.
|
||||||
type duckGenerator struct {
|
type duckGenerator struct {
|
||||||
generator.DefaultGen
|
generator.GoGenerator
|
||||||
outputPackage string
|
outputPackage string
|
||||||
groupVersion clientgentypes.GroupVersion
|
groupVersion clientgentypes.GroupVersion
|
||||||
groupGoName string
|
groupGoName string
|
||||||
|
@ -45,7 +47,7 @@ func (g *duckGenerator) Filter(c *generator.Context, t *types.Type) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *duckGenerator) Namers(c *generator.Context) namer.NameSystems {
|
func (g *duckGenerator) Namers(c *generator.Context) namer.NameSystems {
|
||||||
publicPluralNamer := &ExceptionNamer{
|
publicPluralNamer := &gennamer.ExceptionNamer{
|
||||||
Exceptions: map[string]string{
|
Exceptions: map[string]string{
|
||||||
// these exceptions are used to deconflict the generated code
|
// these exceptions are used to deconflict the generated code
|
||||||
// you can put your fully qualified package like
|
// you can put your fully qualified package like
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2019 The Knative Authors.
|
Copyright 2019 The Knative Authors
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -14,22 +14,24 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package generators
|
package duck
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
|
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
|
||||||
"k8s.io/gengo/generator"
|
"k8s.io/gengo/v2/generator"
|
||||||
"k8s.io/gengo/namer"
|
"k8s.io/gengo/v2/namer"
|
||||||
"k8s.io/gengo/types"
|
"k8s.io/gengo/v2/types"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
|
gennamer "knative.dev/pkg/codegen/cmd/injection-gen/namer"
|
||||||
)
|
)
|
||||||
|
|
||||||
// fakeDuckGenerator produces a file of listers for a given GroupVersion and
|
// fakeDuckGenerator produces a file of listers for a given GroupVersion and
|
||||||
// type.
|
// type.
|
||||||
type fakeDuckGenerator struct {
|
type fakeDuckGenerator struct {
|
||||||
generator.DefaultGen
|
generator.GoGenerator
|
||||||
outputPackage string
|
outputPackage string
|
||||||
imports namer.ImportTracker
|
imports namer.ImportTracker
|
||||||
|
|
||||||
|
@ -47,7 +49,7 @@ func (g *fakeDuckGenerator) Filter(c *generator.Context, t *types.Type) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *fakeDuckGenerator) Namers(c *generator.Context) namer.NameSystems {
|
func (g *fakeDuckGenerator) Namers(c *generator.Context) namer.NameSystems {
|
||||||
publicPluralNamer := &ExceptionNamer{
|
publicPluralNamer := &gennamer.ExceptionNamer{
|
||||||
Exceptions: map[string]string{
|
Exceptions: map[string]string{
|
||||||
// these exceptions are used to deconflict the generated code
|
// these exceptions are used to deconflict the generated code
|
||||||
// you can put your fully qualified package like
|
// you can put your fully qualified package like
|
|
@ -0,0 +1,98 @@
|
||||||
|
/*
|
||||||
|
Copyright 2025 The Knative Authors
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package duck
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
|
||||||
|
"k8s.io/gengo/v2/generator"
|
||||||
|
"k8s.io/gengo/v2/types"
|
||||||
|
"knative.dev/pkg/codegen/cmd/injection-gen/args"
|
||||||
|
"knative.dev/pkg/codegen/cmd/injection-gen/tags"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Targets(
|
||||||
|
args *args.Args,
|
||||||
|
groupPkgName string,
|
||||||
|
gv clientgentypes.GroupVersion,
|
||||||
|
groupGoName string,
|
||||||
|
typesToGenerate []*types.Type,
|
||||||
|
) []generator.Target {
|
||||||
|
packagePath := filepath.Join(args.GetOutputPackagePath(), "ducks", groupPkgName, strings.ToLower(gv.Version.NonEmpty()))
|
||||||
|
packageDir := filepath.Join(args.GetOutputDir(), "ducks", groupPkgName, strings.ToLower(gv.Version.NonEmpty()))
|
||||||
|
|
||||||
|
vers := make([]generator.Target, 0, 2*len(typesToGenerate))
|
||||||
|
|
||||||
|
for _, t := range typesToGenerate {
|
||||||
|
packagePath := filepath.Join(packagePath, strings.ToLower(t.Name.Name))
|
||||||
|
packageDir := filepath.Join(packageDir, strings.ToLower(t.Name.Name))
|
||||||
|
|
||||||
|
// Impl
|
||||||
|
vers = append(vers, &generator.SimpleTarget{
|
||||||
|
PkgName: strings.ToLower(t.Name.Name),
|
||||||
|
PkgPath: packagePath,
|
||||||
|
PkgDir: packageDir,
|
||||||
|
HeaderComment: args.Boilerplate,
|
||||||
|
GeneratorsFunc: func(c *generator.Context) []generator.Generator {
|
||||||
|
// Impl
|
||||||
|
return []generator.Generator{&duckGenerator{
|
||||||
|
GoGenerator: generator.GoGenerator{
|
||||||
|
OutputFilename: strings.ToLower(t.Name.Name) + ".go",
|
||||||
|
},
|
||||||
|
outputPackage: packagePath,
|
||||||
|
groupVersion: gv,
|
||||||
|
groupGoName: groupGoName,
|
||||||
|
typeToGenerate: t,
|
||||||
|
imports: generator.NewImportTracker(),
|
||||||
|
}}
|
||||||
|
},
|
||||||
|
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
||||||
|
tags := tags.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||||
|
return tags.NeedsDuckInjection()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// Fake
|
||||||
|
vers = append(vers, &generator.SimpleTarget{
|
||||||
|
PkgName: "fake",
|
||||||
|
PkgPath: filepath.Join(packagePath, "fake"),
|
||||||
|
PkgDir: filepath.Join(packageDir, "fake"),
|
||||||
|
HeaderComment: args.Boilerplate,
|
||||||
|
GeneratorsFunc: func(c *generator.Context) []generator.Generator {
|
||||||
|
// Impl
|
||||||
|
return []generator.Generator{&fakeDuckGenerator{
|
||||||
|
GoGenerator: generator.GoGenerator{
|
||||||
|
OutputFilename: "fake.go",
|
||||||
|
},
|
||||||
|
outputPackage: filepath.Join(packagePath, "fake"),
|
||||||
|
imports: generator.NewImportTracker(),
|
||||||
|
typeToGenerate: t,
|
||||||
|
groupVersion: gv,
|
||||||
|
groupGoName: groupGoName,
|
||||||
|
duckInjectionPkg: packagePath,
|
||||||
|
}}
|
||||||
|
},
|
||||||
|
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
||||||
|
tags := tags.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||||
|
return tags.NeedsDuckInjection()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return vers
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2019 The Knative Authors.
|
Copyright 2019 The Knative Authors
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -14,21 +14,21 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package generators
|
package factory
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"k8s.io/gengo/generator"
|
"k8s.io/gengo/v2/generator"
|
||||||
"k8s.io/gengo/namer"
|
"k8s.io/gengo/v2/namer"
|
||||||
"k8s.io/gengo/types"
|
"k8s.io/gengo/v2/types"
|
||||||
|
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// factoryTestGenerator produces a file of factory injection of a given type.
|
// factoryTestGenerator produces a file of factory injection of a given type.
|
||||||
type factoryGenerator struct {
|
type factoryGenerator struct {
|
||||||
generator.DefaultGen
|
generator.GoGenerator
|
||||||
outputPackage string
|
outputPackage string
|
||||||
imports namer.ImportTracker
|
imports namer.ImportTracker
|
||||||
cachingClientSetPackage string
|
cachingClientSetPackage string
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2019 The Knative Authors.
|
Copyright 2019 The Knative Authors
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -14,21 +14,21 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package generators
|
package factory
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"k8s.io/gengo/generator"
|
"k8s.io/gengo/v2/generator"
|
||||||
"k8s.io/gengo/namer"
|
"k8s.io/gengo/v2/namer"
|
||||||
"k8s.io/gengo/types"
|
"k8s.io/gengo/v2/types"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// fakeFactoryGenerator produces a file of listers for a given GroupVersion and
|
// fakeFactoryGenerator produces a file of listers for a given GroupVersion and
|
||||||
// type.
|
// type.
|
||||||
type fakeFactoryGenerator struct {
|
type fakeFactoryGenerator struct {
|
||||||
generator.DefaultGen
|
generator.GoGenerator
|
||||||
outputPackage string
|
outputPackage string
|
||||||
imports namer.ImportTracker
|
imports namer.ImportTracker
|
||||||
filtered bool
|
filtered bool
|
|
@ -14,21 +14,21 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package generators
|
package factory
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"k8s.io/gengo/generator"
|
"k8s.io/gengo/v2/generator"
|
||||||
"k8s.io/gengo/namer"
|
"k8s.io/gengo/v2/namer"
|
||||||
"k8s.io/gengo/types"
|
"k8s.io/gengo/v2/types"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// fakeFilteredFactoryGenerator produces a file of listers for a given GroupVersion and
|
// fakeFilteredFactoryGenerator produces a file of listers for a given GroupVersion and
|
||||||
// type.
|
// type.
|
||||||
type fakeFilteredFactoryGenerator struct {
|
type fakeFilteredFactoryGenerator struct {
|
||||||
generator.DefaultGen
|
generator.GoGenerator
|
||||||
outputPackage string
|
outputPackage string
|
||||||
imports namer.ImportTracker
|
imports namer.ImportTracker
|
||||||
filtered bool
|
filtered bool
|
|
@ -14,20 +14,20 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package generators
|
package factory
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"k8s.io/gengo/generator"
|
"k8s.io/gengo/v2/generator"
|
||||||
"k8s.io/gengo/namer"
|
"k8s.io/gengo/v2/namer"
|
||||||
"k8s.io/gengo/types"
|
"k8s.io/gengo/v2/types"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// factoryTestGenerator produces a file of factory injection of a given type.
|
// factoryTestGenerator produces a file of factory injection of a given type.
|
||||||
type filteredFactoryGenerator struct {
|
type filteredFactoryGenerator struct {
|
||||||
generator.DefaultGen
|
generator.GoGenerator
|
||||||
outputPackage string
|
outputPackage string
|
||||||
imports namer.ImportTracker
|
imports namer.ImportTracker
|
||||||
cachingClientSetPackage string
|
cachingClientSetPackage string
|
133
vendor/knative.dev/pkg/codegen/cmd/injection-gen/generators/factory/targets.go
vendored
Normal file
133
vendor/knative.dev/pkg/codegen/cmd/injection-gen/generators/factory/targets.go
vendored
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
/*
|
||||||
|
Copyright 2025 The Knative Authors
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package factory
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"k8s.io/gengo/v2/generator"
|
||||||
|
"k8s.io/gengo/v2/types"
|
||||||
|
"knative.dev/pkg/codegen/cmd/injection-gen/args"
|
||||||
|
"knative.dev/pkg/codegen/cmd/injection-gen/generators/client"
|
||||||
|
"knative.dev/pkg/codegen/cmd/injection-gen/tags"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Targets(args *args.Args) []generator.Target {
|
||||||
|
packagePath := filepath.Join(args.GetOutputPackagePath(), "informers", "factory")
|
||||||
|
packageDir := filepath.Join(args.GetOutputDir(), "informers", "factory")
|
||||||
|
|
||||||
|
clientGen := client.New(args)
|
||||||
|
clientFakeGen := client.NewFake(args)
|
||||||
|
|
||||||
|
return []generator.Target{
|
||||||
|
// Impl
|
||||||
|
&generator.SimpleTarget{
|
||||||
|
PkgName: "factory",
|
||||||
|
PkgPath: packagePath,
|
||||||
|
PkgDir: packageDir,
|
||||||
|
HeaderComment: args.Boilerplate,
|
||||||
|
GeneratorsFunc: func(c *generator.Context) []generator.Generator {
|
||||||
|
// Impl
|
||||||
|
return []generator.Generator{&factoryGenerator{
|
||||||
|
GoGenerator: generator.GoGenerator{
|
||||||
|
OutputFilename: "factory.go",
|
||||||
|
},
|
||||||
|
outputPackage: packagePath,
|
||||||
|
cachingClientSetPackage: clientGen.OutputPackagePath(),
|
||||||
|
sharedInformerFactoryPackage: args.ExternalVersionsInformersPackage,
|
||||||
|
imports: generator.NewImportTracker(),
|
||||||
|
}}
|
||||||
|
},
|
||||||
|
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
||||||
|
tags := tags.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||||
|
return tags.NeedsInformerInjection()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Fake
|
||||||
|
&generator.SimpleTarget{
|
||||||
|
PkgName: "fake",
|
||||||
|
PkgPath: filepath.Join(packagePath, "fake"),
|
||||||
|
PkgDir: filepath.Join(packageDir, "fake"),
|
||||||
|
HeaderComment: args.Boilerplate,
|
||||||
|
GeneratorsFunc: func(c *generator.Context) []generator.Generator {
|
||||||
|
// Impl
|
||||||
|
return []generator.Generator{&fakeFactoryGenerator{
|
||||||
|
GoGenerator: generator.GoGenerator{
|
||||||
|
OutputFilename: "fake.go",
|
||||||
|
},
|
||||||
|
outputPackage: filepath.Join(packagePath, "fake"),
|
||||||
|
factoryInjectionPkg: packagePath,
|
||||||
|
fakeClientInjectionPkg: clientFakeGen.OutputPackagePath(),
|
||||||
|
sharedInformerFactoryPackage: args.ExternalVersionsInformersPackage,
|
||||||
|
imports: generator.NewImportTracker(),
|
||||||
|
}}
|
||||||
|
},
|
||||||
|
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
||||||
|
tags := tags.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||||
|
return tags.NeedsInformerInjection()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// FilterFactoryImpl
|
||||||
|
&generator.SimpleTarget{
|
||||||
|
PkgName: "filteredFactory",
|
||||||
|
PkgPath: filepath.Join(packagePath, "filtered"),
|
||||||
|
PkgDir: filepath.Join(packageDir, "filtered"),
|
||||||
|
HeaderComment: args.Boilerplate,
|
||||||
|
GeneratorsFunc: func(c *generator.Context) []generator.Generator {
|
||||||
|
// Impl
|
||||||
|
return []generator.Generator{&filteredFactoryGenerator{
|
||||||
|
GoGenerator: generator.GoGenerator{
|
||||||
|
OutputFilename: "filtered_factory.go",
|
||||||
|
},
|
||||||
|
outputPackage: filepath.Join(packagePath, "filtered"),
|
||||||
|
cachingClientSetPackage: clientGen.OutputPackagePath(),
|
||||||
|
sharedInformerFactoryPackage: args.ExternalVersionsInformersPackage,
|
||||||
|
imports: generator.NewImportTracker(),
|
||||||
|
}}
|
||||||
|
},
|
||||||
|
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
||||||
|
tags := tags.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||||
|
return tags.NeedsInformerInjection()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// FakeFilterFactory
|
||||||
|
&generator.SimpleTarget{
|
||||||
|
PkgName: "fakeFilteredFactory",
|
||||||
|
PkgPath: filepath.Join(packagePath, "filtered", "fake"),
|
||||||
|
PkgDir: filepath.Join(packageDir, "filtered", "fake"),
|
||||||
|
HeaderComment: args.Boilerplate,
|
||||||
|
GeneratorsFunc: func(c *generator.Context) []generator.Generator {
|
||||||
|
// Impl
|
||||||
|
return []generator.Generator{&fakeFilteredFactoryGenerator{
|
||||||
|
GoGenerator: generator.GoGenerator{
|
||||||
|
OutputFilename: "fake_filtered_factory.go",
|
||||||
|
},
|
||||||
|
outputPackage: filepath.Join(packagePath, "filtered", "fake"),
|
||||||
|
factoryInjectionPkg: filepath.Join(packagePath, "filtered"),
|
||||||
|
fakeClientInjectionPkg: clientFakeGen.OutputPackagePath(),
|
||||||
|
sharedInformerFactoryPackage: args.ExternalVersionsInformersPackage,
|
||||||
|
imports: generator.NewImportTracker(),
|
||||||
|
}}
|
||||||
|
},
|
||||||
|
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
||||||
|
tags := tags.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||||
|
return tags.NeedsInformerInjection()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,22 +14,24 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package generators
|
package informers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
|
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
|
||||||
"k8s.io/gengo/generator"
|
"k8s.io/gengo/v2/generator"
|
||||||
"k8s.io/gengo/namer"
|
"k8s.io/gengo/v2/namer"
|
||||||
"k8s.io/gengo/types"
|
"k8s.io/gengo/v2/types"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
|
gennamer "knative.dev/pkg/codegen/cmd/injection-gen/namer"
|
||||||
)
|
)
|
||||||
|
|
||||||
// fakeFilteredInformerGenerator produces a file of listers for a given GroupVersion and
|
// fakeFilteredInformerGenerator produces a file of listers for a given GroupVersion and
|
||||||
// type.
|
// type.
|
||||||
type fakeFilteredInformerGenerator struct {
|
type fakeFilteredInformerGenerator struct {
|
||||||
generator.DefaultGen
|
generator.GoGenerator
|
||||||
outputPackage string
|
outputPackage string
|
||||||
imports namer.ImportTracker
|
imports namer.ImportTracker
|
||||||
|
|
||||||
|
@ -48,7 +50,7 @@ func (g *fakeFilteredInformerGenerator) Filter(c *generator.Context, t *types.Ty
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *fakeFilteredInformerGenerator) Namers(c *generator.Context) namer.NameSystems {
|
func (g *fakeFilteredInformerGenerator) Namers(c *generator.Context) namer.NameSystems {
|
||||||
publicPluralNamer := &ExceptionNamer{
|
publicPluralNamer := &gennamer.ExceptionNamer{
|
||||||
Exceptions: map[string]string{
|
Exceptions: map[string]string{
|
||||||
// these exceptions are used to deconflict the generated code
|
// these exceptions are used to deconflict the generated code
|
||||||
// you can put your fully qualified package like
|
// you can put your fully qualified package like
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2019 The Knative Authors.
|
Copyright 2019 The Knative Authors
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -14,22 +14,24 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package generators
|
package informers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
|
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
|
||||||
"k8s.io/gengo/generator"
|
"k8s.io/gengo/v2/generator"
|
||||||
"k8s.io/gengo/namer"
|
"k8s.io/gengo/v2/namer"
|
||||||
"k8s.io/gengo/types"
|
"k8s.io/gengo/v2/types"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
|
gennamer "knative.dev/pkg/codegen/cmd/injection-gen/namer"
|
||||||
)
|
)
|
||||||
|
|
||||||
// fakeInformerGenerator produces a file of listers for a given GroupVersion and
|
// fakeInformerGenerator produces a file of listers for a given GroupVersion and
|
||||||
// type.
|
// type.
|
||||||
type fakeInformerGenerator struct {
|
type fakeInformerGenerator struct {
|
||||||
generator.DefaultGen
|
generator.GoGenerator
|
||||||
outputPackage string
|
outputPackage string
|
||||||
imports namer.ImportTracker
|
imports namer.ImportTracker
|
||||||
|
|
||||||
|
@ -48,7 +50,7 @@ func (g *fakeInformerGenerator) Filter(c *generator.Context, t *types.Type) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *fakeInformerGenerator) Namers(c *generator.Context) namer.NameSystems {
|
func (g *fakeInformerGenerator) Namers(c *generator.Context) namer.NameSystems {
|
||||||
publicPluralNamer := &ExceptionNamer{
|
publicPluralNamer := &gennamer.ExceptionNamer{
|
||||||
Exceptions: map[string]string{
|
Exceptions: map[string]string{
|
||||||
// these exceptions are used to deconflict the generated code
|
// these exceptions are used to deconflict the generated code
|
||||||
// you can put your fully qualified package like
|
// you can put your fully qualified package like
|
|
@ -14,22 +14,24 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package generators
|
package informers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
|
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
|
||||||
"k8s.io/gengo/generator"
|
"k8s.io/gengo/v2/generator"
|
||||||
"k8s.io/gengo/namer"
|
"k8s.io/gengo/v2/namer"
|
||||||
"k8s.io/gengo/types"
|
"k8s.io/gengo/v2/types"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
|
gennamer "knative.dev/pkg/codegen/cmd/injection-gen/namer"
|
||||||
)
|
)
|
||||||
|
|
||||||
// injectionTestGenerator produces a file of listers for a given GroupVersion and
|
// injectionTestGenerator produces a file of listers for a given GroupVersion and
|
||||||
// type.
|
// type.
|
||||||
type filteredInjectionGenerator struct {
|
type filteredInjectionGenerator struct {
|
||||||
generator.DefaultGen
|
generator.GoGenerator
|
||||||
outputPackage string
|
outputPackage string
|
||||||
groupVersion clientgentypes.GroupVersion
|
groupVersion clientgentypes.GroupVersion
|
||||||
groupGoName string
|
groupGoName string
|
||||||
|
@ -47,7 +49,7 @@ func (g *filteredInjectionGenerator) Filter(c *generator.Context, t *types.Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *filteredInjectionGenerator) Namers(c *generator.Context) namer.NameSystems {
|
func (g *filteredInjectionGenerator) Namers(c *generator.Context) namer.NameSystems {
|
||||||
publicPluralNamer := &ExceptionNamer{
|
publicPluralNamer := &gennamer.ExceptionNamer{
|
||||||
Exceptions: map[string]string{
|
Exceptions: map[string]string{
|
||||||
// these exceptions are used to deconflict the generated code
|
// these exceptions are used to deconflict the generated code
|
||||||
// you can put your fully qualified package like
|
// you can put your fully qualified package like
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2019 The Knative Authors.
|
Copyright 2019 The Knative Authors
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -14,22 +14,24 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package generators
|
package informers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
|
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
|
||||||
"k8s.io/gengo/generator"
|
"k8s.io/gengo/v2/generator"
|
||||||
"k8s.io/gengo/namer"
|
"k8s.io/gengo/v2/namer"
|
||||||
"k8s.io/gengo/types"
|
"k8s.io/gengo/v2/types"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
|
gennamer "knative.dev/pkg/codegen/cmd/injection-gen/namer"
|
||||||
)
|
)
|
||||||
|
|
||||||
// injectionTestGenerator produces a file of listers for a given GroupVersion and
|
// injectionTestGenerator produces a file of listers for a given GroupVersion and
|
||||||
// type.
|
// type.
|
||||||
type injectionGenerator struct {
|
type injectionGenerator struct {
|
||||||
generator.DefaultGen
|
generator.GoGenerator
|
||||||
outputPackage string
|
outputPackage string
|
||||||
groupVersion clientgentypes.GroupVersion
|
groupVersion clientgentypes.GroupVersion
|
||||||
groupGoName string
|
groupGoName string
|
||||||
|
@ -48,7 +50,7 @@ func (g *injectionGenerator) Filter(c *generator.Context, t *types.Type) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *injectionGenerator) Namers(c *generator.Context) namer.NameSystems {
|
func (g *injectionGenerator) Namers(c *generator.Context) namer.NameSystems {
|
||||||
publicPluralNamer := &ExceptionNamer{
|
publicPluralNamer := &gennamer.ExceptionNamer{
|
||||||
Exceptions: map[string]string{
|
Exceptions: map[string]string{
|
||||||
// these exceptions are used to deconflict the generated code
|
// these exceptions are used to deconflict the generated code
|
||||||
// you can put your fully qualified package like
|
// you can put your fully qualified package like
|
163
vendor/knative.dev/pkg/codegen/cmd/injection-gen/generators/informers/targets.go
vendored
Normal file
163
vendor/knative.dev/pkg/codegen/cmd/injection-gen/generators/informers/targets.go
vendored
Normal file
|
@ -0,0 +1,163 @@
|
||||||
|
/*
|
||||||
|
Copyright 2025 The Knative Authors
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package informers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
|
||||||
|
"k8s.io/gengo/v2/generator"
|
||||||
|
"k8s.io/gengo/v2/types"
|
||||||
|
"knative.dev/pkg/codegen/cmd/injection-gen/args"
|
||||||
|
"knative.dev/pkg/codegen/cmd/injection-gen/tags"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Targets(
|
||||||
|
args *args.Args,
|
||||||
|
groupPkgName string,
|
||||||
|
gv clientgentypes.GroupVersion,
|
||||||
|
groupGoName string,
|
||||||
|
typesToGenerate []*types.Type,
|
||||||
|
) []generator.Target {
|
||||||
|
factoryPackagePath := filepath.Join(args.GetOutputPackagePath(), "informers", "factory")
|
||||||
|
filteredFactoryPackagePath := filepath.Join(args.GetOutputPackagePath(), "informers", "factory", "filtered")
|
||||||
|
|
||||||
|
packagePath := filepath.Join(args.GetOutputPackagePath(), "informers", groupPkgName, strings.ToLower(gv.Version.NonEmpty()))
|
||||||
|
packageDir := filepath.Join(args.GetOutputDir(), "informers", groupPkgName, strings.ToLower(gv.Version.NonEmpty()))
|
||||||
|
|
||||||
|
vers := make([]generator.Target, 0, 2*len(typesToGenerate))
|
||||||
|
|
||||||
|
for _, t := range typesToGenerate {
|
||||||
|
packagePath := filepath.Join(packagePath, strings.ToLower(t.Name.Name))
|
||||||
|
packageDir := filepath.Join(packageDir, strings.ToLower(t.Name.Name))
|
||||||
|
typedInformerPackage := typedInformerPackage(groupPkgName, gv, args.ExternalVersionsInformersPackage)
|
||||||
|
|
||||||
|
// Impl
|
||||||
|
vers = append(vers, &generator.SimpleTarget{
|
||||||
|
PkgName: strings.ToLower(t.Name.Name),
|
||||||
|
PkgPath: packagePath,
|
||||||
|
PkgDir: packageDir,
|
||||||
|
HeaderComment: args.Boilerplate,
|
||||||
|
GeneratorsFunc: func(c *generator.Context) []generator.Generator {
|
||||||
|
// Impl
|
||||||
|
return []generator.Generator{&injectionGenerator{
|
||||||
|
GoGenerator: generator.GoGenerator{
|
||||||
|
OutputFilename: strings.ToLower(t.Name.Name) + ".go",
|
||||||
|
},
|
||||||
|
outputPackage: packagePath,
|
||||||
|
groupVersion: gv,
|
||||||
|
groupGoName: groupGoName,
|
||||||
|
typeToGenerate: t,
|
||||||
|
imports: generator.NewImportTracker(),
|
||||||
|
typedInformerPackage: typedInformerPackage,
|
||||||
|
groupInformerFactoryPackage: factoryPackagePath,
|
||||||
|
disableInformerInit: args.DisableInformerInit,
|
||||||
|
}}
|
||||||
|
},
|
||||||
|
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
||||||
|
tags := tags.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||||
|
return tags.NeedsInformerInjection()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// Fake
|
||||||
|
vers = append(vers, &generator.SimpleTarget{
|
||||||
|
PkgName: "fake",
|
||||||
|
PkgPath: filepath.Join(packagePath, "fake"),
|
||||||
|
PkgDir: filepath.Join(packageDir, "fake"),
|
||||||
|
HeaderComment: args.Boilerplate,
|
||||||
|
GeneratorsFunc: func(c *generator.Context) []generator.Generator {
|
||||||
|
// Impl
|
||||||
|
return []generator.Generator{&fakeInformerGenerator{
|
||||||
|
GoGenerator: generator.GoGenerator{
|
||||||
|
OutputFilename: "fake.go",
|
||||||
|
},
|
||||||
|
outputPackage: filepath.Join(packagePath, "fake"),
|
||||||
|
imports: generator.NewImportTracker(),
|
||||||
|
typeToGenerate: t,
|
||||||
|
groupVersion: gv,
|
||||||
|
groupGoName: groupGoName,
|
||||||
|
informerInjectionPkg: packagePath,
|
||||||
|
fakeFactoryInjectionPkg: filepath.Join(factoryPackagePath, "fake"),
|
||||||
|
}}
|
||||||
|
},
|
||||||
|
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
||||||
|
tags := tags.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||||
|
return tags.NeedsInformerInjection()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
// FilteredInformer
|
||||||
|
vers = append(vers, &generator.SimpleTarget{
|
||||||
|
PkgName: "filtered",
|
||||||
|
PkgPath: filepath.Join(packagePath, "filtered"),
|
||||||
|
PkgDir: filepath.Join(packageDir, "filtered"),
|
||||||
|
HeaderComment: args.Boilerplate,
|
||||||
|
GeneratorsFunc: func(c *generator.Context) []generator.Generator {
|
||||||
|
// Impl
|
||||||
|
return []generator.Generator{&filteredInjectionGenerator{
|
||||||
|
GoGenerator: generator.GoGenerator{
|
||||||
|
OutputFilename: strings.ToLower(t.Name.Name) + ".go",
|
||||||
|
},
|
||||||
|
outputPackage: filepath.Join(packagePath, "filtered"),
|
||||||
|
groupVersion: gv,
|
||||||
|
groupGoName: groupGoName,
|
||||||
|
typeToGenerate: t,
|
||||||
|
imports: generator.NewImportTracker(),
|
||||||
|
typedInformerPackage: typedInformerPackage,
|
||||||
|
groupInformerFactoryPackage: filteredFactoryPackagePath,
|
||||||
|
}}
|
||||||
|
},
|
||||||
|
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
||||||
|
tags := tags.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||||
|
return tags.NeedsInformerInjection()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// FakeFilteredInformer
|
||||||
|
vers = append(vers, &generator.SimpleTarget{
|
||||||
|
PkgName: "fake",
|
||||||
|
PkgPath: filepath.Join(packagePath, "filtered", "fake"),
|
||||||
|
PkgDir: filepath.Join(packageDir, "filtered", "fake"),
|
||||||
|
HeaderComment: args.Boilerplate,
|
||||||
|
GeneratorsFunc: func(c *generator.Context) []generator.Generator {
|
||||||
|
// Impl
|
||||||
|
return []generator.Generator{&fakeFilteredInformerGenerator{
|
||||||
|
GoGenerator: generator.GoGenerator{
|
||||||
|
OutputFilename: "fake.go",
|
||||||
|
},
|
||||||
|
outputPackage: filepath.Join(packagePath, "filtered", "fake"),
|
||||||
|
imports: generator.NewImportTracker(),
|
||||||
|
typeToGenerate: t,
|
||||||
|
groupVersion: gv,
|
||||||
|
groupGoName: groupGoName,
|
||||||
|
informerInjectionPkg: filepath.Join(packagePath, "filtered"),
|
||||||
|
fakeFactoryInjectionPkg: filteredFactoryPackagePath,
|
||||||
|
}}
|
||||||
|
},
|
||||||
|
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
||||||
|
tags := tags.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||||
|
return tags.NeedsInformerInjection()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return vers
|
||||||
|
}
|
||||||
|
|
||||||
|
func typedInformerPackage(groupPkgName string, gv clientgentypes.GroupVersion, externalVersionsInformersPackage string) string {
|
||||||
|
return filepath.Join(externalVersionsInformersPackage, groupPkgName, gv.Version.String())
|
||||||
|
}
|
|
@ -1,58 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2016 The Kubernetes Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package generators
|
|
||||||
|
|
||||||
import (
|
|
||||||
"k8s.io/gengo/namer"
|
|
||||||
"k8s.io/gengo/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TagOverrideNamer is a namer which pulls names from a given tag, if specified,
|
|
||||||
// and otherwise falls back to a different namer.
|
|
||||||
type tagOverrideNamer struct {
|
|
||||||
tagName string
|
|
||||||
fallback namer.Namer
|
|
||||||
}
|
|
||||||
|
|
||||||
// Name returns the tag value if it exists. It no tag was found the fallback namer will be used
|
|
||||||
func (n *tagOverrideNamer) Name(t *types.Type) string {
|
|
||||||
if nameOverride := extractTag(n.tagName, append(t.SecondClosestCommentLines, t.CommentLines...)); nameOverride != "" {
|
|
||||||
return nameOverride
|
|
||||||
}
|
|
||||||
|
|
||||||
return n.fallback.Name(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewTagOverrideNamer creates a namer.Namer which uses the contents of the given tag as
|
|
||||||
// the name, or falls back to another Namer if the tag is not present.
|
|
||||||
func newTagOverrideNamer(tagName string, fallback namer.Namer) namer.Namer {
|
|
||||||
return &tagOverrideNamer{
|
|
||||||
tagName: tagName,
|
|
||||||
fallback: fallback,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// extractTag gets the comment-tags for the key. If the tag did not exist, it
|
|
||||||
// returns the empty string.
|
|
||||||
func extractTag(key string, lines []string) string {
|
|
||||||
val, present := types.ExtractCommentTags("+", lines)[key]
|
|
||||||
if !present || len(val) < 1 {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return val[0]
|
|
||||||
}
|
|
|
@ -17,39 +17,32 @@ limitations under the License.
|
||||||
package generators
|
package generators
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"k8s.io/code-generator/cmd/client-gen/generators/util"
|
|
||||||
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
|
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
|
||||||
"k8s.io/gengo/args"
|
"k8s.io/gengo/v2"
|
||||||
"k8s.io/gengo/generator"
|
"k8s.io/gengo/v2/generator"
|
||||||
"k8s.io/gengo/namer"
|
"k8s.io/gengo/v2/namer"
|
||||||
"k8s.io/gengo/types"
|
"k8s.io/gengo/v2/types"
|
||||||
"k8s.io/klog/v2"
|
|
||||||
|
|
||||||
informergenargs "knative.dev/pkg/codegen/cmd/injection-gen/args"
|
"knative.dev/pkg/codegen/cmd/injection-gen/args"
|
||||||
|
"knative.dev/pkg/codegen/cmd/injection-gen/generators/client"
|
||||||
|
"knative.dev/pkg/codegen/cmd/injection-gen/generators/duck"
|
||||||
|
"knative.dev/pkg/codegen/cmd/injection-gen/generators/factory"
|
||||||
|
"knative.dev/pkg/codegen/cmd/injection-gen/generators/informers"
|
||||||
|
"knative.dev/pkg/codegen/cmd/injection-gen/generators/reconciler"
|
||||||
|
"knative.dev/pkg/codegen/cmd/injection-gen/tags"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type genFunc func(*args.Args, string, clientgentypes.GroupVersion, string, []*types.Type) []generator.Target
|
||||||
|
|
||||||
// Packages makes the client package definition.
|
// Packages makes the client package definition.
|
||||||
func Packages(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages {
|
func Targets(context *generator.Context, args *args.Args) []generator.Target {
|
||||||
boilerplate, err := arguments.LoadGoBoilerplate()
|
var packageList []generator.Target
|
||||||
if err != nil {
|
|
||||||
klog.Fatal("Failed loading boilerplate: ", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
customArgs, ok := arguments.CustomArgs.(*informergenargs.CustomArgs)
|
|
||||||
if !ok {
|
|
||||||
klog.Fatalf("Wrong CustomArgs type: %T", arguments.CustomArgs)
|
|
||||||
}
|
|
||||||
|
|
||||||
versionPackagePath := filepath.Clean(arguments.OutputPackagePath)
|
|
||||||
|
|
||||||
var packageList generator.Packages
|
|
||||||
|
|
||||||
groupGoNames := make(map[string]string)
|
groupGoNames := make(map[string]string)
|
||||||
for _, inputDir := range arguments.InputDirs {
|
for _, inputDir := range args.InputDirs {
|
||||||
p := context.Universe.Package(vendorless(inputDir))
|
p := context.Universe.Package(inputDir)
|
||||||
|
|
||||||
var gv clientgentypes.GroupVersion
|
var gv clientgentypes.GroupVersion
|
||||||
|
|
||||||
|
@ -62,677 +55,58 @@ func Packages(context *generator.Context, arguments *args.GeneratorArgs) generat
|
||||||
// If there's a comment of the form "// +groupName=somegroup" or
|
// If there's a comment of the form "// +groupName=somegroup" or
|
||||||
// "// +groupName=somegroup.foo.bar.io", use the first field (somegroup) as the name of the
|
// "// +groupName=somegroup.foo.bar.io", use the first field (somegroup) as the name of the
|
||||||
// group when generating.
|
// group when generating.
|
||||||
if override := types.ExtractCommentTags("+", p.Comments)["groupName"]; override != nil {
|
if override := gengo.ExtractCommentTags("+", p.Comments)["groupName"]; override != nil {
|
||||||
gv.Group = clientgentypes.Group(override[0])
|
gv.Group = clientgentypes.Group(override[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there's a comment of the form "// +groupGoName=SomeUniqueShortName", use that as
|
// If there's a comment of the form "// +groupGoName=SomeUniqueShortName", use that as
|
||||||
// the Go group identifier in CamelCase. It defaults
|
// the Go group identifier in CamelCase. It defaults
|
||||||
groupGoNames[groupPackageName] = namer.IC(strings.SplitN(gv.Group.NonEmpty(), ".", 2)[0])
|
groupGoNames[groupPackageName] = namer.IC(strings.SplitN(gv.Group.NonEmpty(), ".", 2)[0])
|
||||||
if override := types.ExtractCommentTags("+", p.Comments)["groupGoName"]; override != nil {
|
if override := gengo.ExtractCommentTags("+", p.Comments)["groupGoName"]; override != nil {
|
||||||
groupGoNames[groupPackageName] = namer.IC(override[0])
|
groupGoNames[groupPackageName] = namer.IC(override[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
var typesWithInformers []*types.Type
|
var typesWithInformers []*types.Type
|
||||||
var duckTypes []*types.Type
|
var duckTypes []*types.Type
|
||||||
var reconcilerTypes []*types.Type
|
var reconcilerTypes []*types.Type
|
||||||
|
|
||||||
for _, t := range p.Types {
|
for _, t := range p.Types {
|
||||||
tags := MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
tags := tags.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||||
if tags.NeedsInformerInjection() {
|
if tags.NeedsInformerInjection() {
|
||||||
typesWithInformers = append(typesWithInformers, t)
|
typesWithInformers = append(typesWithInformers, t)
|
||||||
}
|
}
|
||||||
if tags.NeedsDuckInjection() {
|
if tags.NeedsDuckInjection() {
|
||||||
duckTypes = append(duckTypes, t)
|
duckTypes = append(duckTypes, t)
|
||||||
}
|
}
|
||||||
if tags.NeedsReconciler(t, customArgs) {
|
if tags.NeedsReconciler(t, args) {
|
||||||
reconcilerTypes = append(reconcilerTypes, t)
|
reconcilerTypes = append(reconcilerTypes, t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(typesWithInformers) != 0 {
|
sources := []struct {
|
||||||
orderer := namer.Orderer{Namer: namer.NewPrivateNamer(0)}
|
types []*types.Type
|
||||||
typesWithInformers = orderer.OrderTypes(typesWithInformers)
|
generator genFunc
|
||||||
|
}{
|
||||||
// Generate the informer and fake, for each type.
|
{types: typesWithInformers, generator: informers.Targets},
|
||||||
packageList = append(packageList, versionInformerPackages(versionPackagePath, groupPackageName, gv, groupGoNames[groupPackageName], boilerplate, typesWithInformers, customArgs)...)
|
{types: duckTypes, generator: duck.Targets},
|
||||||
|
{types: reconcilerTypes, generator: reconciler.Targets},
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(duckTypes) != 0 {
|
for _, source := range sources {
|
||||||
orderer := namer.Orderer{Namer: namer.NewPrivateNamer(0)}
|
if len(source.types) != 0 {
|
||||||
duckTypes = orderer.OrderTypes(duckTypes)
|
orderer := namer.Orderer{Namer: namer.NewPrivateNamer(0)}
|
||||||
|
source.types = orderer.OrderTypes(source.types)
|
||||||
// Generate a duck-typed informer for each type.
|
targets := source.generator(args, groupPackageName, gv, groupGoNames[groupPackageName], source.types)
|
||||||
packageList = append(packageList, versionDuckPackages(versionPackagePath, groupPackageName, gv, groupGoNames[groupPackageName], boilerplate, duckTypes, customArgs)...)
|
packageList = append(packageList, targets...)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(reconcilerTypes) != 0 {
|
|
||||||
orderer := namer.Orderer{Namer: namer.NewPrivateNamer(0)}
|
|
||||||
reconcilerTypes = orderer.OrderTypes(reconcilerTypes)
|
|
||||||
|
|
||||||
// Generate a reconciler and controller for each type.
|
|
||||||
packageList = append(packageList, reconcilerPackages(versionPackagePath, groupPackageName, gv, groupGoNames[groupPackageName], boilerplate, reconcilerTypes, customArgs)...)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate the client and fake.
|
// Generate the client and fake.
|
||||||
packageList = append(packageList, versionClientsPackages(versionPackagePath, boilerplate, customArgs)...)
|
packageList = append(packageList, client.Targets(args)...)
|
||||||
|
|
||||||
// Generate the informer factory and fake.
|
// // Generate the informer factory and fake.
|
||||||
packageList = append(packageList, versionFactoryPackages(versionPackagePath, boilerplate, customArgs)...)
|
packageList = append(packageList, factory.Targets(args)...)
|
||||||
|
|
||||||
return packageList
|
return packageList
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tags represents a genclient configuration for a single type.
|
|
||||||
type Tags struct {
|
|
||||||
util.Tags
|
|
||||||
|
|
||||||
GenerateDuck bool
|
|
||||||
GenerateReconciler bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t Tags) NeedsInformerInjection() bool {
|
|
||||||
return t.GenerateClient && !t.NoVerbs && t.HasVerb("list") && t.HasVerb("watch")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t Tags) NeedsDuckInjection() bool {
|
|
||||||
return t.GenerateDuck
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t Tags) NeedsReconciler(kind *types.Type, args *informergenargs.CustomArgs) bool {
|
|
||||||
// Overrides
|
|
||||||
kinds := strings.Split(args.ForceKinds, ",")
|
|
||||||
for _, k := range kinds {
|
|
||||||
if kind.Name.Name == k {
|
|
||||||
klog.V(5).Infof("Kind %s was forced to generate reconciler.", k)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Normal
|
|
||||||
return t.GenerateReconciler
|
|
||||||
}
|
|
||||||
|
|
||||||
// MustParseClientGenTags calls ParseClientGenTags but instead of returning error it panics.
|
|
||||||
func MustParseClientGenTags(lines []string) Tags {
|
|
||||||
ret := Tags{
|
|
||||||
Tags: util.MustParseClientGenTags(lines),
|
|
||||||
}
|
|
||||||
|
|
||||||
values := ExtractCommentTags("+", lines)
|
|
||||||
|
|
||||||
_, ret.GenerateDuck = values["genduck"]
|
|
||||||
|
|
||||||
_, ret.GenerateReconciler = values["genreconciler"]
|
|
||||||
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
func extractCommentTags(t *types.Type) CommentTags {
|
|
||||||
comments := append(append([]string{}, t.SecondClosestCommentLines...), t.CommentLines...)
|
|
||||||
return ExtractCommentTags("+", comments)
|
|
||||||
}
|
|
||||||
|
|
||||||
func extractReconcilerClassesTag(tags CommentTags) ([]string, bool) {
|
|
||||||
vals, ok := tags["genreconciler"]
|
|
||||||
if !ok {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
classnames, has := vals["class"]
|
|
||||||
if has && len(classnames) == 0 {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
return classnames, has
|
|
||||||
}
|
|
||||||
|
|
||||||
func isKRShaped(tags CommentTags) bool {
|
|
||||||
vals, has := tags["genreconciler"]
|
|
||||||
if !has {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
stringVals, has := vals["krshapedlogic"]
|
|
||||||
if !has || len(vals) == 0 {
|
|
||||||
return true // Default is true
|
|
||||||
}
|
|
||||||
return stringVals[0] != "false"
|
|
||||||
}
|
|
||||||
|
|
||||||
func isNonNamespaced(tags CommentTags) bool {
|
|
||||||
vals, has := tags["genclient"]
|
|
||||||
if !has {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
_, has = vals["nonNamespaced"]
|
|
||||||
return has
|
|
||||||
}
|
|
||||||
|
|
||||||
func stubs(tags CommentTags) bool {
|
|
||||||
vals, has := tags["genreconciler"]
|
|
||||||
if !has {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
_, has = vals["stubs"]
|
|
||||||
return has
|
|
||||||
}
|
|
||||||
|
|
||||||
func vendorless(p string) string {
|
|
||||||
if pos := strings.LastIndex(p, "/vendor/"); pos != -1 {
|
|
||||||
return p[pos+len("/vendor/"):]
|
|
||||||
}
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
func typedInformerPackage(groupPkgName string, gv clientgentypes.GroupVersion, externalVersionsInformersPackage string) string {
|
|
||||||
return filepath.Join(externalVersionsInformersPackage, groupPkgName, gv.Version.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
func versionClientsPackages(basePackage string, boilerplate []byte, customArgs *informergenargs.CustomArgs) []generator.Package {
|
|
||||||
packagePath := filepath.Join(basePackage, "client")
|
|
||||||
|
|
||||||
return []generator.Package{
|
|
||||||
// Impl
|
|
||||||
&generator.DefaultPackage{
|
|
||||||
PackageName: "client",
|
|
||||||
PackagePath: packagePath,
|
|
||||||
HeaderText: boilerplate,
|
|
||||||
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
|
|
||||||
// Impl
|
|
||||||
generators = append(generators, &clientGenerator{
|
|
||||||
DefaultGen: generator.DefaultGen{
|
|
||||||
OptionalName: "client",
|
|
||||||
},
|
|
||||||
|
|
||||||
outputPackage: packagePath,
|
|
||||||
imports: generator.NewImportTracker(),
|
|
||||||
clientSetPackage: customArgs.VersionedClientSetPackage,
|
|
||||||
})
|
|
||||||
return generators
|
|
||||||
},
|
|
||||||
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
|
||||||
tags := MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
|
||||||
return tags.NeedsInformerInjection()
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// Fake
|
|
||||||
&generator.DefaultPackage{
|
|
||||||
PackageName: "fake",
|
|
||||||
PackagePath: filepath.Join(packagePath, "fake"),
|
|
||||||
HeaderText: boilerplate,
|
|
||||||
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
|
|
||||||
// Impl
|
|
||||||
generators = append(generators, &fakeClientGenerator{
|
|
||||||
DefaultGen: generator.DefaultGen{
|
|
||||||
OptionalName: "fake",
|
|
||||||
},
|
|
||||||
outputPackage: filepath.Join(packagePath, "fake"),
|
|
||||||
imports: generator.NewImportTracker(),
|
|
||||||
fakeClientPkg: filepath.Join(customArgs.VersionedClientSetPackage, "fake"),
|
|
||||||
clientInjectionPkg: packagePath,
|
|
||||||
})
|
|
||||||
return generators
|
|
||||||
},
|
|
||||||
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
|
||||||
tags := MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
|
||||||
return tags.NeedsInformerInjection()
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func versionFactoryPackages(basePackage string, boilerplate []byte, customArgs *informergenargs.CustomArgs) []generator.Package {
|
|
||||||
packagePath := filepath.Join(basePackage, "informers", "factory")
|
|
||||||
|
|
||||||
return []generator.Package{
|
|
||||||
// Impl
|
|
||||||
&generator.DefaultPackage{
|
|
||||||
PackageName: "factory",
|
|
||||||
PackagePath: packagePath,
|
|
||||||
HeaderText: boilerplate,
|
|
||||||
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
|
|
||||||
// Impl
|
|
||||||
generators = append(generators, &factoryGenerator{
|
|
||||||
DefaultGen: generator.DefaultGen{
|
|
||||||
OptionalName: "factory",
|
|
||||||
},
|
|
||||||
outputPackage: packagePath,
|
|
||||||
cachingClientSetPackage: filepath.Join(basePackage, "client"),
|
|
||||||
sharedInformerFactoryPackage: customArgs.ExternalVersionsInformersPackage,
|
|
||||||
imports: generator.NewImportTracker(),
|
|
||||||
})
|
|
||||||
return generators
|
|
||||||
},
|
|
||||||
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
|
||||||
tags := MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
|
||||||
return tags.NeedsInformerInjection()
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// Fake
|
|
||||||
&generator.DefaultPackage{
|
|
||||||
PackageName: "fake",
|
|
||||||
PackagePath: filepath.Join(packagePath, "fake"),
|
|
||||||
HeaderText: boilerplate,
|
|
||||||
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
|
|
||||||
// Impl
|
|
||||||
generators = append(generators, &fakeFactoryGenerator{
|
|
||||||
DefaultGen: generator.DefaultGen{
|
|
||||||
OptionalName: "fake",
|
|
||||||
},
|
|
||||||
outputPackage: filepath.Join(packagePath, "fake"),
|
|
||||||
factoryInjectionPkg: packagePath,
|
|
||||||
fakeClientInjectionPkg: filepath.Join(basePackage, "client", "fake"),
|
|
||||||
sharedInformerFactoryPackage: customArgs.ExternalVersionsInformersPackage,
|
|
||||||
imports: generator.NewImportTracker(),
|
|
||||||
})
|
|
||||||
return generators
|
|
||||||
},
|
|
||||||
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
|
||||||
tags := MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
|
||||||
return tags.NeedsInformerInjection()
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
// FilterFactoryImpl
|
|
||||||
&generator.DefaultPackage{
|
|
||||||
PackageName: "filteredFactory",
|
|
||||||
PackagePath: filepath.Join(packagePath, "filtered"),
|
|
||||||
HeaderText: boilerplate,
|
|
||||||
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
|
|
||||||
// Impl
|
|
||||||
generators = append(generators, &filteredFactoryGenerator{
|
|
||||||
DefaultGen: generator.DefaultGen{
|
|
||||||
OptionalName: "filtered_factory",
|
|
||||||
},
|
|
||||||
outputPackage: filepath.Join(packagePath, "filtered"),
|
|
||||||
cachingClientSetPackage: filepath.Join(basePackage, "client"),
|
|
||||||
sharedInformerFactoryPackage: customArgs.ExternalVersionsInformersPackage,
|
|
||||||
imports: generator.NewImportTracker(),
|
|
||||||
})
|
|
||||||
return generators
|
|
||||||
},
|
|
||||||
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
|
||||||
tags := MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
|
||||||
return tags.NeedsInformerInjection()
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// FakeFilterFactory
|
|
||||||
&generator.DefaultPackage{
|
|
||||||
PackageName: "fakeFilteredFactory",
|
|
||||||
PackagePath: filepath.Join(packagePath, "filtered", "fake"),
|
|
||||||
HeaderText: boilerplate,
|
|
||||||
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
|
|
||||||
// Impl
|
|
||||||
generators = append(generators, &fakeFilteredFactoryGenerator{
|
|
||||||
DefaultGen: generator.DefaultGen{
|
|
||||||
OptionalName: "fake_filtered_factory",
|
|
||||||
},
|
|
||||||
outputPackage: filepath.Join(packagePath, "filtered", "fake"),
|
|
||||||
factoryInjectionPkg: filepath.Join(packagePath, "filtered"),
|
|
||||||
fakeClientInjectionPkg: filepath.Join(basePackage, "client", "fake"),
|
|
||||||
sharedInformerFactoryPackage: customArgs.ExternalVersionsInformersPackage,
|
|
||||||
imports: generator.NewImportTracker(),
|
|
||||||
})
|
|
||||||
return generators
|
|
||||||
},
|
|
||||||
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
|
||||||
tags := MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
|
||||||
return tags.NeedsInformerInjection()
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func versionInformerPackages(basePackage string, groupPkgName string, gv clientgentypes.GroupVersion, groupGoName string, boilerplate []byte, typesToGenerate []*types.Type, customArgs *informergenargs.CustomArgs) []generator.Package {
|
|
||||||
factoryPackagePath := filepath.Join(basePackage, "informers", "factory")
|
|
||||||
filteredFactoryPackagePath := filepath.Join(basePackage, "informers", "factory", "filtered")
|
|
||||||
|
|
||||||
packagePath := filepath.Join(basePackage, "informers", groupPkgName, strings.ToLower(gv.Version.NonEmpty()))
|
|
||||||
|
|
||||||
vers := make([]generator.Package, 0, 2*len(typesToGenerate))
|
|
||||||
|
|
||||||
for _, t := range typesToGenerate {
|
|
||||||
packagePath := packagePath + "/" + strings.ToLower(t.Name.Name)
|
|
||||||
typedInformerPackage := typedInformerPackage(groupPkgName, gv, customArgs.ExternalVersionsInformersPackage)
|
|
||||||
|
|
||||||
// Impl
|
|
||||||
vers = append(vers, &generator.DefaultPackage{
|
|
||||||
PackageName: strings.ToLower(t.Name.Name),
|
|
||||||
PackagePath: packagePath,
|
|
||||||
HeaderText: boilerplate,
|
|
||||||
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
|
|
||||||
// Impl
|
|
||||||
generators = append(generators, &injectionGenerator{
|
|
||||||
DefaultGen: generator.DefaultGen{
|
|
||||||
OptionalName: strings.ToLower(t.Name.Name),
|
|
||||||
},
|
|
||||||
outputPackage: packagePath,
|
|
||||||
groupVersion: gv,
|
|
||||||
groupGoName: groupGoName,
|
|
||||||
typeToGenerate: t,
|
|
||||||
imports: generator.NewImportTracker(),
|
|
||||||
typedInformerPackage: typedInformerPackage,
|
|
||||||
groupInformerFactoryPackage: factoryPackagePath,
|
|
||||||
disableInformerInit: customArgs.DisableInformerInit,
|
|
||||||
})
|
|
||||||
return generators
|
|
||||||
},
|
|
||||||
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
|
||||||
tags := MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
|
||||||
return tags.NeedsInformerInjection()
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
// Fake
|
|
||||||
vers = append(vers, &generator.DefaultPackage{
|
|
||||||
PackageName: "fake",
|
|
||||||
PackagePath: filepath.Join(packagePath, "fake"),
|
|
||||||
HeaderText: boilerplate,
|
|
||||||
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
|
|
||||||
// Impl
|
|
||||||
generators = append(generators, &fakeInformerGenerator{
|
|
||||||
DefaultGen: generator.DefaultGen{
|
|
||||||
OptionalName: "fake",
|
|
||||||
},
|
|
||||||
outputPackage: filepath.Join(packagePath, "fake"),
|
|
||||||
imports: generator.NewImportTracker(),
|
|
||||||
typeToGenerate: t,
|
|
||||||
groupVersion: gv,
|
|
||||||
groupGoName: groupGoName,
|
|
||||||
informerInjectionPkg: packagePath,
|
|
||||||
fakeFactoryInjectionPkg: filepath.Join(factoryPackagePath, "fake"),
|
|
||||||
})
|
|
||||||
return generators
|
|
||||||
},
|
|
||||||
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
|
||||||
tags := MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
|
||||||
return tags.NeedsInformerInjection()
|
|
||||||
},
|
|
||||||
})
|
|
||||||
// FilteredInformer
|
|
||||||
vers = append(vers, &generator.DefaultPackage{
|
|
||||||
PackageName: "filtered",
|
|
||||||
PackagePath: filepath.Join(packagePath, "filtered"),
|
|
||||||
HeaderText: boilerplate,
|
|
||||||
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
|
|
||||||
// Impl
|
|
||||||
generators = append(generators, &filteredInjectionGenerator{
|
|
||||||
DefaultGen: generator.DefaultGen{
|
|
||||||
OptionalName: strings.ToLower(t.Name.Name),
|
|
||||||
},
|
|
||||||
outputPackage: filepath.Join(packagePath, "filtered"),
|
|
||||||
groupVersion: gv,
|
|
||||||
groupGoName: groupGoName,
|
|
||||||
typeToGenerate: t,
|
|
||||||
imports: generator.NewImportTracker(),
|
|
||||||
typedInformerPackage: typedInformerPackage,
|
|
||||||
groupInformerFactoryPackage: filteredFactoryPackagePath,
|
|
||||||
})
|
|
||||||
return generators
|
|
||||||
},
|
|
||||||
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
|
||||||
tags := MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
|
||||||
return tags.NeedsInformerInjection()
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
// FakeFilteredInformer
|
|
||||||
vers = append(vers, &generator.DefaultPackage{
|
|
||||||
PackageName: "fake",
|
|
||||||
PackagePath: filepath.Join(packagePath, "filtered", "fake"),
|
|
||||||
HeaderText: boilerplate,
|
|
||||||
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
|
|
||||||
// Impl
|
|
||||||
generators = append(generators, &fakeFilteredInformerGenerator{
|
|
||||||
DefaultGen: generator.DefaultGen{
|
|
||||||
OptionalName: "fake",
|
|
||||||
},
|
|
||||||
outputPackage: filepath.Join(packagePath, "filtered", "fake"),
|
|
||||||
imports: generator.NewImportTracker(),
|
|
||||||
typeToGenerate: t,
|
|
||||||
groupVersion: gv,
|
|
||||||
groupGoName: groupGoName,
|
|
||||||
informerInjectionPkg: filepath.Join(packagePath, "filtered"),
|
|
||||||
fakeFactoryInjectionPkg: filteredFactoryPackagePath,
|
|
||||||
})
|
|
||||||
return generators
|
|
||||||
},
|
|
||||||
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
|
||||||
tags := MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
|
||||||
return tags.NeedsInformerInjection()
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return vers
|
|
||||||
}
|
|
||||||
|
|
||||||
func reconcilerPackages(basePackage string, groupPkgName string, gv clientgentypes.GroupVersion, groupGoName string, boilerplate []byte, typesToGenerate []*types.Type, customArgs *informergenargs.CustomArgs) []generator.Package {
|
|
||||||
packagePath := filepath.Join(basePackage, "reconciler", groupPkgName, strings.ToLower(gv.Version.NonEmpty()))
|
|
||||||
clientPackagePath := filepath.Join(basePackage, "client")
|
|
||||||
|
|
||||||
vers := make([]generator.Package, 0, 4*len(typesToGenerate))
|
|
||||||
|
|
||||||
for _, t := range typesToGenerate {
|
|
||||||
extracted := extractCommentTags(t)
|
|
||||||
reconcilerClasses, hasReconcilerClass := extractReconcilerClassesTag(extracted)
|
|
||||||
nonNamespaced := isNonNamespaced(extracted)
|
|
||||||
isKRShaped := isKRShaped(extracted)
|
|
||||||
stubs := stubs(extracted)
|
|
||||||
|
|
||||||
packagePath := filepath.Join(packagePath, strings.ToLower(t.Name.Name))
|
|
||||||
|
|
||||||
informerPackagePath := filepath.Join(basePackage, "informers", groupPkgName, strings.ToLower(gv.Version.NonEmpty()), strings.ToLower(t.Name.Name))
|
|
||||||
listerPackagePath := filepath.Join(customArgs.ListersPackage, groupPkgName, strings.ToLower(gv.Version.NonEmpty()))
|
|
||||||
|
|
||||||
// Controller
|
|
||||||
vers = append(vers, &generator.DefaultPackage{
|
|
||||||
PackageName: strings.ToLower(t.Name.Name),
|
|
||||||
PackagePath: packagePath,
|
|
||||||
HeaderText: boilerplate,
|
|
||||||
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
|
|
||||||
// Impl
|
|
||||||
generators = append(generators, &reconcilerControllerGenerator{
|
|
||||||
DefaultGen: generator.DefaultGen{
|
|
||||||
OptionalName: "controller",
|
|
||||||
},
|
|
||||||
typeToGenerate: t,
|
|
||||||
outputPackage: packagePath,
|
|
||||||
imports: generator.NewImportTracker(),
|
|
||||||
groupName: gv.Group.String(),
|
|
||||||
clientPkg: clientPackagePath,
|
|
||||||
informerPackagePath: informerPackagePath,
|
|
||||||
schemePkg: filepath.Join(customArgs.VersionedClientSetPackage, "scheme"),
|
|
||||||
reconcilerClasses: reconcilerClasses,
|
|
||||||
hasReconcilerClass: hasReconcilerClass,
|
|
||||||
hasStatus: hasStatus(t),
|
|
||||||
})
|
|
||||||
return generators
|
|
||||||
},
|
|
||||||
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
|
||||||
tags := MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
|
||||||
return tags.NeedsReconciler(t, customArgs)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
if stubs {
|
|
||||||
// Controller Stub
|
|
||||||
vers = append(vers, &generator.DefaultPackage{
|
|
||||||
PackageName: strings.ToLower(t.Name.Name),
|
|
||||||
PackagePath: filepath.Join(packagePath, "stub"),
|
|
||||||
HeaderText: boilerplate,
|
|
||||||
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
|
|
||||||
// Impl
|
|
||||||
generators = append(generators, &reconcilerControllerStubGenerator{
|
|
||||||
DefaultGen: generator.DefaultGen{
|
|
||||||
OptionalName: "controller",
|
|
||||||
},
|
|
||||||
typeToGenerate: t,
|
|
||||||
reconcilerPkg: packagePath,
|
|
||||||
outputPackage: filepath.Join(packagePath, "stub"),
|
|
||||||
imports: generator.NewImportTracker(),
|
|
||||||
informerPackagePath: informerPackagePath,
|
|
||||||
reconcilerClasses: reconcilerClasses,
|
|
||||||
hasReconcilerClass: hasReconcilerClass,
|
|
||||||
})
|
|
||||||
return generators
|
|
||||||
},
|
|
||||||
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
|
||||||
tags := MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
|
||||||
return tags.NeedsReconciler(t, customArgs)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reconciler
|
|
||||||
vers = append(vers, &generator.DefaultPackage{
|
|
||||||
PackageName: strings.ToLower(t.Name.Name),
|
|
||||||
PackagePath: packagePath,
|
|
||||||
HeaderText: boilerplate,
|
|
||||||
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
|
|
||||||
// Impl
|
|
||||||
generators = append(generators, &reconcilerReconcilerGenerator{
|
|
||||||
DefaultGen: generator.DefaultGen{
|
|
||||||
OptionalName: "reconciler",
|
|
||||||
},
|
|
||||||
typeToGenerate: t,
|
|
||||||
outputPackage: packagePath,
|
|
||||||
imports: generator.NewImportTracker(),
|
|
||||||
clientsetPkg: customArgs.VersionedClientSetPackage,
|
|
||||||
listerName: t.Name.Name + "Lister",
|
|
||||||
listerPkg: listerPackagePath,
|
|
||||||
groupGoName: groupGoName,
|
|
||||||
groupVersion: gv,
|
|
||||||
reconcilerClasses: reconcilerClasses,
|
|
||||||
hasReconcilerClass: hasReconcilerClass,
|
|
||||||
nonNamespaced: nonNamespaced,
|
|
||||||
isKRShaped: isKRShaped,
|
|
||||||
hasStatus: hasStatus(t),
|
|
||||||
})
|
|
||||||
return generators
|
|
||||||
},
|
|
||||||
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
|
||||||
tags := MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
|
||||||
return tags.NeedsReconciler(t, customArgs)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
if stubs {
|
|
||||||
// Reconciler Stub
|
|
||||||
vers = append(vers, &generator.DefaultPackage{
|
|
||||||
PackageName: strings.ToLower(t.Name.Name),
|
|
||||||
PackagePath: filepath.Join(packagePath, "stub"),
|
|
||||||
HeaderText: boilerplate,
|
|
||||||
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
|
|
||||||
// Impl
|
|
||||||
generators = append(generators, &reconcilerReconcilerStubGenerator{
|
|
||||||
DefaultGen: generator.DefaultGen{
|
|
||||||
OptionalName: "reconciler",
|
|
||||||
},
|
|
||||||
typeToGenerate: t,
|
|
||||||
reconcilerPkg: packagePath,
|
|
||||||
outputPackage: filepath.Join(packagePath, "stub"),
|
|
||||||
imports: generator.NewImportTracker(),
|
|
||||||
})
|
|
||||||
return generators
|
|
||||||
},
|
|
||||||
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
|
||||||
tags := MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
|
||||||
return tags.NeedsReconciler(t, customArgs)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reconciler State
|
|
||||||
vers = append(vers, &generator.DefaultPackage{
|
|
||||||
PackageName: strings.ToLower(t.Name.Name),
|
|
||||||
PackagePath: packagePath,
|
|
||||||
HeaderText: boilerplate,
|
|
||||||
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
|
|
||||||
// state
|
|
||||||
generators = append(generators, &reconcilerStateGenerator{
|
|
||||||
DefaultGen: generator.DefaultGen{
|
|
||||||
OptionalName: "state",
|
|
||||||
},
|
|
||||||
typeToGenerate: t,
|
|
||||||
outputPackage: packagePath,
|
|
||||||
imports: generator.NewImportTracker(),
|
|
||||||
})
|
|
||||||
return generators
|
|
||||||
},
|
|
||||||
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
|
||||||
tags := MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
|
||||||
return tags.NeedsReconciler(t, customArgs)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return vers
|
|
||||||
}
|
|
||||||
|
|
||||||
func versionDuckPackages(basePackage string, groupPkgName string, gv clientgentypes.GroupVersion, groupGoName string, boilerplate []byte, typesToGenerate []*types.Type, _ *informergenargs.CustomArgs) []generator.Package {
|
|
||||||
packagePath := filepath.Join(basePackage, "ducks", groupPkgName, strings.ToLower(gv.Version.NonEmpty()))
|
|
||||||
|
|
||||||
vers := make([]generator.Package, 0, 2*len(typesToGenerate))
|
|
||||||
|
|
||||||
for _, t := range typesToGenerate {
|
|
||||||
// Fix for golang iterator bug.
|
|
||||||
packagePath := filepath.Join(packagePath, strings.ToLower(t.Name.Name))
|
|
||||||
|
|
||||||
// Impl
|
|
||||||
vers = append(vers, &generator.DefaultPackage{
|
|
||||||
PackageName: strings.ToLower(t.Name.Name),
|
|
||||||
PackagePath: packagePath,
|
|
||||||
HeaderText: boilerplate,
|
|
||||||
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
|
|
||||||
// Impl
|
|
||||||
generators = append(generators, &duckGenerator{
|
|
||||||
DefaultGen: generator.DefaultGen{
|
|
||||||
OptionalName: strings.ToLower(t.Name.Name),
|
|
||||||
},
|
|
||||||
outputPackage: packagePath,
|
|
||||||
groupVersion: gv,
|
|
||||||
groupGoName: groupGoName,
|
|
||||||
typeToGenerate: t,
|
|
||||||
imports: generator.NewImportTracker(),
|
|
||||||
})
|
|
||||||
return generators
|
|
||||||
},
|
|
||||||
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
|
||||||
tags := MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
|
||||||
return tags.NeedsDuckInjection()
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
// Fake
|
|
||||||
vers = append(vers, &generator.DefaultPackage{
|
|
||||||
PackageName: "fake",
|
|
||||||
PackagePath: filepath.Join(packagePath, "fake"),
|
|
||||||
HeaderText: boilerplate,
|
|
||||||
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
|
|
||||||
// Impl
|
|
||||||
generators = append(generators, &fakeDuckGenerator{
|
|
||||||
DefaultGen: generator.DefaultGen{
|
|
||||||
OptionalName: "fake",
|
|
||||||
},
|
|
||||||
outputPackage: filepath.Join(packagePath, "fake"),
|
|
||||||
imports: generator.NewImportTracker(),
|
|
||||||
typeToGenerate: t,
|
|
||||||
groupVersion: gv,
|
|
||||||
groupGoName: groupGoName,
|
|
||||||
duckInjectionPkg: packagePath,
|
|
||||||
})
|
|
||||||
return generators
|
|
||||||
},
|
|
||||||
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
|
||||||
tags := MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
|
||||||
return tags.NeedsDuckInjection()
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return vers
|
|
||||||
}
|
|
||||||
|
|
||||||
func hasStatus(t *types.Type) bool {
|
|
||||||
for _, member := range t.Members {
|
|
||||||
if member.Name == "Status" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2020 The Knative Authors.
|
Copyright 2020 The Knative Authors
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -14,21 +14,21 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package generators
|
package reconciler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"k8s.io/gengo/generator"
|
"k8s.io/gengo/v2/generator"
|
||||||
"k8s.io/gengo/namer"
|
"k8s.io/gengo/v2/namer"
|
||||||
"k8s.io/gengo/types"
|
"k8s.io/gengo/v2/types"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// reconcilerControllerGenerator produces a file for setting up the reconciler
|
// reconcilerControllerGenerator produces a file for setting up the reconciler
|
||||||
// with injection.
|
// with injection.
|
||||||
type reconcilerControllerGenerator struct {
|
type reconcilerControllerGenerator struct {
|
||||||
generator.DefaultGen
|
generator.GoGenerator
|
||||||
outputPackage string
|
outputPackage string
|
||||||
imports namer.ImportTracker
|
imports namer.ImportTracker
|
||||||
typeToGenerate *types.Type
|
typeToGenerate *types.Type
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2020 The Knative Authors.
|
Copyright 2020 The Knative Authors
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -14,21 +14,21 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package generators
|
package reconciler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"k8s.io/gengo/generator"
|
"k8s.io/gengo/v2/generator"
|
||||||
"k8s.io/gengo/namer"
|
"k8s.io/gengo/v2/namer"
|
||||||
"k8s.io/gengo/types"
|
"k8s.io/gengo/v2/types"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// reconcilerControllerStubGenerator produces a file of the stub of the
|
// reconcilerControllerStubGenerator produces a file of the stub of the
|
||||||
// controller for a custom impl with injection.
|
// controller for a custom impl with injection.
|
||||||
type reconcilerControllerStubGenerator struct {
|
type reconcilerControllerStubGenerator struct {
|
||||||
generator.DefaultGen
|
generator.GoGenerator
|
||||||
outputPackage string
|
outputPackage string
|
||||||
imports namer.ImportTracker
|
imports namer.ImportTracker
|
||||||
typeToGenerate *types.Type
|
typeToGenerate *types.Type
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2020 The Knative Authors.
|
Copyright 2020 The Knative Authors
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -14,22 +14,22 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package generators
|
package reconciler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
|
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
|
||||||
|
|
||||||
"k8s.io/gengo/generator"
|
"k8s.io/gengo/v2/generator"
|
||||||
"k8s.io/gengo/namer"
|
"k8s.io/gengo/v2/namer"
|
||||||
"k8s.io/gengo/types"
|
"k8s.io/gengo/v2/types"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// reconcilerReconcilerGenerator produces a reconciler struct for the given type.
|
// reconcilerReconcilerGenerator produces a reconciler struct for the given type.
|
||||||
type reconcilerReconcilerGenerator struct {
|
type reconcilerReconcilerGenerator struct {
|
||||||
generator.DefaultGen
|
generator.GoGenerator
|
||||||
outputPackage string
|
outputPackage string
|
||||||
imports namer.ImportTracker
|
imports namer.ImportTracker
|
||||||
typeToGenerate *types.Type
|
typeToGenerate *types.Type
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2020 The Knative Authors.
|
Copyright 2020 The Knative Authors
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -14,21 +14,21 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package generators
|
package reconciler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"k8s.io/gengo/generator"
|
"k8s.io/gengo/v2/generator"
|
||||||
"k8s.io/gengo/namer"
|
"k8s.io/gengo/v2/namer"
|
||||||
"k8s.io/gengo/types"
|
"k8s.io/gengo/v2/types"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// reconcilerReconcilerStubGenerator produces a file of the stub of how to
|
// reconcilerReconcilerStubGenerator produces a file of the stub of how to
|
||||||
// implement the reconciler.
|
// implement the reconciler.
|
||||||
type reconcilerReconcilerStubGenerator struct {
|
type reconcilerReconcilerStubGenerator struct {
|
||||||
generator.DefaultGen
|
generator.GoGenerator
|
||||||
outputPackage string
|
outputPackage string
|
||||||
imports namer.ImportTracker
|
imports namer.ImportTracker
|
||||||
typeToGenerate *types.Type
|
typeToGenerate *types.Type
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2020 The Knative Authors.
|
Copyright 2020 The Knative Authors
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -14,20 +14,20 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package generators
|
package reconciler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"k8s.io/gengo/generator"
|
"k8s.io/gengo/v2/generator"
|
||||||
"k8s.io/gengo/namer"
|
"k8s.io/gengo/v2/namer"
|
||||||
"k8s.io/gengo/types"
|
"k8s.io/gengo/v2/types"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// reconcilerStateGenerator produces a reconciler state object to manage reconciliation runs.
|
// reconcilerStateGenerator produces a reconciler state object to manage reconciliation runs.
|
||||||
type reconcilerStateGenerator struct {
|
type reconcilerStateGenerator struct {
|
||||||
generator.DefaultGen
|
generator.GoGenerator
|
||||||
outputPackage string
|
outputPackage string
|
||||||
imports namer.ImportTracker
|
imports namer.ImportTracker
|
||||||
typeToGenerate *types.Type
|
typeToGenerate *types.Type
|
256
vendor/knative.dev/pkg/codegen/cmd/injection-gen/generators/reconciler/targets.go
vendored
Normal file
256
vendor/knative.dev/pkg/codegen/cmd/injection-gen/generators/reconciler/targets.go
vendored
Normal file
|
@ -0,0 +1,256 @@
|
||||||
|
/*
|
||||||
|
Copyright 2024 The Knative Authors
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package reconciler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
|
||||||
|
"k8s.io/gengo/v2/generator"
|
||||||
|
"k8s.io/gengo/v2/types"
|
||||||
|
"knative.dev/pkg/codegen/cmd/injection-gen/args"
|
||||||
|
"knative.dev/pkg/codegen/cmd/injection-gen/tags"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Targets(
|
||||||
|
args *args.Args,
|
||||||
|
groupPkgName string,
|
||||||
|
gv clientgentypes.GroupVersion,
|
||||||
|
groupGoName string,
|
||||||
|
typesToGenerate []*types.Type,
|
||||||
|
) []generator.Target {
|
||||||
|
basePackage := args.GetOutputPackagePath()
|
||||||
|
packagePath := filepath.Join(basePackage, "reconciler", groupPkgName, strings.ToLower(gv.Version.NonEmpty()))
|
||||||
|
packageDir := filepath.Join(args.GetOutputDir(), "reconciler", groupPkgName, strings.ToLower(gv.Version.NonEmpty()))
|
||||||
|
|
||||||
|
clientPackagePath := filepath.Join(basePackage, "client")
|
||||||
|
|
||||||
|
vers := make([]generator.Target, 0, 4*len(typesToGenerate))
|
||||||
|
|
||||||
|
for _, t := range typesToGenerate {
|
||||||
|
extracted := extractCommentTags(t)
|
||||||
|
reconcilerClasses, hasReconcilerClass := extractReconcilerClassesTag(extracted)
|
||||||
|
nonNamespaced := isNonNamespaced(extracted)
|
||||||
|
isKRShaped := isKRShaped(extracted)
|
||||||
|
stubs := stubs(extracted)
|
||||||
|
|
||||||
|
packagePath := filepath.Join(packagePath, strings.ToLower(t.Name.Name))
|
||||||
|
packageDir := filepath.Join(packageDir, strings.ToLower(t.Name.Name))
|
||||||
|
|
||||||
|
informerPackagePath := filepath.Join(basePackage, "informers", groupPkgName, strings.ToLower(gv.Version.NonEmpty()), strings.ToLower(t.Name.Name))
|
||||||
|
listerPackagePath := filepath.Join(args.ListersPackage, groupPkgName, strings.ToLower(gv.Version.NonEmpty()))
|
||||||
|
|
||||||
|
// Controller
|
||||||
|
vers = append(vers, &generator.SimpleTarget{
|
||||||
|
PkgName: strings.ToLower(t.Name.Name),
|
||||||
|
PkgPath: packagePath,
|
||||||
|
PkgDir: packageDir,
|
||||||
|
HeaderComment: args.Boilerplate,
|
||||||
|
GeneratorsFunc: func(c *generator.Context) []generator.Generator {
|
||||||
|
// Impl
|
||||||
|
return []generator.Generator{&reconcilerControllerGenerator{
|
||||||
|
GoGenerator: generator.GoGenerator{
|
||||||
|
OutputFilename: "controller.go",
|
||||||
|
},
|
||||||
|
typeToGenerate: t,
|
||||||
|
outputPackage: packagePath,
|
||||||
|
imports: generator.NewImportTracker(),
|
||||||
|
groupName: gv.Group.String(),
|
||||||
|
clientPkg: clientPackagePath,
|
||||||
|
informerPackagePath: informerPackagePath,
|
||||||
|
schemePkg: filepath.Join(args.VersionedClientSetPackage, "scheme"),
|
||||||
|
reconcilerClasses: reconcilerClasses,
|
||||||
|
hasReconcilerClass: hasReconcilerClass,
|
||||||
|
hasStatus: hasStatus(t),
|
||||||
|
}}
|
||||||
|
},
|
||||||
|
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
||||||
|
tags := tags.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||||
|
return tags.NeedsReconciler(t, args)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if stubs {
|
||||||
|
// Controller Stub
|
||||||
|
vers = append(vers, &generator.SimpleTarget{
|
||||||
|
PkgName: strings.ToLower(t.Name.Name),
|
||||||
|
PkgPath: filepath.Join(packagePath, "stub"),
|
||||||
|
PkgDir: filepath.Join(packageDir, "stub"),
|
||||||
|
HeaderComment: args.Boilerplate,
|
||||||
|
GeneratorsFunc: func(c *generator.Context) []generator.Generator {
|
||||||
|
// Impl
|
||||||
|
return []generator.Generator{&reconcilerControllerStubGenerator{
|
||||||
|
GoGenerator: generator.GoGenerator{
|
||||||
|
OutputFilename: "controller.go",
|
||||||
|
},
|
||||||
|
typeToGenerate: t,
|
||||||
|
reconcilerPkg: packagePath,
|
||||||
|
outputPackage: filepath.Join(packagePath, "stub"),
|
||||||
|
imports: generator.NewImportTracker(),
|
||||||
|
informerPackagePath: informerPackagePath,
|
||||||
|
reconcilerClasses: reconcilerClasses,
|
||||||
|
hasReconcilerClass: hasReconcilerClass,
|
||||||
|
}}
|
||||||
|
},
|
||||||
|
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
||||||
|
tags := tags.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||||
|
return tags.NeedsReconciler(t, args)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reconciler
|
||||||
|
vers = append(vers, &generator.SimpleTarget{
|
||||||
|
PkgName: strings.ToLower(t.Name.Name),
|
||||||
|
PkgPath: packagePath,
|
||||||
|
PkgDir: packageDir,
|
||||||
|
HeaderComment: args.Boilerplate,
|
||||||
|
GeneratorsFunc: func(c *generator.Context) []generator.Generator {
|
||||||
|
// Impl
|
||||||
|
return []generator.Generator{&reconcilerReconcilerGenerator{
|
||||||
|
GoGenerator: generator.GoGenerator{
|
||||||
|
OutputFilename: "reconciler.go",
|
||||||
|
},
|
||||||
|
typeToGenerate: t,
|
||||||
|
outputPackage: packagePath,
|
||||||
|
imports: generator.NewImportTracker(),
|
||||||
|
clientsetPkg: args.VersionedClientSetPackage,
|
||||||
|
listerName: t.Name.Name + "Lister",
|
||||||
|
listerPkg: listerPackagePath,
|
||||||
|
groupGoName: groupGoName,
|
||||||
|
groupVersion: gv,
|
||||||
|
reconcilerClasses: reconcilerClasses,
|
||||||
|
hasReconcilerClass: hasReconcilerClass,
|
||||||
|
nonNamespaced: nonNamespaced,
|
||||||
|
isKRShaped: isKRShaped,
|
||||||
|
hasStatus: hasStatus(t),
|
||||||
|
}}
|
||||||
|
},
|
||||||
|
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
||||||
|
tags := tags.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||||
|
return tags.NeedsReconciler(t, args)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if stubs {
|
||||||
|
// Reconciler Stub
|
||||||
|
vers = append(vers, &generator.SimpleTarget{
|
||||||
|
PkgName: strings.ToLower(t.Name.Name),
|
||||||
|
PkgPath: filepath.Join(packagePath, "stub"),
|
||||||
|
PkgDir: filepath.Join(packageDir, "stub"),
|
||||||
|
HeaderComment: args.Boilerplate,
|
||||||
|
GeneratorsFunc: func(c *generator.Context) []generator.Generator {
|
||||||
|
// Impl
|
||||||
|
return []generator.Generator{&reconcilerReconcilerStubGenerator{
|
||||||
|
GoGenerator: generator.GoGenerator{
|
||||||
|
OutputFilename: "reconciler.go",
|
||||||
|
},
|
||||||
|
typeToGenerate: t,
|
||||||
|
reconcilerPkg: packagePath,
|
||||||
|
outputPackage: filepath.Join(packagePath, "stub"),
|
||||||
|
imports: generator.NewImportTracker(),
|
||||||
|
}}
|
||||||
|
},
|
||||||
|
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
||||||
|
tags := tags.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||||
|
return tags.NeedsReconciler(t, args)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reconciler State
|
||||||
|
vers = append(vers, &generator.SimpleTarget{
|
||||||
|
PkgName: strings.ToLower(t.Name.Name),
|
||||||
|
PkgPath: packagePath,
|
||||||
|
PkgDir: packageDir,
|
||||||
|
HeaderComment: args.Boilerplate,
|
||||||
|
GeneratorsFunc: func(c *generator.Context) []generator.Generator {
|
||||||
|
// state
|
||||||
|
return []generator.Generator{&reconcilerStateGenerator{
|
||||||
|
GoGenerator: generator.GoGenerator{
|
||||||
|
OutputFilename: "state.go",
|
||||||
|
},
|
||||||
|
typeToGenerate: t,
|
||||||
|
outputPackage: packagePath,
|
||||||
|
imports: generator.NewImportTracker(),
|
||||||
|
}}
|
||||||
|
},
|
||||||
|
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
||||||
|
tags := tags.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||||
|
return tags.NeedsReconciler(t, args)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return vers
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractCommentTags(t *types.Type) tags.CommentTags {
|
||||||
|
comments := append(append([]string{}, t.SecondClosestCommentLines...), t.CommentLines...)
|
||||||
|
return tags.ExtractCommentTags("+", comments)
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractReconcilerClassesTag(tags tags.CommentTags) ([]string, bool) {
|
||||||
|
vals, ok := tags["genreconciler"]
|
||||||
|
if !ok {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
classnames, has := vals["class"]
|
||||||
|
if has && len(classnames) == 0 {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
return classnames, has
|
||||||
|
}
|
||||||
|
|
||||||
|
func isKRShaped(tags tags.CommentTags) bool {
|
||||||
|
vals, has := tags["genreconciler"]
|
||||||
|
if !has {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
stringVals, has := vals["krshapedlogic"]
|
||||||
|
if !has || len(vals) == 0 {
|
||||||
|
return true // Default is true
|
||||||
|
}
|
||||||
|
return stringVals[0] != "false"
|
||||||
|
}
|
||||||
|
|
||||||
|
func isNonNamespaced(tags tags.CommentTags) bool {
|
||||||
|
vals, has := tags["genclient"]
|
||||||
|
if !has {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
_, has = vals["nonNamespaced"]
|
||||||
|
return has
|
||||||
|
}
|
||||||
|
|
||||||
|
func stubs(tags tags.CommentTags) bool {
|
||||||
|
vals, has := tags["genreconciler"]
|
||||||
|
if !has {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
_, has = vals["stubs"]
|
||||||
|
return has
|
||||||
|
}
|
||||||
|
|
||||||
|
func hasStatus(t *types.Type) bool {
|
||||||
|
for _, member := range t.Members {
|
||||||
|
if member.Name == "Status" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2019 The Knative Authors.
|
Copyright 2019 The Knative Authors
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -19,37 +19,44 @@ package main
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
|
|
||||||
"k8s.io/klog/v2"
|
|
||||||
|
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
generatorargs "knative.dev/pkg/codegen/cmd/injection-gen/args"
|
|
||||||
|
"knative.dev/pkg/codegen/cmd/injection-gen/args"
|
||||||
"knative.dev/pkg/codegen/cmd/injection-gen/generators"
|
"knative.dev/pkg/codegen/cmd/injection-gen/generators"
|
||||||
|
"knative.dev/pkg/codegen/cmd/injection-gen/namer"
|
||||||
|
|
||||||
|
"k8s.io/code-generator/pkg/util"
|
||||||
|
"k8s.io/gengo/v2"
|
||||||
|
"k8s.io/gengo/v2/generator"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
klog.InitFlags(nil)
|
klog.InitFlags(nil)
|
||||||
genericArgs, customArgs := generatorargs.NewDefaults()
|
args := args.New()
|
||||||
|
|
||||||
// Override defaults.
|
args.AddFlags(pflag.CommandLine)
|
||||||
genericArgs.OutputPackagePath = "k8s.io/kubernetes/pkg/client/injection/informers/informers_generated"
|
|
||||||
|
|
||||||
genericArgs.AddFlags(pflag.CommandLine)
|
|
||||||
customArgs.AddFlags(pflag.CommandLine)
|
|
||||||
flag.Set("logtostderr", "true")
|
flag.Set("logtostderr", "true")
|
||||||
pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
|
pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
|
||||||
pflag.Parse()
|
pflag.Parse()
|
||||||
|
|
||||||
if err := generatorargs.Validate(genericArgs); err != nil {
|
if err := args.Validate(); err != nil {
|
||||||
klog.Fatal("Error: ", err)
|
klog.Fatal("Error: ", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
myTargets := func(context *generator.Context) []generator.Target {
|
||||||
|
return generators.Targets(context, args)
|
||||||
|
}
|
||||||
|
|
||||||
// Run it.
|
// Run it.
|
||||||
if err := genericArgs.Execute(
|
if err := gengo.Execute(
|
||||||
generators.NameSystems(),
|
namer.NameSystems(util.PluralExceptionListToMapOrDie(args.PluralExceptions)),
|
||||||
generators.DefaultNameSystem(),
|
namer.DefaultNameSystem(),
|
||||||
generators.Packages,
|
myTargets,
|
||||||
|
gengo.StdBuildTag,
|
||||||
|
args.InputDirs,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
klog.Fatal("Error: ", err)
|
klog.Fatalf("Error: %v", err)
|
||||||
}
|
}
|
||||||
klog.V(2).Info("Completed successfully.")
|
klog.V(2).Info("Completed successfully.")
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2019 The Knative Authors.
|
Copyright 2016 The Kubernetes Authors
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -14,49 +14,51 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package generators
|
package namer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"k8s.io/gengo/namer"
|
"k8s.io/gengo/v2"
|
||||||
"k8s.io/gengo/types"
|
"k8s.io/gengo/v2/namer"
|
||||||
|
"k8s.io/gengo/v2/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NameSystems returns the name system used by the generators in this package.
|
// TagOverrideNamer is a namer which pulls names from a given tag, if specified,
|
||||||
func NameSystems() namer.NameSystems {
|
// and otherwise falls back to a different namer.
|
||||||
pluralExceptions := map[string]string{
|
type tagOverrideNamer struct {
|
||||||
"Endpoints": "Endpoints",
|
tagName string
|
||||||
|
fallback namer.Namer
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name returns the tag value if it exists. It no tag was found the fallback namer will be used
|
||||||
|
func (n *tagOverrideNamer) Name(t *types.Type) string {
|
||||||
|
nameOverride := extractTag(n.tagName, append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||||
|
if nameOverride != "" {
|
||||||
|
return nameOverride
|
||||||
}
|
}
|
||||||
|
|
||||||
publicPluralNamer := namer.NewPublicPluralNamer(pluralExceptions)
|
return n.fallback.Name(t)
|
||||||
|
}
|
||||||
|
|
||||||
publicNamer := &ExceptionNamer{
|
// NewTagOverrideNamer creates a namer.Namer which uses the contents of the given tag as
|
||||||
Exceptions: map[string]string{},
|
// the name, or falls back to another Namer if the tag is not present.
|
||||||
KeyFunc: func(t *types.Type) string {
|
func newTagOverrideNamer(tagName string, fallback namer.Namer) namer.Namer {
|
||||||
return t.Name.Package + "." + t.Name.Name
|
return &tagOverrideNamer{
|
||||||
},
|
tagName: tagName,
|
||||||
Delegate: namer.NewPublicNamer(0),
|
fallback: fallback,
|
||||||
}
|
|
||||||
|
|
||||||
return namer.NameSystems{
|
|
||||||
"public": namer.NewPublicNamer(0),
|
|
||||||
"private": namer.NewPrivateNamer(0),
|
|
||||||
"raw": namer.NewRawNamer("", nil),
|
|
||||||
"publicPlural": publicPluralNamer,
|
|
||||||
"allLowercasePlural": namer.NewAllLowercasePluralNamer(pluralExceptions),
|
|
||||||
"lowercaseSingular": &lowercaseSingularNamer{},
|
|
||||||
"apiGroup": newTagOverrideNamer("publicPlural", publicPluralNamer),
|
|
||||||
"versionedClientset": &versionedClientsetNamer{public: publicNamer},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// lowercaseSingularNamer implements Namer
|
// extractTag gets the comment-tags for the key. If the tag did not exist, it
|
||||||
type lowercaseSingularNamer struct{}
|
// returns the empty string.
|
||||||
|
func extractTag(key string, lines []string) string {
|
||||||
|
val, present := gengo.ExtractCommentTags("+", lines)[key]
|
||||||
|
if !present || len(val) < 1 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
// Name returns t's name in all lowercase.
|
return val[0]
|
||||||
func (n *lowercaseSingularNamer) Name(t *types.Type) string {
|
|
||||||
return strings.ToLower(t.Name.Name)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type versionedClientsetNamer struct {
|
type versionedClientsetNamer struct {
|
||||||
|
@ -75,12 +77,6 @@ func (r *versionedClientsetNamer) Name(t *types.Type) string {
|
||||||
return g + v
|
return g + v
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultNameSystem returns the default name system for ordering the types to be
|
|
||||||
// processed by the generators in this package.
|
|
||||||
func DefaultNameSystem() string {
|
|
||||||
return "public"
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExceptionNamer allows you specify exceptional cases with exact names. This allows you to have control
|
// ExceptionNamer allows you specify exceptional cases with exact names. This allows you to have control
|
||||||
// for handling various conflicts, like group and resource names for instance.
|
// for handling various conflicts, like group and resource names for instance.
|
||||||
type ExceptionNamer struct {
|
type ExceptionNamer struct {
|
||||||
|
@ -98,3 +94,11 @@ func (n *ExceptionNamer) Name(t *types.Type) string {
|
||||||
}
|
}
|
||||||
return n.Delegate.Name(t)
|
return n.Delegate.Name(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// lowercaseSingularNamer implements Namer
|
||||||
|
type lowercaseSingularNamer struct{}
|
||||||
|
|
||||||
|
// Name returns t's name in all lowercase.
|
||||||
|
func (n *lowercaseSingularNamer) Name(t *types.Type) string {
|
||||||
|
return strings.ToLower(t.Name.Name)
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
Copyright 2019 The Knative Authors
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package namer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"k8s.io/gengo/v2/namer"
|
||||||
|
"k8s.io/gengo/v2/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NameSystems returns the name system used by the generators in this package.
|
||||||
|
func NameSystems(pluralExceptions map[string]string) namer.NameSystems {
|
||||||
|
pluralExceptions["Endpoints"] = "Endpoints"
|
||||||
|
|
||||||
|
publicPluralNamer := namer.NewPublicPluralNamer(pluralExceptions)
|
||||||
|
|
||||||
|
publicNamer := &ExceptionNamer{
|
||||||
|
Exceptions: map[string]string{},
|
||||||
|
KeyFunc: func(t *types.Type) string {
|
||||||
|
return t.Name.Package + "." + t.Name.Name
|
||||||
|
},
|
||||||
|
Delegate: namer.NewPublicNamer(0),
|
||||||
|
}
|
||||||
|
|
||||||
|
return namer.NameSystems{
|
||||||
|
"public": namer.NewPublicNamer(0),
|
||||||
|
"private": namer.NewPrivateNamer(0),
|
||||||
|
"raw": namer.NewRawNamer("", nil),
|
||||||
|
"publicPlural": publicPluralNamer,
|
||||||
|
"allLowercasePlural": namer.NewAllLowercasePluralNamer(pluralExceptions),
|
||||||
|
"lowercaseSingular": &lowercaseSingularNamer{},
|
||||||
|
"apiGroup": newTagOverrideNamer("publicPlural", publicPluralNamer),
|
||||||
|
"versionedClientset": &versionedClientsetNamer{public: publicNamer},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultNameSystem returns the default name system for ordering the types to be
|
||||||
|
// processed by the generators in this package.
|
||||||
|
func DefaultNameSystem() string {
|
||||||
|
return "public"
|
||||||
|
}
|
|
@ -1,11 +1,11 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2020 The Knative Authors.
|
Copyright 2020 The Knative Authors
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
You may obtain a copy of the License at
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
Unless required by applicable law or agreed to in writing, software
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
@ -13,7 +13,8 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
package generators
|
|
||||||
|
package tags
|
||||||
|
|
||||||
import "strings"
|
import "strings"
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 The Knative Authors
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package tags
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"k8s.io/code-generator/cmd/client-gen/generators/util"
|
||||||
|
"k8s.io/gengo/v2/types"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
|
"knative.dev/pkg/codegen/cmd/injection-gen/args"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Tags represents a genclient configuration for a single type.
|
||||||
|
type Tags struct {
|
||||||
|
util.Tags
|
||||||
|
|
||||||
|
GenerateDuck bool
|
||||||
|
GenerateReconciler bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t Tags) NeedsInformerInjection() bool {
|
||||||
|
return t.GenerateClient && !t.NoVerbs && t.HasVerb("list") && t.HasVerb("watch")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t Tags) NeedsDuckInjection() bool {
|
||||||
|
return t.GenerateDuck
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t Tags) NeedsReconciler(kind *types.Type, args *args.Args) bool {
|
||||||
|
// Overrides
|
||||||
|
kinds := strings.Split(args.ForceKinds, ",")
|
||||||
|
for _, k := range kinds {
|
||||||
|
if kind.Name.Name == k {
|
||||||
|
klog.V(5).Infof("Kind %s was forced to generate reconciler.", k)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Normal
|
||||||
|
return t.GenerateReconciler
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustParseClientGenTags calls ParseClientGenTags but instead of returning error it panics.
|
||||||
|
func MustParseClientGenTags(lines []string) Tags {
|
||||||
|
ret := Tags{
|
||||||
|
Tags: util.MustParseClientGenTags(lines),
|
||||||
|
}
|
||||||
|
|
||||||
|
values := ExtractCommentTags("+", lines)
|
||||||
|
|
||||||
|
_, ret.GenerateDuck = values["genduck"]
|
||||||
|
|
||||||
|
_, ret.GenerateReconciler = values["genreconciler"]
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
|
@ -82,11 +82,14 @@ if grep -qw "injection" <<<"${GENS}"; then
|
||||||
# Clear old injection
|
# Clear old injection
|
||||||
rm -rf ${OUTPUT_PKG}
|
rm -rf ${OUTPUT_PKG}
|
||||||
|
|
||||||
|
MODULE_NAME=$(go list -m)
|
||||||
|
|
||||||
go run knative.dev/pkg/codegen/cmd/injection-gen \
|
go run knative.dev/pkg/codegen/cmd/injection-gen \
|
||||||
--input-dirs $(codegen::join , "${FQ_APIS[@]}") \
|
--input-dirs $(codegen::join , "${FQ_APIS[@]}") \
|
||||||
--versioned-clientset-package ${VERSIONED_CLIENTSET_PKG} \
|
--versioned-clientset-package ${VERSIONED_CLIENTSET_PKG} \
|
||||||
--external-versions-informers-package ${EXTERNAL_INFORMER_PKG} \
|
--external-versions-informers-package ${EXTERNAL_INFORMER_PKG} \
|
||||||
--listers-package ${LISTERS_PKG} \
|
--listers-package ${LISTERS_PKG} \
|
||||||
--output-package ${OUTPUT_PKG} \
|
--output-package ${OUTPUT_PKG} \
|
||||||
|
--output-dir ${OUTPUT_PKG//${MODULE_NAME}\//} \
|
||||||
"$@"
|
"$@"
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -22,7 +22,7 @@ source $(dirname $0)/../vendor/knative.dev/hack/codegen-library.sh
|
||||||
|
|
||||||
echo "=== Update Codegen for $MODULE_NAME"
|
echo "=== Update Codegen for $MODULE_NAME"
|
||||||
|
|
||||||
group "Kubernetes Codegen"
|
group "Knative Codegen"
|
||||||
|
|
||||||
# Knative Injection
|
# Knative Injection
|
||||||
${REPO_ROOT_DIR}/hack/generate-knative.sh "injection" \
|
${REPO_ROOT_DIR}/hack/generate-knative.sh "injection" \
|
||||||
|
@ -35,7 +35,6 @@ ${REPO_ROOT_DIR}/hack/generate-knative.sh "injection" \
|
||||||
K8S_TYPES=$(find ./vendor/k8s.io/api -type d -path '*/*/*/*/*/*' | cut -d'/' -f 5-6 | sort | sed 's@/@:@g' |
|
K8S_TYPES=$(find ./vendor/k8s.io/api -type d -path '*/*/*/*/*/*' | cut -d'/' -f 5-6 | sort | sed 's@/@:@g' |
|
||||||
grep -v "abac:" | \
|
grep -v "abac:" | \
|
||||||
grep -v "admission:" | \
|
grep -v "admission:" | \
|
||||||
grep -v "admissionregistration:" | \
|
|
||||||
grep -v "componentconfig:" | \
|
grep -v "componentconfig:" | \
|
||||||
grep -v "imagepolicy:" | \
|
grep -v "imagepolicy:" | \
|
||||||
grep -v "resource:" | \
|
grep -v "resource:" | \
|
||||||
|
@ -61,7 +60,8 @@ VERSIONED_CLIENTSET_PKG="k8s.io/apiextensions-apiserver/pkg/client/clientset/cli
|
||||||
--go-header-file ${REPO_ROOT_DIR}/hack/boilerplate/boilerplate.go.txt \
|
--go-header-file ${REPO_ROOT_DIR}/hack/boilerplate/boilerplate.go.txt \
|
||||||
--force-genreconciler-kinds "CustomResourceDefinition"
|
--force-genreconciler-kinds "CustomResourceDefinition"
|
||||||
|
|
||||||
group "Knative Codegen"
|
|
||||||
|
group "Kubernetes Codegen"
|
||||||
|
|
||||||
# Only deepcopy the Duck types, as they are not real resources.
|
# Only deepcopy the Duck types, as they are not real resources.
|
||||||
go run k8s.io/code-generator/cmd/deepcopy-gen \
|
go run k8s.io/code-generator/cmd/deepcopy-gen \
|
||||||
|
|
|
@ -206,7 +206,7 @@ golang.org/x/net/trace
|
||||||
## explicit; go 1.18
|
## explicit; go 1.18
|
||||||
golang.org/x/oauth2
|
golang.org/x/oauth2
|
||||||
golang.org/x/oauth2/internal
|
golang.org/x/oauth2/internal
|
||||||
# golang.org/x/sync v0.10.0
|
# golang.org/x/sync v0.11.0
|
||||||
## explicit; go 1.18
|
## explicit; go 1.18
|
||||||
golang.org/x/sync/errgroup
|
golang.org/x/sync/errgroup
|
||||||
golang.org/x/sync/semaphore
|
golang.org/x/sync/semaphore
|
||||||
|
@ -329,7 +329,7 @@ google.golang.org/grpc/serviceconfig
|
||||||
google.golang.org/grpc/stats
|
google.golang.org/grpc/stats
|
||||||
google.golang.org/grpc/status
|
google.golang.org/grpc/status
|
||||||
google.golang.org/grpc/tap
|
google.golang.org/grpc/tap
|
||||||
# google.golang.org/protobuf v1.36.4
|
# google.golang.org/protobuf v1.36.5
|
||||||
## explicit; go 1.21
|
## explicit; go 1.21
|
||||||
google.golang.org/protobuf/encoding/protodelim
|
google.golang.org/protobuf/encoding/protodelim
|
||||||
google.golang.org/protobuf/encoding/protojson
|
google.golang.org/protobuf/encoding/protojson
|
||||||
|
@ -797,13 +797,6 @@ k8s.io/code-generator/cmd/register-gen/generators
|
||||||
k8s.io/code-generator/pkg/namer
|
k8s.io/code-generator/pkg/namer
|
||||||
k8s.io/code-generator/pkg/util
|
k8s.io/code-generator/pkg/util
|
||||||
k8s.io/code-generator/third_party/forked/golang/reflect
|
k8s.io/code-generator/third_party/forked/golang/reflect
|
||||||
# k8s.io/gengo v0.0.0-20240404160639-a0386bf69313
|
|
||||||
## explicit; go 1.13
|
|
||||||
k8s.io/gengo/args
|
|
||||||
k8s.io/gengo/generator
|
|
||||||
k8s.io/gengo/namer
|
|
||||||
k8s.io/gengo/parser
|
|
||||||
k8s.io/gengo/types
|
|
||||||
# k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70
|
# k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70
|
||||||
## explicit; go 1.20
|
## explicit; go 1.20
|
||||||
k8s.io/gengo/v2
|
k8s.io/gengo/v2
|
||||||
|
@ -850,7 +843,7 @@ k8s.io/utils/trace
|
||||||
# knative.dev/hack v0.0.0-20250128013659-5f7f0f50e9de
|
# knative.dev/hack v0.0.0-20250128013659-5f7f0f50e9de
|
||||||
## explicit; go 1.21
|
## explicit; go 1.21
|
||||||
knative.dev/hack
|
knative.dev/hack
|
||||||
# knative.dev/pkg v0.0.0-20250203163623-f62a97fc6ad4
|
# knative.dev/pkg v0.0.0-20250211185550-c8bea7c326ff
|
||||||
## explicit; go 1.22.7
|
## explicit; go 1.22.7
|
||||||
knative.dev/pkg/apis
|
knative.dev/pkg/apis
|
||||||
knative.dev/pkg/apis/duck
|
knative.dev/pkg/apis/duck
|
||||||
|
@ -862,6 +855,13 @@ knative.dev/pkg/client/injection/kube/client
|
||||||
knative.dev/pkg/codegen/cmd/injection-gen
|
knative.dev/pkg/codegen/cmd/injection-gen
|
||||||
knative.dev/pkg/codegen/cmd/injection-gen/args
|
knative.dev/pkg/codegen/cmd/injection-gen/args
|
||||||
knative.dev/pkg/codegen/cmd/injection-gen/generators
|
knative.dev/pkg/codegen/cmd/injection-gen/generators
|
||||||
|
knative.dev/pkg/codegen/cmd/injection-gen/generators/client
|
||||||
|
knative.dev/pkg/codegen/cmd/injection-gen/generators/duck
|
||||||
|
knative.dev/pkg/codegen/cmd/injection-gen/generators/factory
|
||||||
|
knative.dev/pkg/codegen/cmd/injection-gen/generators/informers
|
||||||
|
knative.dev/pkg/codegen/cmd/injection-gen/generators/reconciler
|
||||||
|
knative.dev/pkg/codegen/cmd/injection-gen/namer
|
||||||
|
knative.dev/pkg/codegen/cmd/injection-gen/tags
|
||||||
knative.dev/pkg/configmap
|
knative.dev/pkg/configmap
|
||||||
knative.dev/pkg/controller
|
knative.dev/pkg/controller
|
||||||
knative.dev/pkg/environment
|
knative.dev/pkg/environment
|
||||||
|
|
Loading…
Reference in New Issue