github.com/mlmmr/revel-cmd@v0.21.2-0.20191112133115-68d8795776dd/parser/imports.go (about) 1 package parser 2 3 import ( 4 "github.com/mlmmr/revel-cmd/utils" 5 "go/ast" 6 "go/build" 7 "go/token" 8 "path/filepath" 9 "strings" 10 ) 11 12 // Add imports to the map from the source dir 13 func addImports(imports map[string]string, decl ast.Decl, srcDir string) { 14 genDecl, ok := decl.(*ast.GenDecl) 15 if !ok { 16 return 17 } 18 19 if genDecl.Tok != token.IMPORT { 20 return 21 } 22 23 for _, spec := range genDecl.Specs { 24 importSpec := spec.(*ast.ImportSpec) 25 var pkgAlias string 26 if importSpec.Name != nil { 27 pkgAlias = importSpec.Name.Name 28 if pkgAlias == "_" { 29 continue 30 } 31 } 32 quotedPath := importSpec.Path.Value // e.g. "\"sample/app/models\"" 33 fullPath := quotedPath[1 : len(quotedPath)-1] // Remove the quotes 34 35 // If the package was not aliased (common case), we have to import it 36 // to see what the package name is. 37 // TODO: Can improve performance here a lot: 38 // 1. Do not import everything over and over again. Keep a cache. 39 // 2. Exempt the standard library; their directories always match the package name. 40 // 3. Can use build.FindOnly and then use parser.ParseDir with mode PackageClauseOnly 41 if pkgAlias == "" { 42 utils.Logger.Debug("Reading from build", "path", fullPath, "srcPath", srcDir, "gopath", build.Default.GOPATH) 43 if strings.HasSuffix(fullPath, "/app/controllers") { 44 continue 45 } 46 if strings.HasSuffix(fullPath, "/app/routes") { 47 continue 48 } 49 pkg, err := build.Import(fullPath, srcDir, 0) 50 if err != nil { 51 // We expect this to happen for apps using reverse routing (since we 52 // have not yet generated the routes). Don't log that. 53 if !strings.HasSuffix(fullPath, "/app/routes") { 54 utils.Logger.Error("Could not find import:", "path", fullPath, "srcPath", srcDir, "error", err) 55 } 56 continue 57 } else { 58 utils.Logger.Debug("Found package in dir", "dir", pkg.Dir, "name", pkg.ImportPath) 59 } 60 pkgAlias = pkg.Name 61 } 62 63 imports[pkgAlias] = fullPath 64 } 65 } 66 67 // Returns a valid import string from the path 68 // using the build.Defaul.GOPATH to determine the root 69 func importPathFromPath(root, basePath string) string { 70 vendorTest := filepath.Join(basePath, "vendor") 71 if len(root) > len(vendorTest) && root[:len(vendorTest)] == vendorTest { 72 return filepath.ToSlash(root[len(vendorTest)+1:]) 73 } 74 for _, gopath := range filepath.SplitList(build.Default.GOPATH) { 75 srcPath := filepath.Join(gopath, "src") 76 if strings.HasPrefix(root, srcPath) { 77 return filepath.ToSlash(root[len(srcPath)+1:]) 78 } 79 } 80 81 srcPath := filepath.Join(build.Default.GOROOT, "src", "pkg") 82 if strings.HasPrefix(root, srcPath) { 83 utils.Logger.Warn("Code path should be in GOPATH, but is in GOROOT:", "path", root) 84 return filepath.ToSlash(root[len(srcPath)+1:]) 85 } 86 87 utils.Logger.Error("Unexpected! Code path is not in GOPATH:", "path", root) 88 return "" 89 }