Skip to content

Commit

Permalink
feat: [cmd] add golang analysis api support
Browse files Browse the repository at this point in the history
  • Loading branch information
phodal committed Jan 17, 2020
1 parent 2d5f662 commit f5f1b2e
Show file tree
Hide file tree
Showing 10 changed files with 168 additions and 112 deletions.
62 changes: 48 additions & 14 deletions cmd/analysis.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@ package cmd
import (
"encoding/json"
"github.com/phodal/coca/cmd/cmd_util"
"github.com/phodal/coca/pkg/adapter/cocafile"
"github.com/phodal/coca/pkg/application/analysis"
"github.com/phodal/coca/pkg/domain/core_domain"
"github.com/phodal/coca/pkg/infrastructure/ast/cocago"
"github.com/spf13/cobra"
)

type AnalysisCmdConfig struct {
Path string
ForceUpdate bool
Lang string
}

var (
Expand All @@ -21,31 +25,61 @@ var analysisCmd = &cobra.Command{
Short: "analysis code",
Long: ``,
Run: func(cmd *cobra.Command, args []string) {
importPath := analysisCmdConfig.Path
if analysisCmdConfig.Lang == "go" {
analysisGo()
} else {
analysisJava()
}
},
}

identifierApp := analysis.NewJavaIdentifierApp()
iNodes := identifierApp.AnalysisPath(importPath)
func analysisGo() {
importPath := analysisCmdConfig.Path

identModel, _ := json.MarshalIndent(iNodes, "", "\t")
cmd_util.WriteToCocaFile("identify.json", string(identModel))
var results []core_domain.CodeFile
files := cocafile.GetFilesWithFilter(importPath, cocafile.GoFileFilter)
for _, file := range files {
parser := cocago.NewCocagoParser()
parser.SetOutput(output)
result := parser.ProcessFile(file)

var classes []string = nil
results = append(results, result)
}

for _, node := range iNodes {
classes = append(classes, node.Package+"."+node.NodeName)
}
var ds []core_domain.CodeDataStruct
for _, result := range results {
ds = append(ds, result.DataStructures...)
}

callApp := analysis.NewJavaFullApp()
cModel, _ := json.MarshalIndent(ds, "", "\t")
cmd_util.WriteToCocaFile("godeps.json", string(cModel))
}

callNodes := callApp.AnalysisPath(importPath, classes, iNodes)
cModel, _ := json.MarshalIndent(callNodes, "", "\t")
cmd_util.WriteToCocaFile("deps.json", string(cModel))
},
func analysisJava() {
importPath := analysisCmdConfig.Path
identifierApp := analysis.NewJavaIdentifierApp()
iNodes := identifierApp.AnalysisPath(importPath)

identModel, _ := json.MarshalIndent(iNodes, "", "\t")
cmd_util.WriteToCocaFile("identify.json", string(identModel))

var classes []string = nil

for _, node := range iNodes {
classes = append(classes, node.Package+"."+node.NodeName)
}

callApp := analysis.NewJavaFullApp()

callNodes := callApp.AnalysisPath(importPath, classes, iNodes)
cModel, _ := json.MarshalIndent(callNodes, "", "\t")
cmd_util.WriteToCocaFile("deps.json", string(cModel))
}

func init() {
rootCmd.AddCommand(analysisCmd)

analysisCmd.PersistentFlags().StringVarP(&analysisCmdConfig.Path, "path", "p", ".", "example -p core/main")
analysisCmd.PersistentFlags().StringVarP(&analysisCmdConfig.Lang, "lang", "l", "java", "coca analysis -l java")
analysisCmd.PersistentFlags().BoolVarP(&analysisCmdConfig.ForceUpdate, "force", "f", false, "force update -f")
}
17 changes: 17 additions & 0 deletions cmd/analysis_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package cmd

import (
"github.com/phodal/coca/cocatest/testcase"
"testing"
)

func Test_Analysis_Go(t *testing.T) {
path := "config"

analysis := []testcase.CmdTestCase{{
Name: "analysis",
Cmd: "analysis -f -l go -p " + path,
Golden: "testdata/analysis_go.txt",
}}
RunTestCmd(t, analysis)
}
2 changes: 1 addition & 1 deletion cmd/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ func TestApi(t *testing.T) {

analysis := []testcase.CmdTestCase{{
Name: "analysis",
Cmd: "analysis -p " + path,
Cmd: "analysis -l java -p " + path,
Golden: "",
}}
RunTestCmd(t, analysis)
Expand Down
1 change: 1 addition & 0 deletions cmd/testdata/analysis_go.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
process file config/cmd_config.go
1 change: 0 additions & 1 deletion pkg/application/concept/concept_analyser.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ func buildMethodsFromDeps(clzs []core_domain.CodeDataStruct) string_helper.PairL
}

