Update vendored deps, including AWS SDK, openpgp, ftp, ...

This commit is contained in:
Andrey Smirnov
2018-04-05 17:46:45 +03:00
parent cef4fefc40
commit 0e6ee35942
1497 changed files with 450721 additions and 68034 deletions
+107 -19
View File
@@ -10,10 +10,10 @@ import (
"io/ioutil"
"path"
"path/filepath"
"regexp"
"sort"
"strings"
"text/template"
"unicode"
)
// An API defines a service API's definition. and logic to serialize the definition.
@@ -94,23 +94,53 @@ func (a *API) InterfacePackageName() string {
return a.PackageName() + "iface"
}
var nameRegex = regexp.MustCompile(`^Amazon|AWS\s*|\(.*|\s+|\W+`)
var stripServiceNamePrefixes = []string{
"Amazon",
"AWS",
}
// StructName returns the struct name for a given API.
func (a *API) StructName() string {
if a.name == "" {
name := a.Metadata.ServiceAbbreviation
if name == "" {
name = a.Metadata.ServiceFullName
}
if len(a.name) != 0 {
return a.name
}
name = nameRegex.ReplaceAllString(name, "")
name := a.Metadata.ServiceAbbreviation
if len(name) == 0 {
name = a.Metadata.ServiceFullName
}
a.name = name
if name, ok := serviceAliases[strings.ToLower(name)]; ok {
a.name = name
name = strings.TrimSpace(name)
// Strip out prefix names not reflected in service client symbol names.
for _, prefix := range stripServiceNamePrefixes {
if strings.HasPrefix(name, prefix) {
name = name[len(prefix):]
break
}
}
// Replace all Non-letter/number values with space
runes := []rune(name)
for i := 0; i < len(runes); i++ {
if r := runes[i]; !(unicode.IsNumber(r) || unicode.IsLetter(r)) {
runes[i] = ' '
}
}
name = string(runes)
// Title case name so its readable as a symbol.
name = strings.Title(name)
// Strip out spaces.
name = strings.Replace(name, " ", "", -1)
// Swap out for alias name if one is defined.
if alias, ok := serviceAliases[strings.ToLower(name)]; ok {
name = alias
}
a.name = name
return a.name
}
@@ -307,6 +337,12 @@ var noCrossLinkServices = map[string]struct{}{
"swf": {},
}
// HasCrosslinks will return whether or not a service has crosslinking .
func HasCrosslinks(service string) bool {
_, ok := noCrossLinkServices[service]
return !ok
}
// GetCrosslinkURL returns the crosslinking URL for the shape based on the name and
// uid provided. Empty string is returned if no crosslink link could be determined.
func GetCrosslinkURL(baseURL, uid string, params ...string) string {
@@ -314,14 +350,16 @@ func GetCrosslinkURL(baseURL, uid string, params ...string) string {
return ""
}
if _, ok := noCrossLinkServices[strings.ToLower(serviceIDFromUID(uid))]; ok {
if !HasCrosslinks(strings.ToLower(ServiceIDFromUID(uid))) {
return ""
}
return strings.Join(append([]string{baseURL, "goto", "WebAPI", uid}, params...), "/")
}
func serviceIDFromUID(uid string) string {
// ServiceIDFromUID will parse the service id from the uid and return
// the service id that was found.
func ServiceIDFromUID(uid string) string {
found := 0
i := len(uid) - 1
for ; i >= 0; i-- {
@@ -363,7 +401,7 @@ var tplServiceDoc = template.Must(template.New("service docs").Funcs(template.Fu
//
// Using the Client
//
// To {{ .Metadata.ServiceFullName }} with the SDK use the New function to create
// To contact {{ .Metadata.ServiceFullName }} with the SDK use the New function to create
// a new service client. With that client you can make API requests to the service.
// These clients are safe to use concurrently.
//
@@ -450,16 +488,17 @@ func New(p client.ConfigProvider, cfgs ...*aws.Config) *{{ .StructName }} {
{{- else -}}
c := p.ClientConfig({{ EndpointsIDValue . }}, cfgs...)
{{- end }}
{{- if .Metadata.SigningName }}
if c.SigningNameDerived || len(c.SigningName) == 0{
c.SigningName = "{{ .Metadata.SigningName }}"
}
{{- end }}
return newClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName)
}
// newClient creates, initializes and returns a new service client instance.
func newClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *{{ .StructName }} {
{{- if .Metadata.SigningName }}
if len(signingName) == 0 {
signingName = "{{ .Metadata.SigningName }}"
}
{{- end }}
svc := &{{ .StructName }}{
Client: client.New(
cfg,
@@ -763,3 +802,52 @@ func (a *API) APIErrorsGoCode() string {
return strings.TrimSpace(buf.String())
}
// removeOperation removes an operation, its input/output shapes, as well as
// any references/shapes that are unique to this operation.
func (a *API) removeOperation(name string) {
fmt.Println("removing operation,", name)
op := a.Operations[name]
delete(a.Operations, name)
delete(a.Examples, name)
a.removeShape(op.InputRef.Shape)
a.removeShape(op.OutputRef.Shape)
}
// removeShape removes the given shape, and all form member's reference target
// shapes. Will also remove member reference targeted shapes if those shapes do
// not have any additional references.
func (a *API) removeShape(s *Shape) {
fmt.Println("removing shape,", s.ShapeName)
delete(a.Shapes, s.ShapeName)
for name, ref := range s.MemberRefs {
a.removeShapeRef(ref)
delete(s.MemberRefs, name)
}
for _, ref := range []*ShapeRef{&s.MemberRef, &s.KeyRef, &s.ValueRef} {
if ref.Shape == nil {
continue
}
a.removeShapeRef(ref)
*ref = ShapeRef{}
}
}
// removeShapeRef removes the shape reference from its target shape. If the
// reference was the last reference to the target shape, the shape will also be
// removed.
func (a *API) removeShapeRef(ref *ShapeRef) {
if ref.Shape == nil {
return
}
ref.Shape.removeRef(ref)
if len(ref.Shape.refs) == 0 {
a.removeShape(ref.Shape)
}
}
+60 -43
View File
@@ -1,4 +1,4 @@
// +build 1.6,codegen
// +build go1.8,codegen
package api
@@ -6,49 +6,66 @@ import (
"testing"
)
func TestStructNameWithFullName(t *testing.T) {
a := API{
Metadata: Metadata{
ServiceFullName: "Amazon Service Name-100",
func TestAPI_StructName(t *testing.T) {
origAliases := serviceAliases
defer func() { serviceAliases = origAliases }()
cases := map[string]struct {
Aliases map[string]string
Metadata Metadata
StructName string
}{
"FullName": {
Metadata: Metadata{
ServiceFullName: "Amazon Service Name-100",
},
StructName: "ServiceName100",
},
"Abbreviation": {
Metadata: Metadata{
ServiceFullName: "Amazon Service Name-100",
ServiceAbbreviation: "AWS SN100",
},
StructName: "SN100",
},
"Lowercase Name": {
Metadata: Metadata{
EndpointPrefix: "other",
ServiceFullName: "AWS Lowercase service",
ServiceAbbreviation: "lowercase",
},
StructName: "Lowercase",
},
"Lowercase Name Mixed": {
Metadata: Metadata{
EndpointPrefix: "other",
ServiceFullName: "AWS Lowercase service",
ServiceAbbreviation: "lowercase name Goes heRe",
},
StructName: "LowercaseNameGoesHeRe",
},
"Alias": {
Aliases: map[string]string{
"elasticloadbalancing": "ELB",
},
Metadata: Metadata{
ServiceFullName: "Elastic Load Balancing",
},
StructName: "ELB",
},
}
if a.StructName() != "ServiceName100" {
t.Errorf("API struct name should have been %s, but received %s", "ServiceName100", a.StructName())
}
}
func TestStructNameWithAbbreviation(t *testing.T) {
a := API{
Metadata: Metadata{
ServiceFullName: "AWS Service Name-100",
ServiceAbbreviation: "AWS SN100",
},
}
if a.StructName() != "SN100" {
t.Errorf("API struct name should have been %s, but received %s", "SN100", a.StructName())
}
}
func TestStructNameForExceptions(t *testing.T) {
serviceAliases = map[string]string{}
serviceAliases["elasticloadbalancing"] = "ELB"
serviceAliases["config"] = "ConfigService"
a := API{
Metadata: Metadata{
ServiceFullName: "Elastic Load Balancing",
},
}
if a.StructName() != "ELB" {
t.Errorf("API struct name should have been %s, but received %s", "ELB", a.StructName())
}
a = API{
Metadata: Metadata{
ServiceFullName: "AWS Config",
},
}
if a.StructName() != "ConfigService" {
t.Errorf("API struct name should have been %s, but received %s", "ConfigService", a.StructName())
for k, c := range cases {
t.Run(k, func(t *testing.T) {
serviceAliases = c.Aliases
a := API{
Metadata: c.Metadata,
}
if e, o := c.StructName, a.StructName(); e != o {
t.Errorf("expect %v structName, got %v", e, o)
}
})
}
}
+11 -3
View File
@@ -53,12 +53,20 @@ func (a *API) customizationPasses() {
func s3Customizations(a *API) {
var strExpires *Shape
var keepContentMD5Ref = map[string]struct{}{
"PutObjectInput": struct{}{},
"UploadPartInput": struct{}{},
}
for name, s := range a.Shapes {
// Remove ContentMD5 members
if _, ok := s.MemberRefs["ContentMD5"]; ok {
delete(s.MemberRefs, "ContentMD5")
// Remove ContentMD5 members unless specified otherwise.
if _, keep := keepContentMD5Ref[name]; !keep {
if _, have := s.MemberRefs["ContentMD5"]; have {
delete(s.MemberRefs, "ContentMD5")
}
}
// Generate getter methods for API operation fields used by customizations.
for _, refName := range []string{"Bucket", "SSECustomerKey", "CopySourceSSECustomerKey"} {
if ref, ok := s.MemberRefs[refName]; ok {
ref.GenerateGetter = true
+28
View File
@@ -0,0 +1,28 @@
// +build codegen
package api
func (a *API) suppressEventStreams() {
const eventStreamMemberName = "EventStream"
for name, op := range a.Operations {
outbound := hasEventStream(op.InputRef.Shape)
inbound := hasEventStream(op.OutputRef.Shape)
if !(outbound || inbound) {
continue
}
a.removeOperation(name)
}
}
func hasEventStream(topShape *Shape) bool {
for _, ref := range topShape.MemberRefs {
if ref.Shape.IsEventStream {
return true
}
}
return false
}
+79
View File
@@ -0,0 +1,79 @@
// +build go1.6,codegen
package api
import (
"testing"
)
func TestSuppressEventStream(t *testing.T) {
cases := []struct {
API *API
Ops []string
Shapes []string
}{
{
API: &API{
Operations: map[string]*Operation{
"abc": {
InputRef: ShapeRef{
ShapeName: "abcRequest",
},
OutputRef: ShapeRef{
ShapeName: "abcResponse",
},
},
"eventStreamOp": {
InputRef: ShapeRef{
ShapeName: "eventStreamOpRequest",
},
OutputRef: ShapeRef{
ShapeName: "eventStreamOpResponse",
},
},
},
Shapes: map[string]*Shape{
"abcRequest": {},
"abcResponse": {},
"eventStreamOpRequest": {},
"eventStreamOpResponse": {
MemberRefs: map[string]*ShapeRef{
"eventStreamShape": {
ShapeName: "eventStreamShape",
},
},
},
"eventStreamShape": {
IsEventStream: true,
},
},
},
Ops: []string{"Abc"},
Shapes: []string{"AbcInput", "AbcOutput"},
},
}
for _, c := range cases {
c.API.Setup()
if e, a := c.Ops, c.API.OperationNames(); !stringsEqual(e, a) {
t.Errorf("expect %v ops, got %v", e, a)
}
if e, a := c.Shapes, c.API.ShapeNames(); !stringsEqual(e, a) {
t.Errorf("expect %v ops, got %v", e, a)
}
}
}
func stringsEqual(a, b []string) bool {
if len(a) != len(b) {
return false
}
for i := 0; i < len(a); i++ {
if a[i] != b[i] {
return false
}
}
return true
}
+121 -5
View File
@@ -32,11 +32,84 @@ func buildAPI() *API {
Shape: intShape,
}
nestedComplexShape := &Shape{
API: a,
ShapeName: "NestedComplexShape",
MemberRefs: map[string]*ShapeRef{
"NestedField": stringShapeRef,
},
Type: "structure",
}
nestedComplexShapeRef := &ShapeRef{
API: a,
ShapeName: "NestedComplexShape",
Shape: nestedComplexShape,
}
nestedListShape := &Shape{
API: a,
ShapeName: "NestedListShape",
MemberRef: *nestedComplexShapeRef,
Type: "list",
}
nestedListShapeRef := &ShapeRef{
API: a,
ShapeName: "NestedListShape",
Shape: nestedListShape,
}
complexShape := &Shape{
API: a,
ShapeName: "ComplexShape",
MemberRefs: map[string]*ShapeRef{
"Field": stringShapeRef,
"List": nestedListShapeRef,
},
Type: "structure",
}
complexShapeRef := &ShapeRef{
API: a,
ShapeName: "ComplexShape",
Shape: complexShape,
}
listShape := &Shape{
API: a,
ShapeName: "ListShape",
MemberRef: *complexShapeRef,
Type: "list",
}
listShapeRef := &ShapeRef{
API: a,
ShapeName: "ListShape",
Shape: listShape,
}
listsShape := &Shape{
API: a,
ShapeName: "ListsShape",
MemberRef: *listShapeRef,
Type: "list",
}
listsShapeRef := &ShapeRef{
API: a,
ShapeName: "ListsShape",
Shape: listsShape,
}
input := &Shape{
API: a,
ShapeName: "FooInput",
MemberRefs: map[string]*ShapeRef{
"BarShape": stringShapeRef,
"BarShape": stringShapeRef,
"ComplexField": complexShapeRef,
"ListField": listShapeRef,
"ListsField": listsShapeRef,
},
Type: "structure",
}
@@ -44,7 +117,10 @@ func buildAPI() *API {
API: a,
ShapeName: "FooOutput",
MemberRefs: map[string]*ShapeRef{
"BazShape": intShapeRef,
"BazShape": intShapeRef,
"ComplexField": complexShapeRef,
"ListField": listShapeRef,
"ListsField": listsShapeRef,
},
Type: "structure",
}
@@ -91,7 +167,27 @@ func TestExampleGeneration(t *testing.T) {
"Foo": [
{
"input": {
"BarShape": "Hello world"
"BarShape": "Hello world",
"ComplexField": {
"Field": "bar",
"List": [
{
"NestedField": "qux"
}
]
},
"ListField": [
{
"Field": "baz"
}
],
"ListsField": [
[
{
"Field": "baz"
}
]
]
},
"output": {
"BazShape": 1
@@ -121,7 +217,7 @@ func TestExampleGeneration(t *testing.T) {
expected := `
import (
"fmt"
"bytes"
"strings"
"time"
"github.com/aws/aws-sdk-go/aws"
@@ -131,7 +227,7 @@ import (
)
var _ time.Duration
var _ bytes.Buffer
var _ strings.Reader
var _ aws.Config
func parseTime(layout, value string) *time.Time {
@@ -149,6 +245,26 @@ func ExampleFooService_Foo_shared00() {
svc := fooservice.New(session.New())
input := &fooservice.FooInput{
BarShape: aws.String("Hello world"),
ComplexField: &fooservice.ComplexShape{
Field: aws.String("bar"),
List: []*fooservice.NestedComplexShape{
{
NestedField: aws.String("qux"),
},
},
},
ListField: []*fooservice.ComplexShape{
{
Field: aws.String("baz"),
},
},
ListsField: [][]*fooservice.ComplexShape{
{
{
Field: aws.String("baz"),
},
},
},
}
result, err := svc.Foo(input)
+54 -88
View File
@@ -44,17 +44,20 @@ func (builder defaultExamplesBuilder) BuildShape(ref *ShapeRef, shapes map[strin
}
memName := name
passRef := ref.Shape.MemberRefs[name]
if isMap {
memName = fmt.Sprintf("%q", memName)
passRef = &ref.Shape.ValueRef
}
switch v := shape.(type) {
case map[string]interface{}:
ret += builder.BuildComplex(name, memName, ref, v)
ret += builder.BuildComplex(name, memName, passRef, v)
case []interface{}:
ret += builder.BuildList(name, memName, ref, v)
ret += builder.BuildList(name, memName, passRef, v)
default:
ret += builder.BuildScalar(name, memName, ref, v)
ret += builder.BuildScalar(name, memName, passRef, v, ref.Shape.Payload == name)
}
}
return ret
@@ -69,105 +72,86 @@ func (builder defaultExamplesBuilder) BuildList(name, memName string, ref *Shape
return ""
}
t := ""
dataType := ""
format := ""
isComplex := false
passRef := ref
isMap := false
passRef := &ref.Shape.MemberRef
ret += fmt.Sprintf("%s: %s {\n", memName, builder.GoType(ref, false))
ret += builder.buildListElements(passRef, v)
ret += "},\n"
return ret
}
if ref.Shape.MemberRefs[name] != nil {
t = builder.GoType(&ref.Shape.MemberRefs[name].Shape.MemberRef, false)
dataType = ref.Shape.MemberRefs[name].Shape.MemberRef.Shape.Type
passRef = ref.Shape.MemberRefs[name]
if dataType == "map" {
t = fmt.Sprintf("map[string]%s", builder.GoType(&ref.Shape.MemberRefs[name].Shape.MemberRef.Shape.ValueRef, false))
passRef = &ref.Shape.MemberRefs[name].Shape.MemberRef.Shape.ValueRef
isMap = true
}
} else if ref.Shape.MemberRef.Shape != nil && ref.Shape.MemberRef.Shape.MemberRefs[name] != nil {
t = builder.GoType(&ref.Shape.MemberRef.Shape.MemberRefs[name].Shape.MemberRef, false)
dataType = ref.Shape.MemberRef.Shape.MemberRefs[name].Shape.MemberRef.Shape.Type
passRef = &ref.Shape.MemberRef.Shape.MemberRefs[name].Shape.MemberRef
} else {
t = builder.GoType(&ref.Shape.MemberRef, false)
dataType = ref.Shape.MemberRef.Shape.Type
passRef = &ref.Shape.MemberRef
func (builder defaultExamplesBuilder) buildListElements(ref *ShapeRef, v []interface{}) string {
if len(v) == 0 || ref == nil {
return ""
}
ret := ""
format := ""
isComplex := false
isList := false
// get format for atomic type. If it is not an atomic type,
// get the element.
switch v[0].(type) {
case string:
format = "%s"
case bool:
format = "%t"
case float64:
if dataType == "integer" || dataType == "int64" {
switch ref.Shape.Type {
case "integer", "int64", "long":
format = "%d"
} else {
default:
format = "%f"
}
default:
if ref.Shape.MemberRefs[name] != nil {
} else {
passRef = ref.Shape.MemberRef.Shape.MemberRefs[name]
// if passRef is nil that means we are either in a map or within a nested array
if passRef == nil {
passRef = &ref.Shape.MemberRef
}
}
case []interface{}:
isList = true
case map[string]interface{}:
isComplex = true
}
ret += fmt.Sprintf("%s: []%s {\n", memName, t)
for _, elem := range v {
if isComplex {
ret += fmt.Sprintf("{\n%s\n},\n", builder.BuildShape(passRef, elem.(map[string]interface{}), isMap))
ret += fmt.Sprintf("{\n%s\n},\n", builder.BuildShape(ref, elem.(map[string]interface{}), ref.Shape.Type == "map"))
} else if isList {
ret += fmt.Sprintf("{\n%s\n},\n", builder.buildListElements(&ref.Shape.MemberRef, elem.([]interface{})))
} else {
if dataType == "integer" || dataType == "int64" || dataType == "long" {
switch ref.Shape.Type {
case "integer", "int64", "long":
elem = int(elem.(float64))
}
ret += fmt.Sprintf("%s,\n", getValue(t, fmt.Sprintf(format, elem)))
ret += fmt.Sprintf("%s,\n", getValue(ref.Shape.Type, fmt.Sprintf(format, elem)))
}
}
ret += "},\n"
return ret
}
// BuildScalar will build atomic Go types.
func (builder defaultExamplesBuilder) BuildScalar(name, memName string, ref *ShapeRef, shape interface{}) string {
func (builder defaultExamplesBuilder) BuildScalar(name, memName string, ref *ShapeRef, shape interface{}, isPayload bool) string {
if ref == nil || ref.Shape == nil {
return ""
} else if ref.Shape.MemberRefs[name] == nil {
if ref.Shape.MemberRef.Shape != nil && ref.Shape.MemberRef.Shape.MemberRefs[name] != nil {
return correctType(memName, ref.Shape.MemberRef.Shape.MemberRefs[name].Shape.Type, shape)
}
if ref.Shape.Type != "structure" && ref.Shape.Type != "map" {
return correctType(memName, ref.Shape.Type, shape)
}
return ""
}
switch v := shape.(type) {
case bool:
return convertToCorrectType(memName, ref.Shape.MemberRefs[name].Shape.Type, fmt.Sprintf("%t", v))
return convertToCorrectType(memName, ref.Shape.Type, fmt.Sprintf("%t", v))
case int:
if ref.Shape.MemberRefs[name].Shape.Type == "timestamp" {
if ref.Shape.Type == "timestamp" {
return parseTimeString(ref, memName, fmt.Sprintf("%d", v))
}
return convertToCorrectType(memName, ref.Shape.MemberRefs[name].Shape.Type, fmt.Sprintf("%d", v))
return convertToCorrectType(memName, ref.Shape.Type, fmt.Sprintf("%d", v))
case float64:
dataType := ref.Shape.MemberRefs[name].Shape.Type
dataType := ref.Shape.Type
if dataType == "integer" || dataType == "int64" || dataType == "long" {
return convertToCorrectType(memName, ref.Shape.MemberRefs[name].Shape.Type, fmt.Sprintf("%d", int(shape.(float64))))
return convertToCorrectType(memName, ref.Shape.Type, fmt.Sprintf("%d", int(shape.(float64))))
}
return convertToCorrectType(memName, ref.Shape.MemberRefs[name].Shape.Type, fmt.Sprintf("%f", v))
return convertToCorrectType(memName, ref.Shape.Type, fmt.Sprintf("%f", v))
case string:
t := ref.Shape.MemberRefs[name].Shape.Type
t := ref.Shape.Type
switch t {
case "timestamp":
return parseTimeString(ref, memName, fmt.Sprintf("%s", v))
case "blob":
if (ref.Shape.MemberRefs[name].Streaming || ref.Shape.MemberRefs[name].Shape.Streaming) && ref.Shape.Payload == name {
if (ref.Streaming || ref.Shape.Streaming) && isPayload {
return fmt.Sprintf("%s: aws.ReadSeekCloser(strings.NewReader(%q)),\n", memName, v)
}
@@ -182,47 +166,33 @@ func (builder defaultExamplesBuilder) BuildScalar(name, memName string, ref *Sha
}
func (builder defaultExamplesBuilder) BuildComplex(name, memName string, ref *ShapeRef, v map[string]interface{}) string {
t := ""
if ref == nil {
return builder.BuildShape(nil, v, true)
}
member := ref.Shape.MemberRefs[name]
if member != nil && member.Shape != nil {
t = ref.Shape.MemberRefs[name].Shape.Type
} else {
t = ref.Shape.Type
}
switch t {
switch ref.Shape.Type {
case "structure":
passRef := ref.Shape.MemberRefs[name]
// passRef will be nil if the entry is a map. In that case
// we want to pass the reference, because the previous call
// passed the value reference.
if passRef == nil {
passRef = ref
}
return fmt.Sprintf(`%s: &%s{
%s
},
`, memName, builder.GoType(passRef, true), builder.BuildShape(passRef, v, false))
`, memName, builder.GoType(ref, true), builder.BuildShape(ref, v, false))
case "map":
return fmt.Sprintf(`%s: %s{
%s
},
`, name, builder.GoType(ref.Shape.MemberRefs[name], false), builder.BuildShape(&ref.Shape.MemberRefs[name].Shape.ValueRef, v, true))
`, name, builder.GoType(ref, false), builder.BuildShape(ref, v, true))
default:
panic(fmt.Sprintf("Expected complex type but recieved %q", ref.Shape.Type))
}
return ""
}
func (builder defaultExamplesBuilder) GoType(ref *ShapeRef, elem bool) string {
if ref.Shape.Type != "structure" && ref.Shape.Type != "list" && ref.Shape.Type != "map" {
return ref.GoTypeWithPkgName()
}
prefix := ""
if ref.Shape.Type == "list" {
ref = &ref.Shape.MemberRef
prefix = "[]*"
prefix = "[]"
}
name := ref.GoTypeWithPkgName()
@@ -233,10 +203,6 @@ func (builder defaultExamplesBuilder) GoType(ref *ShapeRef, elem bool) string {
}
}
if ref.Shape.Type != "structure" && ref.Shape.Type != "list" {
return name
}
return prefix + name
}
+3 -15
View File
@@ -9,21 +9,6 @@ import (
"path/filepath"
)
// Load takes a set of files for each filetype and returns an API pointer.
// The API will be initialized once all files have been loaded and parsed.
//
// Will panic if any failure opening the definition JSON files, or there
// are unrecognized exported names.
func Load(api, docs, paginators, waiters string) *API {
a := API{}
a.Attach(api)
a.Attach(docs)
a.Attach(paginators)
a.Attach(waiters)
a.Setup()
return &a
}
// Attach opens a file by name, and unmarshal its JSON data.
// Will proceed to setup the API if not already done so.
func (a *API) Attach(filename string) {
@@ -58,8 +43,11 @@ func (a *API) Setup() {
if !a.NoRenameToplevelShapes {
a.renameToplevelShapes()
}
a.renameCollidingFields()
a.updateTopLevelShapeReferences()
a.createInputOutputShapes()
a.suppressEventStreams()
a.customizationPasses()
if !a.NoRemoveUnusedShapes {
+3 -3
View File
@@ -72,7 +72,7 @@ const op{{ .ExportedName }} = "{{ .Name }}"
// {{ .ExportedName }}Request generates a "aws/request.Request" representing the
// client's request for the {{ .ExportedName }} operation. The "output" return
// value will be populated with the request's response once the request complets
// value will be populated with the request's response once the request completes
// successfuly.
//
// Use "Send" method on the returned Request to send the API call to the service.
@@ -95,7 +95,7 @@ const op{{ .ExportedName }} = "{{ .Name }}"
{{ $crosslinkURL := GetCrosslinkURL $.API.BaseCrosslinkURL $.API.Metadata.UID $.ExportedName -}}
{{ if ne $crosslinkURL "" -}}
//
// Please also see {{ $crosslinkURL }}
// See also, {{ $crosslinkURL }}
{{ end -}}
func (c *{{ .API.StructName }}) {{ .ExportedName }}Request(` +
`input {{ .InputRef.GoType }}) (req *request.Request, output {{ .OutputRef.GoType }}) {
@@ -152,7 +152,7 @@ func (c *{{ .API.StructName }}) {{ .ExportedName }}Request(` +
{{ end -}}
{{ $crosslinkURL := GetCrosslinkURL $.API.BaseCrosslinkURL $.API.Metadata.UID $.ExportedName -}}
{{ if ne $crosslinkURL "" -}}
// Please also see {{ $crosslinkURL }}
// See also, {{ $crosslinkURL }}
{{ end -}}
func (c *{{ .API.StructName }}) {{ .ExportedName }}(` +
`input {{ .InputRef.GoType }}) ({{ .OutputRef.GoType }}, error) {
+14
View File
@@ -4,6 +4,7 @@ package api
import (
"fmt"
"encoding/json"
"reflect"
"strings"
@@ -79,6 +80,19 @@ func (f paramFiller) paramsStructAny(value interface{}, shape *Shape) string {
if v.IsValid() {
return fmt.Sprintf("aws.Time(time.Unix(%d, 0))", int(v.Float()))
}
case "jsonvalue":
v, err := json.Marshal(value)
if err != nil {
panic("failed to marshal JSONValue, "+err.Error())
}
const tmpl = `func() aws.JSONValue {
var m aws.JSONValue
if err := json.Unmarshal([]byte(%q), &m); err != nil {
panic("failed to unmarshal JSONValue, "+err.Error())
}
return m
}()`
return fmt.Sprintf(tmpl, string(v))
default:
panic("Unhandled type " + shape.Type)
}
+70 -22
View File
@@ -85,25 +85,29 @@ func (r *referenceResolver) resolveReference(ref *ShapeRef) {
return
}
if shape, ok := r.API.Shapes[ref.ShapeName]; ok {
if ref.JSONValue {
ref.ShapeName = "JSONValue"
r.API.Shapes[ref.ShapeName] = jsonvalueShape
}
ref.API = r.API // resolve reference back to API
ref.Shape = shape // resolve shape reference
if r.visited[ref] {
return
}
r.visited[ref] = true
shape.refs = append(shape.refs, ref) // register the ref
// resolve shape's references, if it has any
r.resolveShape(shape)
shape, ok := r.API.Shapes[ref.ShapeName]
if !ok {
panic(fmt.Sprintf("unable resolve reference, %s", ref.ShapeName))
return
}
if ref.JSONValue {
ref.ShapeName = "JSONValue"
r.API.Shapes[ref.ShapeName] = jsonvalueShape
}
ref.API = r.API // resolve reference back to API
ref.Shape = shape // resolve shape reference
if r.visited[ref] {
return
}
r.visited[ref] = true
shape.refs = append(shape.refs, ref) // register the ref
// resolve shape's references, if it has any
r.resolveShape(shape)
}
// resolveShape resolves a shape's Member Key Value, and nested member
@@ -164,7 +168,7 @@ func (a *API) fixStutterNames() {
for name, op := range a.Operations {
newName := re.ReplaceAllString(name, "")
if newName != name {
if newName != name && len(newName) > 0 {
delete(a.Operations, name)
a.Operations[newName] = op
}
@@ -173,7 +177,7 @@ func (a *API) fixStutterNames() {
for k, s := range a.Shapes {
newName := re.ReplaceAllString(k, "")
if newName != s.ShapeName {
if newName != s.ShapeName && len(newName) > 0 {
s.Rename(newName)
}
}
@@ -244,6 +248,50 @@ func (a *API) renameExportable() {
}
}
// renameCollidingFields will rename any fields that uses an SDK or Golang
// specific name.
func (a *API) renameCollidingFields() {
for _, v := range a.Shapes {
namesWithSet := map[string]struct{}{}
for k, field := range v.MemberRefs {
if strings.HasPrefix(k, "Set") {
namesWithSet[k] = struct{}{}
}
if collides(k) {
renameCollidingField(k, v, field)
}
}
// checks if any field names collide with setters.
for name := range namesWithSet {
if field, ok := v.MemberRefs["Set"+name]; ok {
renameCollidingField(name, v, field)
}
}
}
}
func renameCollidingField(name string, v *Shape, field *ShapeRef) {
newName := name + "_"
fmt.Printf("Shape %s's field %q renamed to %q\n", v.ShapeName, name, newName)
delete(v.MemberRefs, name)
v.MemberRefs[newName] = field
}
// collides will return true if it is a name used by the SDK or Golang.
func collides(name string) bool {
switch name {
case "String",
"GoString",
"Validate":
return true
default:
return false
}
}
// createInputOutputShapes creates toplevel input/output shapes if they
// have not been defined in the API. This normalizes all APIs to always
// have an input and output structure in the signature.
@@ -278,9 +326,9 @@ func (a *API) makeIOShape(name string) *Shape {
// removeUnusedShapes removes shapes from the API which are not referenced by any
// other shape in the API.
func (a *API) removeUnusedShapes() {
for n, s := range a.Shapes {
for _, s := range a.Shapes {
if len(s.refs) == 0 {
delete(a.Shapes, n)
a.removeShape(s)
}
}
}
+44 -2
View File
@@ -22,7 +22,7 @@ func TestUniqueInputAndOutputs(t *testing.T) {
v.output = true
shamelist["FooService"]["OpBothNoRename"] = v
testCases := [][]struct {
cases := [][]struct {
expectedInput string
expectedOutput string
operation string
@@ -113,7 +113,7 @@ func TestUniqueInputAndOutputs(t *testing.T) {
},
}
for _, c := range testCases {
for _, c := range cases {
a := &API{
name: "FooService",
Operations: map[string]*Operation{},
@@ -167,3 +167,45 @@ func TestUniqueInputAndOutputs(t *testing.T) {
}
}
func TestCollidingFields(t *testing.T) {
cases := []struct {
api *API
expected []*Shapes
}{
{
&API{
name: "FooService",
Shapes: []*Shapes{
{
MemberRefs: map[string]*ShapeRef{
"String": &ShapeRef{},
"GoString": &ShapeRef{},
"Validate": &ShapeRef{},
"Foo": &ShapeRef{},
"SetFoo": &ShapeRef{},
},
},
},
},
[]*Shapes{
{
MemberRefs: map[string]*ShapeRef{
"String_": &ShapeRef{},
"GoString_": &ShapeRef{},
"Validate_": &ShapeRef{},
"Foo": &ShapeRef{},
"SetFoo_": &ShapeRef{},
},
},
},
},
}
for _, c := range testCases {
c.api.renameCollidingFields()
if !reflect.DeepEqual(c.api.Shapes, c.expected) {
t.Errorf("expected %v, but received %v", c.expected, c.api.Shapes)
}
}
}
+5 -14
View File
@@ -55,9 +55,9 @@ type Shape struct {
ShapeName string
Documentation string
MemberRefs map[string]*ShapeRef `json:"members"`
MemberRef ShapeRef `json:"member"`
KeyRef ShapeRef `json:"key"`
ValueRef ShapeRef `json:"value"`
MemberRef ShapeRef `json:"member"` // List ref
KeyRef ShapeRef `json:"key"` // map key ref
ValueRef ShapeRef `json:"value"` // map value ref
Required []string
Payload string
Type string
@@ -73,6 +73,8 @@ type Shape struct {
Min float64 // optional Minimum length (string, list) or value (number)
Max float64 // optional Maximum length (string, list) or value (number)
IsEventStream bool `json:"eventstream"`
refs []*ShapeRef // References to this shape
resolvePkg string // use this package in the goType() if present
@@ -516,17 +518,6 @@ var structShapeTmpl = template.Must(template.New("StructShape").Funcs(template.F
"GetCrosslinkURL": GetCrosslinkURL,
}).Parse(`
{{ .Docstring }}
{{ if ne $.OrigShapeName "" -}}
{{ $crosslinkURL := GetCrosslinkURL $.API.BaseCrosslinkURL $.API.Metadata.UID $.OrigShapeName -}}
{{ if ne $crosslinkURL "" -}}
// Please also see {{ $crosslinkURL }}
{{ end -}}
{{ else -}}
{{ $crosslinkURL := GetCrosslinkURL $.API.BaseCrosslinkURL $.API.Metadata.UID $.ShapeName -}}
{{ if ne $crosslinkURL "" -}}
// Please also see {{ $crosslinkURL }}
{{ end -}}
{{ end -}}
{{ $context := . -}}
type {{ .ShapeName }} struct {
_ struct{} {{ .GoTags true false }}
+13 -1
View File
@@ -132,7 +132,7 @@ func main() {
for svcName := range excludeServices {
if strings.Contains(os.Getenv("SERVICES"), svcName) {
fmt.Printf("Service %s is not supported\n", svcName)
fmt.Fprintf(os.Stderr, "Service %s is not supported\n", svcName)
os.Exit(1)
}
}
@@ -141,6 +141,10 @@ func main() {
// Remove old API versions from list
m := map[string]bool{}
// caches paths to ensure we are not overriding previously generated
// code.
servicePaths := map[string]struct{}{}
for i := range files {
idx := len(files) - 1 - i
parts := strings.Split(files[idx], string(filepath.Separator))
@@ -168,6 +172,13 @@ func main() {
continue
}
if _, ok := servicePaths[genInfo.PackageDir]; ok {
fmt.Fprintf(os.Stderr, "Path %q has already been generated", genInfo.PackageDir)
os.Exit(1)
}
servicePaths[genInfo.PackageDir] = struct{}{}
wg.Add(1)
go func(g *generateInfo, filename string) {
defer wg.Done()
@@ -183,6 +194,7 @@ func writeServiceFiles(g *generateInfo, filename string) {
if r := recover(); r != nil {
fmt.Fprintf(os.Stderr, "Error generating %s\n%s\n%s\n",
filename, r, debug.Stack())
os.Exit(1)
}
}()