restic/vendor/github.com/Azure/azure-sdk-for-go/tools/apidiff/exports/exports.go

163 lines
4.8 KiB
Go

// Copyright 2018 Microsoft Corporation
//
// 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 exports
import (
"go/ast"
"strings"
)
// Content defines the set of exported constants, funcs, and structs.
type Content struct {
// the list of exported constants.
// key is the exported name, value is its type and value.
Consts map[string]Const `json:"consts,omitempty"`
// the list of exported functions and methods.
// key is the exported name, for methods it's prefixed with the receiver type (e.g. "Type.Method").
// value contains the list of params and return types.
Funcs map[string]Func `json:"funcs,omitempty"`
// the list of exported interfaces.
// key is the exported name, value contains the interface definition.
Interfaces map[string]Interface `json:"interfaces,omitempty"`
// the list of exported struct types.
// key is the exported name, value contains field information.
Structs map[string]Struct `json:"structs,omitempty"`
}
// Const is a const definition.
type Const struct {
// the type of the constant
Type string `json:"type"`
// the value of the constant
Value string `json:"value"`
}
// Func contains parameter and return types of a function/method.
type Func struct {
// a comma-delimited list of the param types
Params *string `json:"params,omitempty"`
// a comma-delimited list of the return types
Returns *string `json:"returns,omitempty"`
}
// Interface contains the list of methods for an interface.
type Interface struct {
Methods map[string]Func
}
// Struct contains field info about a struct.
type Struct struct {
// a list of anonymous fields
AnonymousFields []string `json:"anon,omitempty"`
// key/value pairs of the field names and types respectively.
Fields map[string]string `json:"fields,omitempty"`
}
// NewContent returns an initialized Content object.
func NewContent() Content {
return Content{
Consts: make(map[string]Const),
Funcs: make(map[string]Func),
Interfaces: make(map[string]Interface),
Structs: make(map[string]Struct),
}
}
// IsEmpty returns true if there is no content in any of the fields.
func (c Content) IsEmpty() bool {
return len(c.Consts) == 0 && len(c.Funcs) == 0 && len(c.Interfaces) == 0 && len(c.Structs) == 0
}
// adds the specified const declaration to the exports list
func (c *Content) addConst(pkg Package, g *ast.GenDecl) {
for _, s := range g.Specs {
co := Const{}
vs := s.(*ast.ValueSpec)
v := ""
// Type is nil for untyped consts
if vs.Type != nil {
co.Type = vs.Type.(*ast.Ident).Name
v = vs.Values[0].(*ast.BasicLit).Value
} else {
// get the type from the token type
if bl, ok := vs.Values[0].(*ast.BasicLit); ok {
co.Type = strings.ToLower(bl.Kind.String())
v = bl.Value
} else if ce, ok := vs.Values[0].(*ast.CallExpr); ok {
// const FooConst = FooType("value")
co.Type = pkg.getText(ce.Fun.Pos(), ce.Fun.End())
v = pkg.getText(ce.Args[0].Pos(), ce.Args[0].End())
} else {
panic("unhandled case for adding constant")
}
}
// remove any surrounding quotes
if v[0] == '"' {
v = v[1 : len(v)-1]
}
co.Value = v
c.Consts[vs.Names[0].Name] = co
}
}
// adds the specified function declaration to the exports list
func (c *Content) addFunc(pkg Package, f *ast.FuncDecl) {
// create a method sig, for methods it's a combination of the receiver type
// with the function name e.g. "FooReceiver.Method", else just the function name.
sig := ""
if f.Recv != nil {
sig = pkg.getText(f.Recv.List[0].Type.Pos(), f.Recv.List[0].Type.End())
sig += "."
}
sig += f.Name.Name
c.Funcs[sig] = pkg.buildFunc(f.Type)
}
// adds the specified interface type to the exports list.
func (c *Content) addInterface(pkg Package, name string, i *ast.InterfaceType) {
in := Interface{Methods: map[string]Func{}}
if i.Methods != nil {
for _, m := range i.Methods.List {
n := m.Names[0].Name
f := pkg.buildFunc(m.Type.(*ast.FuncType))
in.Methods[n] = f
}
}
c.Interfaces[name] = in
}
// adds the specified struct type to the exports list.
func (c *Content) addStruct(pkg Package, name string, s *ast.StructType) {
sd := Struct{}
// assumes all struct types have fields
pkg.translateFieldList(s.Fields.List, func(n *string, t string) {
if n == nil {
sd.AnonymousFields = append(sd.AnonymousFields, t)
} else {
if sd.Fields == nil {
sd.Fields = map[string]string{}
}
sd.Fields[*n] = t
}
})
c.Structs[name] = sd
}