1 Star 0 Fork 0

陈文甲 / fabric

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
options.go 4.09 KB
一键复制 编辑 原始数据 按行查看 历史
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package gendoc
import (
"fmt"
"go/ast"
"path"
"reflect"
"strconv"
"strings"
"github.com/hyperledger/fabric/common/metrics"
"golang.org/x/tools/go/packages"
)
// Options scans the provided list of packages for options structs used when
// creating metrics and returns instances that are recreated from the source
// tree.
func Options(pkgs []*packages.Package) ([]interface{}, error) {
var options []interface{}
for _, p := range pkgs {
for _, f := range p.Syntax {
opts, err := FileOptions(f)
if err != nil {
return nil, err
}
options = append(options, opts...)
}
}
return options, nil
}
// FileOptions walks the specified ast.File for options structs used when
// creating metrics and returns instances that are recreated from the source.
func FileOptions(f *ast.File) ([]interface{}, error) {
var imports = walkImports(f)
var options []interface{}
var errors []error
// If the file contains gendoc:ignore, ignore the file
for _, c := range f.Comments {
if strings.Index(c.Text(), "gendoc:ignore") != -1 {
return nil, nil
}
}
// Iterate over declarations
for i := range f.Decls {
ast.Inspect(f.Decls[i], func(x ast.Node) bool {
node, ok := x.(*ast.ValueSpec)
if !ok {
return true
}
for _, v := range node.Values {
value, ok := v.(*ast.CompositeLit)
if !ok {
continue
}
literalType, ok := value.Type.(*ast.SelectorExpr)
if !ok {
continue
}
ident, ok := literalType.X.(*ast.Ident)
if !ok {
continue
}
if imports[ident.Name] != "github.com/hyperledger/fabric/common/metrics" {
continue
}
option, err := createOption(literalType)
if err != nil {
errors = append(errors, err)
break
}
option, err = populateOption(value, option)
if err != nil {
errors = append(errors, err)
break
}
options = append(options, option)
}
return false
})
}
if len(errors) != 0 {
return nil, errors[0]
}
return options, nil
}
func walkImports(f *ast.File) map[string]string {
imports := map[string]string{}
for i := range f.Imports {
ast.Inspect(f.Imports[i], func(x ast.Node) bool {
switch node := x.(type) {
case *ast.ImportSpec:
importPath, err := strconv.Unquote(node.Path.Value)
if err != nil {
panic(err)
}
importName := path.Base(importPath)
if node.Name != nil {
importName = node.Name.Name
}
imports[importName] = importPath
return false
default:
return true
}
})
}
return imports
}
func createOption(lit *ast.SelectorExpr) (interface{}, error) {
optionName := lit.Sel.Name
switch optionName {
case "CounterOpts":
return &metrics.CounterOpts{}, nil
case "GaugeOpts":
return &metrics.GaugeOpts{}, nil
case "HistogramOpts":
return &metrics.HistogramOpts{}, nil
default:
return nil, fmt.Errorf("unknown object type: %s", optionName)
}
}
func populateOption(lit *ast.CompositeLit, target interface{}) (interface{}, error) {
val := reflect.ValueOf(target).Elem()
for _, elem := range lit.Elts {
if kv, ok := elem.(*ast.KeyValueExpr); ok {
name := kv.Key.(*ast.Ident).Name
field := val.FieldByName(name)
switch name {
// ignored
case "Buckets":
// slice of strings
case "LabelNames":
labelNames, err := stringSlice(kv.Value.(*ast.CompositeLit))
if err != nil {
return nil, err
}
labelNamesValue := reflect.ValueOf(labelNames)
field.Set(labelNamesValue)
// simple strings
case "Namespace", "Subsystem", "Name", "Help", "StatsdFormat":
basicVal := kv.Value.(*ast.BasicLit)
val, err := strconv.Unquote(basicVal.Value)
if err != nil {
return nil, err
}
field.SetString(val)
default:
return nil, fmt.Errorf("unknown field name: %s", name)
}
}
}
return val.Interface(), nil
}
func stringSlice(lit *ast.CompositeLit) ([]string, error) {
var slice []string
for _, elem := range lit.Elts {
val, err := strconv.Unquote(elem.(*ast.BasicLit).Value)
if err != nil {
return nil, err
}
slice = append(slice, val)
}
return slice, nil
}
1
https://gitee.com/venjia/fabric.git
git@gitee.com:venjia/fabric.git
venjia
fabric
fabric
v1.4.12

搜索帮助