From 5e416ed9b17bab75f4077862deae964c2e8eee64 Mon Sep 17 00:00:00 2001 From: Augusto Date: Wed, 1 Apr 2020 17:52:41 +0100 Subject: [PATCH] Analyses the functions and imports of the file to be checked --- go/tests/rc/rc.go | 199 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) diff --git a/go/tests/rc/rc.go b/go/tests/rc/rc.go index 813546e8..36568dc6 100644 --- a/go/tests/rc/rc.go +++ b/go/tests/rc/rc.go @@ -2,13 +2,17 @@ package main import ( "flag" + "fmt" "go/ast" "go/parser" "go/token" + "os" "path/filepath" "regexp" "strconv" "strings" + + table "github.com/tatsushid/go-prettytable" ) type strBoolMap map[string]bool @@ -570,7 +574,202 @@ func init() { flag.BoolVar(&allowBuiltin, "allow-builtin", false, "Allowes all builtin functions and casting") } +func parseArgs(toAllow []string, builtins bool, casting bool) error { + allowedFun["builtin"] = make(map[string]bool) + predeclaredTypes := []string{"bool", "byte", "complex64", "complex128", + "error", "float32", "float64", "int", "int8", + "int16", "int32", "int64", "rune", "string", + "uint", "uint8", "uint16", "uint32", "uint64", + "uintptr", + } + + if builtins { + allowedFun["builtin"]["*"] = true + } + + if casting { + for _, v := range predeclaredTypes { + allowedFun["builtin"][v] = true + } + } + for _, v := range toAllow { + var path, funcName string + if strings.ContainsRune(v, '/') { + path = filepath.Dir(v) + funcName = filepath.Base(v) + spl := strings.Split(funcName, ".") + path = path + "/" + spl[0] + funcName = spl[1] + } else if strings.ContainsRune(v, '.') { + spl := strings.Split(v, ".") + path = spl[0] + funcName = spl[1] + } else { + path = "builtin" + funcName = v + } + if strings.ContainsRune(funcName, '#') { + spl := strings.Split(funcName, "#") + funcName = spl[0] + n, err := strconv.Atoi(spl[1]) + if err != nil { + return fmt.Errorf("After the '#' there should be a integer" + + " representing the maximum number of allowed occurrences") + } + var prefix string + if path != "" { + prefix = filepath.Base(path) + } + allowedRep[prefix+"."+funcName] = n + } + if allowedFun[path] == nil { + allowedFun[path] = make(map[string]bool) + } + allowedFun[path][funcName] = true + } + return nil +} + func main() { + flag.Parse() + if flag.NArg() < 1 { + fmt.Println("Not enough arguments: missing file") + os.Exit(1) + } + fmt.Println("Parsing:") + + err := parseArgs(flag.Args()[1:], allowBuiltin, casting) + + if err != nil { + panic(err) + } + FileSet := token.NewFileSet() + file, err := parser.ParseFile(FileSet, flag.Arg(0), nil, parser.AllErrors) + + if err != nil { + panic(err) + } + + load := make(loadedSource) + + currentPath := filepath.Dir(flag.Arg(0)) + + err = loadProgram(currentPath, load) + + if err != nil { + panic(err) + } + fmt.Println("\tOk") + + fmt.Println("Cheating:") + // Functions defined in the file + fileFunc := defs(file) + info := analyseProgram(fileFunc, currentPath, load) + info.illegals = append(analyseImports(file, FileSet, noRelativeImports), info.illegals...) + if noFor { + for _, v := range info.fors { + il := &illegal{ + T: "illegal-loop", + Name: v.name, + Pos: v.pos, + } + info.illegals = append(info.illegals, il) + } + } + + for _, v := range info.arrays { + if noArrays || noTheseArrays[v.name] { + il := &illegal{ + T: "illegal-array", + Name: v.name, + Pos: v.pos, + } + info.illegals = append(info.illegals, il) + } + } + + if noLit.active { + for _, v := range info.lits { + if noLit.reg.Match([]byte(v.name)) { + il := &illegal{ + T: "illegal-lit", + Name: v.name, + Pos: v.pos, + } + info.illegals = append(info.illegals, il) + } + } + } + for name, rep := range allowedRep { + if info.callRep[name] > rep { + diff := info.callRep[name] - rep + il := &illegal{ + T: "illegal-amount", + Name: name + " exeding max repetitions by " + strconv.Itoa(diff), + Pos: "all the project", + } + info.illegals = append(info.illegals, il) + } + } + info.illegals = removeRepetitions(info.illegals) + if info.illegals != nil { + tbl, err := table.NewTable([]table.Column{ + {Header: "\tTYPE:"}, + {Header: "NAME:", MinWidth: 7}, + {Header: "LOCATION:"}, + }...) + if err != nil { + panic(err) + } + tbl.Separator = "\t" + for _, v := range info.illegals { + tbl.AddRow("\t"+v.T, v.Name, v.Pos) + } + tbl.Print() + os.Exit(1) + } + fmt.Println("\tOk") +} + +type importVisitor struct { + imports map[string]*element +} + +func (i *importVisitor) Visit(n ast.Node) ast.Visitor { + if imp, ok := n.(*ast.ImportSpec); ok { + path, _ := strconv.Unquote(imp.Path.Value) + var name string + if imp.Name != nil { + name = imp.Name.Name + } else { + name = filepath.Base(path) + } + el := &element{ + name: path, + pos: n.Pos(), + } + i.imports[name] = el + } + return i +} + +func analyseImports(n ast.Node, fset *token.FileSet, noRelImp bool) []*illegal { + var il []*illegal + i := &importVisitor{ + imports: make(map[string]*element), + } + ast.Walk(i, n) + for _, path := range i.imports { + isRelativeImport := isRelativeImport(path.name) + if (noRelativeImports && isRelativeImport) || (allowedFun[path.name] == nil && !isRelativeImport) { + il = append(il, &illegal{ + T: "illegal-import", + Name: path.name, + Pos: fset.Position(path.pos).String(), + }) + } + } + return il } type element struct {