mirror of https://github.com/restic/restic.git
163 lines
4.8 KiB
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
|
|
}
|