From ac326d12aab389794392c85e6e393c67b071d7c6 Mon Sep 17 00:00:00 2001
From: Pandurang Patil <pandurang.patil@privado.ai>
Date: Fri, 23 Jun 2023 13:23:37 +0530
Subject: [PATCH] logging metadata information of processing (#21)

1. Added stdout message to be processed by invoking utility.
2. Better error handling mechanism and subsequently logging the error
situation for given file on stout.

Note: where messages are printed with `log` it will print it to
`stderr`. `fmt.println` and its other version will print the message to
`stdout`
---
 goastgen/libgoastgen.go          | 28 +++++++++-------
 goastgen/libgoastgen_ast_test.go |  2 +-
 main.go                          | 57 +++++++++++++++++++++++++-------
 3 files changed, 62 insertions(+), 25 deletions(-)

diff --git a/goastgen/libgoastgen.go b/goastgen/libgoastgen.go
index 3f32e3f..3a7b91e 100644
--- a/goastgen/libgoastgen.go
+++ b/goastgen/libgoastgen.go
@@ -21,12 +21,15 @@ import (
  Returns:
   If given source is valid go source then it will generate AST in JSON format other will return "" string.
 */
-func ParseAstFromSource(filename string, src any) string {
+func ParseAstFromSource(filename string, src any) (string, error) {
 	fset := token.NewFileSet()
 	parsedAst, err := parser.ParseFile(fset, filename, src, 0)
 	if err != nil {
 		// TODO: convert this to just warning error log.
-		log.Fatal(err)
+		log.SetPrefix("[ERROR]")
+		log.Println("Error while parsing source from source file -> '", filename, "'")
+		log.Print(err)
+		return "", err
 	}
 	result := serilizeToMap(parsedAst, fset)
 	return serilizeToJsonStr(result)
@@ -42,14 +45,15 @@ func ParseAstFromSource(filename string, src any) string {
  Returns:
   If given directory contains valid go source code then it will generate AST in JSON format otherwise will return "" string.
 */
-func ParseAstFromDir(dir string) string {
+func ParseAstFromDir(dir string) (string, error) {
 	fset := token.NewFileSet()
 	parsedAst, err := parser.ParseDir(fset, dir, nil, 0)
 	if err != nil {
 		// TODO: convert this to just warning error log.
 		log.SetPrefix("[ERROR]")
-		log.Println("Error while parsing source from source directory -> '", dir, ",")
+		log.Println("Error while parsing source from source directory -> '", dir, "'")
 		log.Print(err)
+		return "", err
 	}
 	result := serilizeToMap(parsedAst, fset)
 	return serilizeToJsonStr(result)
@@ -65,7 +69,7 @@ func ParseAstFromDir(dir string) string {
  Returns:
   If given file is a valid go code then it will generate AST in JSON format otherwise will return "" string.
 */
-func ParseAstFromFile(file string) string {
+func ParseAstFromFile(file string) (string, error) {
 	fset := token.NewFileSet()
 	// NOTE: Haven't explore much of mode parameter. Default value has been passed as 0
 	parsedAst, err := parser.ParseFile(fset, file, nil, 0)
@@ -73,11 +77,10 @@ func ParseAstFromFile(file string) string {
 		log.SetPrefix("[ERROR]")
 		log.Println("Error while parsing source file -> '", file, ",")
 		log.Print(err)
-		return ""
-	} else {
-		result := serilizeToMap(parsedAst, fset)
-		return serilizeToJsonStr(result)
+		return "", err
 	}
+	result := serilizeToMap(parsedAst, fset)
+	return serilizeToJsonStr(result)
 }
 
 /*
@@ -89,14 +92,15 @@ func ParseAstFromFile(file string) string {
  Returns:
   JSON string
 */
-func serilizeToJsonStr(objectMap interface{}) string {
+func serilizeToJsonStr(objectMap interface{}) (string, error) {
 	jsonStr, err := json.MarshalIndent(objectMap, "", "  ")
 	if err != nil {
 		log.SetPrefix("[ERROR]")
 		log.Println("Error while generating the AST JSON")
-		log.Print(err)
+		log.Println(err)
+		return "", err
 	}
-	return string(jsonStr)
+	return string(jsonStr), nil
 }
 
 /*
diff --git a/goastgen/libgoastgen_ast_test.go b/goastgen/libgoastgen_ast_test.go
index 9bc3752..2e70d08 100644
--- a/goastgen/libgoastgen_ast_test.go
+++ b/goastgen/libgoastgen_ast_test.go
@@ -38,7 +38,7 @@ func TestFirst(t *testing.T) {
 		"fmt.Println(\"Hello World\")\n" +
 		"}"
 
-	result := ParseAstFromSource("helloworld.go", code)
+	result, _ := ParseAstFromSource("helloworld.go", code)
 	fmt.Println(result)
 
 }
diff --git a/main.go b/main.go
index 116eeb5..ad5712d 100644
--- a/main.go
+++ b/main.go
@@ -3,6 +3,7 @@ package main
 import (
 	"flag"
 	"fmt"
+	"log"
 	"os"
 	"path/filepath"
 	"privado.ai/goastgen/goastgen"
@@ -20,7 +21,9 @@ func processRequest(out string, inputPath string) {
 	if strings.HasSuffix(inputPath, ".go") {
 		fileInfo, err := os.Stat(inputPath)
 		if err != nil {
-			fmt.Println("Failed to get file info:", err)
+			log.SetPrefix("[ERROR]")
+			log.Println("Failed to get file info:", err)
+			fmt.Printf("Error accessing path '%s'\n", inputPath)
 			return
 		}
 		directory := filepath.Dir(inputPath)
@@ -30,11 +33,25 @@ func processRequest(out string, inputPath string) {
 		} else {
 			outFile = filepath.Join(out, fileInfo.Name()+".json")
 		}
-		writeFileContents(outFile, goastgen.ParseAstFromFile(inputPath))
+		jsonResult, perr := goastgen.ParseAstFromFile(inputPath)
+		if perr != nil {
+			fmt.Printf("Failed to generate AST for %s\n", inputPath)
+			return
+		} 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", inputPath, outFile)
+			}
+			return
+		}
 	} else {
 		err := filepath.Walk(inputPath, func(path string, info os.FileInfo, err error) error {
 			if err != nil {
-				fmt.Printf("Error accessing path %s: %v\n", path, err)
+				log.SetPrefix("[ERROR]")
+				log.Printf("Error accessing path %s: %v\n", path, err)
+				fmt.Printf("Error accessing path '%s'\n", path)
 				return err
 			}
 			if !info.IsDir() && strings.HasSuffix(info.Name(), ".go") {
@@ -45,13 +62,25 @@ func processRequest(out string, inputPath string) {
 				} else {
 					outFile = filepath.Join(out, strings.ReplaceAll(directory, inputPath, ""), info.Name()+".json")
 				}
-				writeFileContents(outFile, goastgen.ParseAstFromFile(path))
+				jsonResult, perr := goastgen.ParseAstFromFile(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
 		})
 
 		if err != nil {
-			fmt.Printf("Error walking the path %s: %v\n", inputPath, err)
+			log.SetPrefix("[ERROR]")
+			log.Printf("Error walking the path %s: %v\n", inputPath, err)
 		}
 	}
 }
@@ -87,27 +116,31 @@ func parseArguments() (string, string) {
 	return out, inputPath
 }
 
-func writeFileContents(location string, contents string) {
+func writeFileContents(location string, contents string) error {
 	// Open the file for writing (creates a new file if it doesn't exist)
 	dir := filepath.Dir(location)
 
 	// Create all directories recursively
 	err := os.MkdirAll(dir, 0755)
 	if err != nil {
-		fmt.Println("Failed to create file:", err)
-		return
+		log.SetPrefix("[ERROR]")
+		log.Println("Failed to create file:", err)
+		return err
 	}
 	file, err := os.Create(location)
 	if err != nil {
-		fmt.Println("Failed to create file:", err)
-		return
+		log.SetPrefix("[ERROR]")
+		log.Println("Failed to create file:", err)
+		return err
 	}
 	defer file.Close()
 
 	// Write the contents to the file
 	_, err = file.WriteString(contents)
 	if err != nil {
-		fmt.Println("Failed to write to file:", err)
-		return
+		log.SetPrefix("[ERROR]")
+		log.Println("Failed to write to file:", err)
+		return err
 	}
+	return nil
 }