mirror of
https://github.com/foomo/gotsrpc.git
synced 2025-10-16 12:35:35 +00:00
reading further
This commit is contained in:
parent
8b70e1025c
commit
6e5aa7a265
@ -1,13 +1,35 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/foomo/gotsrpc"
|
||||
)
|
||||
|
||||
func jsonDump(v interface{}) {
|
||||
jsonBytes, err := json.MarshalIndent(v, "", " ")
|
||||
fmt.Println(err, string(jsonBytes))
|
||||
}
|
||||
func main() {
|
||||
//fmt.Println("hello", os.Args[1])
|
||||
gotsrpc.Read(os.Args[1], os.Args[2:])
|
||||
//gotsrpc.ReadFile("/Users/jan/go/src/github.com/foomo/gotsrpc/demo/demo.go")
|
||||
gotsrpc.ReaderTrace = true
|
||||
//gotsrpc.Read(os.Args[1], os.Args[2:])
|
||||
//gotsrpc.ReadFile("/Users/jan/go/src/github.com/foomo/gotsrpc/demo/demo.go", []string{"Service"})
|
||||
goPath := os.Getenv("GOPATH")
|
||||
|
||||
if len(goPath) == 0 {
|
||||
fmt.Println("GOPATH not set")
|
||||
os.Exit(1)
|
||||
}
|
||||
jsonDump(os.Args[2:])
|
||||
services, err := gotsrpc.ReadServicesInPackage(goPath, os.Args[1], os.Args[2:])
|
||||
if err != nil {
|
||||
fmt.Println("an error occured", err)
|
||||
os.Exit(2)
|
||||
}
|
||||
jsonDump(services)
|
||||
|
||||
//gotsrpc.ReadFile("/Users/jan/go/src/github.com/foomo/gotsrpc/demo/demo.go", []string{"Service"})
|
||||
}
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
package demo
|
||||
|
||||
import nstd "github.com/foomo/gotsrpc/demo/nested"
|
||||
|
||||
type Address struct {
|
||||
City string `json:"city,omitempty"`
|
||||
SecretServerCrap bool `json:"-"`
|
||||
@ -8,6 +10,8 @@ type Address struct {
|
||||
ArrayArrayAddress [][]*Address
|
||||
People []Person
|
||||
MapCrap map[string]map[int]bool
|
||||
NestedPtr *nstd.Nested
|
||||
NestedStruct nstd.Nested
|
||||
}
|
||||
|
||||
type Person struct {
|
||||
@ -19,6 +23,9 @@ type Person struct {
|
||||
InlinePtr *struct {
|
||||
Foo bool
|
||||
}
|
||||
InlineStruct struct {
|
||||
Bar string
|
||||
}
|
||||
iAmPrivate string
|
||||
}
|
||||
|
||||
|
||||
11
demo/nested/nested.go
Normal file
11
demo/nested/nested.go
Normal file
@ -0,0 +1,11 @@
|
||||
package nested
|
||||
|
||||
type Nested struct {
|
||||
Name string
|
||||
SuperNestedString struct {
|
||||
Ha int64
|
||||
}
|
||||
SuperNestedPtr *struct {
|
||||
Bla string
|
||||
}
|
||||
}
|
||||
34
gotsrpc.go
34
gotsrpc.go
@ -2,7 +2,13 @@ package gotsrpc
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"net/http"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@ -44,3 +50,31 @@ func Reply(response []interface{}, w http.ResponseWriter) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write(jsonBytes)
|
||||
}
|
||||
|
||||
func jsonDump(v interface{}) {
|
||||
jsonBytes, err := json.MarshalIndent(v, "", " ")
|
||||
fmt.Println(err, string(jsonBytes))
|
||||
}
|
||||
|
||||
func parsePackage(goPath string, packageName string) (pkg *ast.Package, err error) {
|
||||
fset := token.NewFileSet()
|
||||
dir := path.Join(goPath, "src", packageName)
|
||||
pkgs, err := parser.ParseDir(fset, dir, nil, parser.AllErrors)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
packageNameParts := strings.Split(packageName, "/")
|
||||
if len(packageNameParts) == 0 {
|
||||
return nil, errors.New("invalid package name given")
|
||||
}
|
||||
strippedPackageName := packageNameParts[len(packageNameParts)-1]
|
||||
foundPackages := []string{}
|
||||
for pkgName, pkg := range pkgs {
|
||||
fmt.Println("pkgName", pkgName)
|
||||
if pkgName == strippedPackageName {
|
||||
return pkg, nil
|
||||
}
|
||||
foundPackages = append(foundPackages, pkgName)
|
||||
}
|
||||
return nil, errors.New("package \"" + packageName + "\" not found in " + strings.Join(foundPackages, ", "))
|
||||
}
|
||||
|
||||
24
model.go
24
model.go
@ -16,13 +16,18 @@ type JSONInfo struct {
|
||||
Ignore bool
|
||||
}
|
||||
|
||||
type StructType struct {
|
||||
Name string
|
||||
Package string
|
||||
}
|
||||
|
||||
type Value struct {
|
||||
ScalarType ScalarType `json:",omitempty"`
|
||||
StructType string `json:",omitempty"`
|
||||
Struct *Struct `json:",omitempty"`
|
||||
Map *Map `json:",omitempty"`
|
||||
Array *Array `json:",omitempty"`
|
||||
IsPtr bool `json:",omitempty"`
|
||||
ScalarType ScalarType `json:",omitempty"`
|
||||
StructType *StructType `json:",omitempty"`
|
||||
Struct *Struct `json:",omitempty"`
|
||||
Map *Map `json:",omitempty"`
|
||||
Array *Array `json:",omitempty"`
|
||||
IsPtr bool `json:",omitempty"`
|
||||
}
|
||||
|
||||
type Array struct {
|
||||
@ -40,7 +45,12 @@ type Field struct {
|
||||
JSONInfo *JSONInfo `json:",omitempty"`
|
||||
}
|
||||
|
||||
type Func struct {
|
||||
type Service struct {
|
||||
Name string
|
||||
Methods []*Method
|
||||
}
|
||||
|
||||
type Method struct {
|
||||
Name string
|
||||
Args []*Field
|
||||
Return []*Field
|
||||
|
||||
85
servicereader.go
Normal file
85
servicereader.go
Normal file
@ -0,0 +1,85 @@
|
||||
package gotsrpc
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func readServiceFile(file *ast.File, services map[string]*Service) error {
|
||||
for _, decl := range file.Decls {
|
||||
if reflect.ValueOf(decl).Type().String() == "*ast.FuncDecl" {
|
||||
funcDecl := decl.(*ast.FuncDecl)
|
||||
if funcDecl.Recv != nil {
|
||||
trace("that is a method named", funcDecl.Name)
|
||||
if len(funcDecl.Recv.List) == 1 {
|
||||
firstReceiverField := funcDecl.Recv.List[0]
|
||||
if "*ast.StarExpr" == reflect.ValueOf(firstReceiverField.Type).Type().String() {
|
||||
starExpr := firstReceiverField.Type.(*ast.StarExpr)
|
||||
if "*ast.Ident" == reflect.ValueOf(starExpr.X).Type().String() {
|
||||
ident := starExpr.X.(*ast.Ident)
|
||||
fmt.Println(" on sth:", ident.Name)
|
||||
|
||||
service, ok := services[ident.Name]
|
||||
|
||||
if ok {
|
||||
service.Methods = append(service.Methods, &Method{
|
||||
Name: funcDecl.Name.Name,
|
||||
Args: readFields(funcDecl.Type.Params.List),
|
||||
Return: readFields(funcDecl.Type.Results.List),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
trace("no receiver for", funcDecl.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func readFields(astFields []*ast.Field) (fields []*Field) {
|
||||
fields = []*Field{}
|
||||
for _, param := range astFields {
|
||||
name, value, _ := readField(param)
|
||||
fields = append(fields, &Field{
|
||||
Name: name,
|
||||
Value: value,
|
||||
})
|
||||
}
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
func readServicesInPackage(pkg *ast.Package, serviceNames []string) (services map[string]*Service, err error) {
|
||||
services = map[string]*Service{}
|
||||
for _, serviceName := range serviceNames {
|
||||
services[serviceName] = &Service{
|
||||
Name: serviceName,
|
||||
Methods: []*Method{},
|
||||
}
|
||||
}
|
||||
for _, file := range pkg.Files {
|
||||
err = readServiceFile(file, services)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func ReadServicesInPackage(goPath string, packageName string, serviceNames []string) (services map[string]*Service, err error) {
|
||||
if len(serviceNames) == 0 {
|
||||
err = errors.New("nothing to do service names are empty")
|
||||
return
|
||||
}
|
||||
pkg, err := parsePackage(goPath, packageName)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return readServicesInPackage(pkg, serviceNames)
|
||||
}
|
||||
@ -1,19 +1,18 @@
|
||||
package gotsrpc
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func jsonDump(v interface{}) {
|
||||
jsonBytes, err := json.MarshalIndent(v, "", " ")
|
||||
fmt.Println(err, string(jsonBytes))
|
||||
var ReaderTrace = false
|
||||
|
||||
func trace(args ...interface{}) {
|
||||
if ReaderTrace {
|
||||
fmt.Println(args...)
|
||||
}
|
||||
}
|
||||
|
||||
func extractJSONInfo(tag string) *JSONInfo {
|
||||
@ -58,47 +57,13 @@ func extractJSONInfo(tag string) *JSONInfo {
|
||||
Ignore: ignore,
|
||||
}
|
||||
}
|
||||
func filterFiles(info os.FileInfo) bool {
|
||||
name := info.Name()
|
||||
parseIt := !info.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go")
|
||||
return parseIt
|
||||
}
|
||||
|
||||
func ReadFile(file string) {
|
||||
fset := token.NewFileSet() // positions are relative to fset
|
||||
|
||||
// Parse the file containing this very example
|
||||
// but stop after processing the imports.
|
||||
f, err := parser.ParseFile(fset, file, nil, parser.Trace)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
readFile(file, f)
|
||||
}
|
||||
|
||||
func Read(dir string, services []string) error {
|
||||
fset := token.NewFileSet()
|
||||
pkgs, err := parser.ParseDir(fset, dir, nil, parser.AllErrors)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
//fmt.Println(pkgs, err)
|
||||
|
||||
func ReadStructs(pkg *ast.Package, services []string) error {
|
||||
structs := map[string]*Struct{}
|
||||
|
||||
for pkgName, pkg := range pkgs {
|
||||
|
||||
fmt.Println("pkg", pkgName) //, "scope", pkg.Scope, "files", pkg.Files)
|
||||
fmt.Println("-------------------------------------------------------------------------")
|
||||
|
||||
for filename, file := range pkg.Files {
|
||||
//readFile(filename, file)
|
||||
extractStructs(filename, file, structs)
|
||||
}
|
||||
for _, file := range pkg.Files {
|
||||
//readFile(filename, file)
|
||||
extractStructs(file, structs)
|
||||
}
|
||||
jsonDump(structs)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -113,7 +78,6 @@ func getScalarFromAstIdent(ident *ast.Ident) ScalarType {
|
||||
default:
|
||||
return ScalarTypeNone
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func getTypesFromAstType(ident *ast.Ident) (structType string, scalarType ScalarType) {
|
||||
@ -128,52 +92,72 @@ func getTypesFromAstType(ident *ast.Ident) (structType string, scalarType Scalar
|
||||
func readAstType(v *Value, fieldIdent *ast.Ident) {
|
||||
structType, scalarType := getTypesFromAstType(fieldIdent)
|
||||
v.ScalarType = scalarType
|
||||
v.StructType = structType
|
||||
if len(structType) > 0 {
|
||||
v.StructType = &StructType{
|
||||
Name: structType,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func readAstStarExpr(v *Value, starExpr *ast.StarExpr) {
|
||||
v.IsPtr = true
|
||||
switch reflect.ValueOf(starExpr.X).Type().String() {
|
||||
case "*ast.Ident":
|
||||
ident := starExpr.X.(*ast.Ident)
|
||||
v.StructType = ident.Name
|
||||
v.IsPtr = true
|
||||
v.StructType = &StructType{
|
||||
Name: ident.Name,
|
||||
}
|
||||
case "*ast.StructType":
|
||||
// nested anonymous
|
||||
structType := starExpr.X.(*ast.StructType)
|
||||
v.Struct = &Struct{}
|
||||
v.Struct.Fields = readFieldList(structType.Fields.List)
|
||||
readAstStructType(v, starExpr.X.(*ast.StructType))
|
||||
case "*ast.SelectorExpr":
|
||||
readAstSelectorExpr(v, starExpr.X.(*ast.SelectorExpr))
|
||||
default:
|
||||
fmt.Println("a pointer on what", reflect.ValueOf(starExpr.X).Type().String())
|
||||
trace("a pointer on what", reflect.ValueOf(starExpr.X).Type().String())
|
||||
}
|
||||
}
|
||||
|
||||
func readAstArrayType(v *Value, arrayType *ast.ArrayType) {
|
||||
|
||||
switch reflect.ValueOf(arrayType.Elt).Type().String() {
|
||||
case "*ast.StarExpr":
|
||||
readAstStarExpr(v, arrayType.Elt.(*ast.StarExpr))
|
||||
default:
|
||||
fmt.Println("array type elt", reflect.ValueOf(arrayType.Elt).Type().String())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func readAstMapType(m *Map, mapType *ast.MapType) {
|
||||
|
||||
fmt.Println(" map key", mapType.Key, reflect.ValueOf(mapType.Key).Type().String())
|
||||
fmt.Println(" map value", mapType.Value, reflect.ValueOf(mapType.Value).Type().String())
|
||||
|
||||
trace(" map key", mapType.Key, reflect.ValueOf(mapType.Key).Type().String())
|
||||
trace(" map value", mapType.Value, reflect.ValueOf(mapType.Value).Type().String())
|
||||
// key
|
||||
switch reflect.ValueOf(mapType.Key).Type().String() {
|
||||
case "*ast.Ident":
|
||||
_, scalarType := getTypesFromAstType(mapType.Key.(*ast.Ident))
|
||||
m.KeyType = string(scalarType)
|
||||
}
|
||||
|
||||
// value
|
||||
m.Value.loadExpr(mapType.Value)
|
||||
}
|
||||
|
||||
func readAstSelectorExpr(v *Value, selectorExpr *ast.SelectorExpr) {
|
||||
switch reflect.ValueOf(selectorExpr.X).Type().String() {
|
||||
case "*ast.Ident":
|
||||
// that could be the package name
|
||||
selectorIdent := selectorExpr.X.(*ast.Ident)
|
||||
v.StructType = &StructType{
|
||||
Package: selectorIdent.Name,
|
||||
Name: selectorExpr.Sel.Name,
|
||||
}
|
||||
default:
|
||||
fmt.Println("selectorExpr.Sel !?", selectorExpr.X, reflect.ValueOf(selectorExpr.X).Type().String())
|
||||
}
|
||||
}
|
||||
|
||||
func readAstStructType(v *Value, structType *ast.StructType) {
|
||||
v.Struct = &Struct{}
|
||||
v.Struct.Fields = readFieldList(structType.Fields.List)
|
||||
}
|
||||
|
||||
func (v *Value) loadExpr(expr ast.Expr) {
|
||||
//fmt.Println(field.Names[0].Name, field.Type, reflect.ValueOf(field.Type).Type().String())
|
||||
switch reflect.ValueOf(expr).Type().String() {
|
||||
@ -198,7 +182,6 @@ func (v *Value) loadExpr(expr ast.Expr) {
|
||||
case "*ast.Ident":
|
||||
fieldIdent := expr.(*ast.Ident)
|
||||
readAstType(v, fieldIdent)
|
||||
|
||||
case "*ast.StarExpr":
|
||||
// a pointer on sth
|
||||
readAstStarExpr(v, expr.(*ast.StarExpr))
|
||||
@ -207,33 +190,38 @@ func (v *Value) loadExpr(expr ast.Expr) {
|
||||
Value: &Value{},
|
||||
}
|
||||
readAstMapType(v.Map, expr.(*ast.MapType))
|
||||
case "*ast.SelectorExpr":
|
||||
readAstSelectorExpr(v, expr.(*ast.SelectorExpr))
|
||||
case "*ast.StructType":
|
||||
readAstStructType(v, expr.(*ast.StructType))
|
||||
default:
|
||||
fmt.Println("what kind of field ident would that be ?!", reflect.ValueOf(expr).Type().String())
|
||||
|
||||
trace("what kind of field ident would that be ?!", reflect.ValueOf(expr).Type().String())
|
||||
}
|
||||
}
|
||||
|
||||
func readField(astField *ast.Field) (name string, v *Value, jsonInfo *JSONInfo) {
|
||||
|
||||
name = astField.Names[0].Name
|
||||
if strings.Compare(strings.ToLower(name[:1]), name[:1]) == 0 {
|
||||
// not exported
|
||||
return "", nil, nil
|
||||
name = ""
|
||||
if len(astField.Names) > 0 {
|
||||
name = astField.Names[0].Name
|
||||
}
|
||||
fmt.Println(" ", astField.Names[0].Name)
|
||||
trace(" ", name)
|
||||
v = &Value{}
|
||||
v.loadExpr(astField.Type)
|
||||
|
||||
if astField.Tag != nil {
|
||||
jsonInfo = extractJSONInfo(astField.Tag.Value[1 : len(astField.Tag.Value)-1])
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func readFieldList(fieldList []*ast.Field) (fields map[string]*Field) {
|
||||
fields = map[string]*Field{}
|
||||
for _, field := range fieldList {
|
||||
|
||||
name, value, jsonInfo := readField(field)
|
||||
|
||||
if strings.Compare(strings.ToLower(name[:1]), name[:1]) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
if value != nil {
|
||||
fields[name] = &Field{
|
||||
Name: name,
|
||||
@ -241,16 +229,14 @@ func readFieldList(fieldList []*ast.Field) (fields map[string]*Field) {
|
||||
JSONInfo: jsonInfo,
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func extractStructs(filename string, file *ast.File, structs map[string]*Struct) {
|
||||
//fmt.Println("-------------------------------------------------------------------------")
|
||||
//jsonDump(file)
|
||||
//fmt.Println(filename, file.Scope, len(file.Scope.Objects), file.Scope.Objects)
|
||||
//fmt.Println("-------------------------------------------------------------------------")
|
||||
func extractStructs(file *ast.File, structs map[string]*Struct) {
|
||||
for _, imp := range file.Imports {
|
||||
fmt.Println("import", imp.Name, imp.Path)
|
||||
}
|
||||
for name, obj := range file.Scope.Objects {
|
||||
//fmt.Println(name, obj.Kind, obj.Data)
|
||||
if obj.Kind == ast.Typ && obj.Decl != nil {
|
||||
@ -264,7 +250,7 @@ func extractStructs(filename string, file *ast.File, structs map[string]*Struct)
|
||||
typeSpecRefl := reflect.ValueOf(typeSpec.Type)
|
||||
if typeSpecRefl.Type().String() == "*ast.StructType" {
|
||||
structType := typeSpec.Type.(*ast.StructType)
|
||||
fmt.Println("structType.Fields", structType.Fields)
|
||||
trace("StructType", obj.Name)
|
||||
structs[name].Fields = readFieldList(structType.Fields.List)
|
||||
} else {
|
||||
// fmt.Println(" what would that be", typeSpecRefl.Type().String())
|
||||
@ -279,27 +265,3 @@ func extractStructs(filename string, file *ast.File, structs map[string]*Struct)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func readFile(filename string, file *ast.File) {
|
||||
for _, decl := range file.Decls {
|
||||
if reflect.ValueOf(decl).Type().String() == "*ast.FuncDecl" {
|
||||
funcDecl := decl.(*ast.FuncDecl)
|
||||
if funcDecl.Recv != nil {
|
||||
fmt.Println("that is a method named", funcDecl.Name)
|
||||
if len(funcDecl.Recv.List) == 1 {
|
||||
firstReceiverField := funcDecl.Recv.List[0]
|
||||
if "*ast.StarExpr" == reflect.ValueOf(firstReceiverField.Type).Type().String() {
|
||||
starExpr := firstReceiverField.Type.(*ast.StarExpr)
|
||||
if "*ast.Ident" == reflect.ValueOf(starExpr.X).Type().String() {
|
||||
ident := starExpr.X.(*ast.Ident)
|
||||
fmt.Println(" on sth:", ident.Name)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fmt.Println("no receiver for", funcDecl.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user