words := SegmentConceptCamelcase(methodsName)

words = removeNormalWords(words)

wordCounts := string_helper.RankByWordCount(words)
Expand Down
4 changes: 3 additions & 1 deletion pkg/application/goapp/process.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package goapp

import (
"bytes"
"github.com/phodal/coca/pkg/adapter/cocafile"
"github.com/phodal/coca/pkg/domain/core_domain"
"github.com/phodal/coca/pkg/infrastructure/ast/cocago"
Expand All @@ -16,7 +17,8 @@ func ProcessPackage(path string, debug bool) []*core_domain.CodeFile {
filesData := make([]*core_domain.CodeFile, len(files))
parser := cocago.NewCocagoParser()
if debug {
parser.SetOutput(true)
buf := new(bytes.Buffer)
parser.SetOutput(buf)
}
for i, file := range files {
processFile := parser.ProcessFile(file)
Expand Down
59 changes: 30 additions & 29 deletions pkg/infrastructure/ast/cocago/cocago_parser.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package cocago

import (
"bytes"
"fmt"
"github.com/phodal/coca/pkg/domain/core_domain"
"go/ast"
Expand All @@ -19,7 +18,6 @@ var currentPackage *core_domain.CodePackage
type CocagoParser struct {
}

var debug = false
var output io.Writer

func NewCocagoParser() *CocagoParser {
Expand All @@ -28,10 +26,8 @@ func NewCocagoParser() *CocagoParser {
return &CocagoParser{}
}

func (n *CocagoParser) SetOutput(isDebug bool) io.Writer {
output = new(bytes.Buffer)
debug = isDebug

func (n *CocagoParser) SetOutput(out io.Writer) io.Writer {
output = out
return output
}

Expand All @@ -56,6 +52,7 @@ func (n *CocagoParser) Visitor(f *ast.File, fset *token.FileSet, fileName string
var currentStruct core_domain.CodeDataStruct
var currentFile core_domain.CodeFile
var currentFunc *core_domain.CodeFunction
var dsMap = make(map[string]*core_domain.CodeDataStruct)

currentFile.FullName = fileName
var funcType = ""
Expand All @@ -72,28 +69,39 @@ func (n *CocagoParser) Visitor(f *ast.File, fset *token.FileSet, fileName string
currentFile.Imports = append(currentFile.Imports, *imp)
case *ast.TypeSpec:
currentStruct = core_domain.CodeDataStruct{}
currentStruct.NodeName = x.Name.String()
currentStruct.NodeName = x.Name.Name
dsMap[currentStruct.NodeName] = &currentStruct
case *ast.StructType:
AddStructType(currentStruct, x, &currentFile)
fmt.Println(currentStruct.NodeName)
AddStructType(currentStruct.NodeName, x, &currentFile, dsMap)
case *ast.FuncDecl:
funcType = "FuncDecl"
currentFunc = AddFunctionDecl(currentStruct, x, &currentFile)
currentFunc, recv := AddFunctionDecl(x, &currentFile)
if recv != "" {
dsMap[recv].Functions = append(dsMap[recv].Functions, *currentFunc)
}
case *ast.FuncType:
if funcType != "FuncDecl" {
AddNestedFunction(currentFunc, x)
}

funcType = ""
case *ast.InterfaceType:
AddInterface(x, lastIdent, &currentFile)
currentStruct := AddInterface(x, lastIdent, &currentFile)
dsMap[currentStruct.NodeName] = &currentStruct
default:
if reflect.TypeOf(x) != nil {
if reflect.TypeOf(x) != nil && reflect.TypeOf(output).String() != "*bytes.Buffer" {
fmt.Fprintf(output, "Visitor case %s\n", reflect.TypeOf(x))
}
}
return true
})

currentFile.DataStructures = nil
for _, ds := range dsMap {
currentFile.DataStructures = append(currentFile.DataStructures, *ds)
}

return &currentFile
}

Expand All @@ -114,7 +122,7 @@ func BuildImport(x *ast.ImportSpec) *core_domain.CodeImport {
return imp
}

func AddInterface(x *ast.InterfaceType, ident string, codeFile *core_domain.CodeFile) {
func AddInterface(x *ast.InterfaceType, ident string, codeFile *core_domain.CodeFile) core_domain.CodeDataStruct {
properties := BuildFieldToProperty(x.Methods.List)

dataStruct := core_domain.CodeDataStruct{
Expand All @@ -123,34 +131,27 @@ func AddInterface(x *ast.InterfaceType, ident string, codeFile *core_domain.Code
}

member := core_domain.CodeMember{
DataStructID: dataStruct.NodeName,
DataStructID: ident,
Type: "interface",
}

codeFile.Members = append(codeFile.Members, &member)
codeFile.DataStructures = append(codeFile.DataStructures, dataStruct)

return dataStruct
}

func AddNestedFunction(currentFunc *core_domain.CodeFunction, x *ast.FuncType) {

}

func AddFunctionDecl(currentStruct core_domain.CodeDataStruct, x *ast.FuncDecl, currentFile *core_domain.CodeFile) *core_domain.CodeFunction {
func AddFunctionDecl(x *ast.FuncDecl, currentFile *core_domain.CodeFile) (*core_domain.CodeFunction, string) {
recv := ""
if x.Recv != nil {
recv = BuildReceiver(x, recv)
}
codeFunc := BuildFunction(x)

if recv != "" {
member := GetMemberFromFile(*currentFile, recv)
if member != nil {
member.FunctionNodes = append(member.FunctionNodes, *codeFunc)
} else {
createMember(currentStruct)
// todo
}
} else {
if recv == "" {
member := GetMemberFromFile(*currentFile, "default")
if member == nil {
member = &core_domain.CodeMember{
Expand All @@ -163,7 +164,7 @@ func AddFunctionDecl(currentStruct core_domain.CodeDataStruct, x *ast.FuncDecl,
currentFile.Members = append(currentFile.Members, member)
}

return codeFunc
return codeFunc, recv
}

func BuildReceiver(x *ast.FuncDecl, recv string) string {
Expand Down Expand Up @@ -260,16 +261,16 @@ func getFieldName(field *ast.Field) string {
return field.Names[0].Name
}

func AddStructType(currentStruct core_domain.CodeDataStruct, x *ast.StructType, currentFile *core_domain.CodeFile) {
func AddStructType(currentNodeName string, x *ast.StructType, currentFile *core_domain.CodeFile, dsMap map[string]*core_domain.CodeDataStruct) {
member := core_domain.CodeMember{
DataStructID: currentStruct.NodeName,
DataStructID: currentNodeName,
Type: "struct",
}
for _, field := range x.Fields.List {
property := BuildPropertyField(getFieldName(field), field)
member.FileID = currentFile.FullName
currentStruct.InOutProperties = append(currentStruct.InOutProperties, *property)
dsMap[currentNodeName].InOutProperties = append(dsMap[currentNodeName].InOutProperties, *property)
}

currentFile.Members = append(currentFile.Members, &member)
currentFile.DataStructures = append(currentFile.DataStructures, currentStruct)
}
4 changes: 3 additions & 1 deletion pkg/infrastructure/ast/cocago/cocago_parser_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cocago

import (
"bytes"
. "github.com/onsi/gomega"
"github.com/phodal/coca/cocatest"
"os"
Expand All @@ -18,7 +19,8 @@ var testParser *CocagoParser

func setup() {
testParser = NewCocagoParser()
testParser.SetOutput(true)
buf := new(bytes.Buffer)
testParser.SetOutput(buf)
}

func shutdown() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,7 @@
"Fields": null,
"FilePath": "",
"FunctionCalls": null,
"Functions": null,
"Implements": null,
"Imports": null,
"InOutProperties": null,
"InnerStructures": null,
"MultipleExtend": null,
"NodeName": "O",
"Package": "",
"Type": ""
}
],
"FullName": "testdata/node_infos/struct_type_zero.code",
"Imports": null,
"Members": [
{
"DataStructID": "O",
"FileID": "",
"FunctionNodes": [
"Functions": [
{
"Annotations": null,
"Extension": null,
Expand All @@ -47,6 +30,23 @@
"ReturnType": ""
}
],
"Implements": null,
"Imports": null,
"InOutProperties": null,
"InnerStructures": null,
"MultipleExtend": null,
"NodeName": "O",
"Package": "",
"Type": ""
}
],
"FullName": "testdata/node_infos/struct_type_zero.code",
"Imports": null,
"Members": [
{
"DataStructID": "O",
"FileID": "",
"FunctionNodes": null,
"ID": "",
"Name": "",
"Namespace": null,
Expand Down
Loading

0 comments on commit f5f1b2e

Please sign in to comment.