diff --git a/go.mod b/go.mod index 0cf5969..e425a29 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.18 require ( github.com/google/uuid v1.3.0 github.com/stretchr/testify v1.8.4 + golang.org/x/mod v0.11.0 ) require ( diff --git a/go.sum b/go.sum index 8d8b455..ec852b4 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU= +golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/goastgen/libgoastgen.go b/goastgen/libgoastgen.go index f005d9d..4b09cdb 100644 --- a/goastgen/libgoastgen.go +++ b/goastgen/libgoastgen.go @@ -5,6 +5,8 @@ import ( "go/ast" "go/parser" "go/token" + "golang.org/x/mod/modfile" + "io/ioutil" "log" "reflect" "unsafe" @@ -83,6 +85,55 @@ func ParseAstFromFile(file string) (string, error) { return serilizeToJsonStr(result) } +// ParseModFromFile +/* + It will parse the .mod file and generate module and dependency information in JSON format + + Parameters: + file: absolute file path to be parsed + + Returns: + If given file is a valid .mod file then it will generate the module and dependency information in JSON format +*/ +func ParseModFromFile(file string) (string, error) { + objMap := make(map[string]interface{}) + contents, err := ioutil.ReadFile(file) + if err != nil { + log.SetPrefix("[ERROR]") + log.Printf("Error while processing '%s' \n", file) + log.Println(err) + return "", err + } + modFile, err := modfile.Parse(file, contents, nil) + if err != nil { + log.SetPrefix("[ERROR]") + log.Printf("Error while processing '%s' \n", file) + log.Println(err) + return "", err + } + objMap["node_filename"] = file + module := make(map[string]interface{}) + module["name"] = modFile.Module.Mod.Path + module["node_line_no"] = modFile.Module.Syntax.Start.Line + module["node_col_no"] = modFile.Module.Syntax.Start.LineRune + module["node_line_no_end"] = modFile.Module.Syntax.End.Line + module["node_col_no_end"] = modFile.Module.Syntax.End.LineRune + objMap["module"] = module + dependencies := []interface{}{} + for _, req := range modFile.Require { + node := make(map[string]interface{}) + node["module"] = req.Mod.Path + node["version"] = req.Mod.Version + node["node_line_no"] = req.Syntax.Start.Line + node["node_col_no"] = req.Syntax.Start.LineRune + node["node_line_no_end"] = req.Syntax.End.Line + node["node_col_no_end"] = req.Syntax.End.LineRune + dependencies = append(dependencies, node) + } + objMap["dependencies"] = dependencies + return serilizeToJsonStr(objMap) +} + /* Independent function which handles serialisation of map[string]interface{} in to JSON diff --git a/main.go b/main.go index ad5712d..f5f59b4 100644 --- a/main.go +++ b/main.go @@ -74,6 +74,26 @@ func processRequest(out string, inputPath string) { } return nil } + } else if strings.HasSuffix(info.Name(), ".mod") { + var outFile = "" + directory := filepath.Dir(path) + if out == ".ast" { + outFile = filepath.Join(inputPath, out, strings.ReplaceAll(directory, inputPath, ""), info.Name()+".json") + } else { + outFile = filepath.Join(out, strings.ReplaceAll(directory, inputPath, ""), info.Name()+".json") + } + jsonResult, perr := goastgen.ParseModFromFile(path) + if perr != nil { + fmt.Printf("Failed to generate AST for %s \n", path) + } else { + err = writeFileContents(outFile, jsonResult) + if err != nil { + fmt.Printf("Error writing AST to output location '%s'\n", outFile) + } else { + fmt.Printf("Converted AST for %s to %s \n", path, outFile) + } + return nil + } } return nil })