func importPathFromPath(root string) string { for _, gopath := range filepath.SplitList(build.Default.GOPATH) { srcPath := filepath.Join(gopath, "src") if strings.HasPrefix(root, srcPath) { return filepath.ToSlash(root[len(srcPath)+1:]) } } srcPath := filepath.Join(build.Default.GOROOT, "src", "pkg") if strings.HasPrefix(root, srcPath) { glog.Warning("Code path should be in GOPATH, but is in GOROOT: ", root) return filepath.ToSlash(root[len(srcPath)+1:]) } glog.Error("Unexpected! Code path is not in GOPATH: ", root) return "" }
// Applications can add custom time formats to this array, and they will be // automatically attempted when binding a time.Time. TimeFormats = []string{} DateFormat string DateTimeFormat string IntBinder = Binder{ Bind: ValueBinder(func(val string, typ reflect.Type) reflect.Value { if len(val) == 0 { return reflect.Zero(typ) } intValue, err := strconv.ParseInt(val, 10, 64) if err != nil { glog.Warning(err) return reflect.Zero(typ) } pValue := reflect.New(typ) pValue.Elem().SetInt(intValue) return pValue.Elem() }), Unbind: func(output map[string]string, key string, val interface{}) { output[key] = fmt.Sprintf("%d", val) }, } UintBinder = Binder{ Bind: ValueBinder(func(val string, typ reflect.Type) reflect.Value { if len(val) == 0 { return reflect.Zero(typ)
// Parse the app controllers directory and return a list of the controller types found. // Returns a CompileError if the parsing fails. func ProcessSource(roots []string) (*SourceInfo, *revel.Error) { var ( srcInfo *SourceInfo compileError *revel.Error ) for _, root := range roots { rootImportPath := importPathFromPath(root) if rootImportPath == "" { glog.Warning("Skipping code path ", root) continue } // Start walking the directory tree. filepath.Walk(root, func(path string, info os.FileInfo, err error) error { if err != nil { log.Println("Error scanning app source:", err) return nil } if !info.IsDir() || info.Name() == "tmp" { return nil } // Get the import path of the package. pkgImportPath := rootImportPath if root != path { pkgImportPath = rootImportPath + "/" + filepath.ToSlash(path[len(root)+1:]) } // Parse files within the path. var pkgs map[string]*ast.Package fset := token.NewFileSet() pkgs, err = parser.ParseDir(fset, path, func(f os.FileInfo) bool { return !f.IsDir() && !strings.HasPrefix(f.Name(), ".") && strings.HasSuffix(f.Name(), ".go") }, 0) if err != nil { if errList, ok := err.(scanner.ErrorList); ok { var pos token.Position = errList[0].Pos compileError = &revel.Error{ SourceType: ".go source", Title: "Go Compilation Error", Path: pos.Filename, Description: errList[0].Msg, Line: pos.Line, Column: pos.Column, SourceLines: revel.MustReadLines(pos.Filename), } return compileError } ast.Print(nil, err) log.Fatalf("Failed to parse dir: %s", err) } // Skip "main" packages. delete(pkgs, "main") // If there is no code in this directory, skip it. if len(pkgs) == 0 { return nil } // There should be only one package in this directory. if len(pkgs) > 1 { log.Println("Most unexpected! Multiple packages in a single directory:", pkgs) } var pkg *ast.Package for _, v := range pkgs { pkg = v } srcInfo = appendSourceInfo(srcInfo, processPackage(fset, pkgImportPath, path, pkg)) return nil }) } return srcInfo, compileError }