github.com/jd-ly/cmd@v1.0.10/parser/imports.go (about) 1 package parser 2 3 import ( 4 "github.com/jd-ly/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 if quotedPath == `"C"` { 34 continue 35 } 36 fullPath := quotedPath[1 : len(quotedPath)-1] // Remove the quotes 37 38 // If the package was not aliased (common case), we have to import it 39 // to see what the package name is. 40 // TODO: Can improve performance here a lot: 41 // 1. Do not import everything over and over again. Keep a cache. 42 // 2. Exempt the standard library; their directories always match the package name. 43 // 3. Can use build.FindOnly and then use parser.ParseDir with mode PackageClauseOnly 44 if pkgAlias == "" { 45 46 utils.Logger.Debug("Reading from build", "path", fullPath, "srcPath", srcDir, "gopath", build.Default.GOPATH) 47 pkg, err := build.Import(fullPath, srcDir, 0) 48 if err != nil { 49 // We expect this to happen for apps using reverse routing (since we 50 // have not yet generated the routes). Don't log that. 51 if !strings.HasSuffix(fullPath, "/app/routes") { 52 utils.Logger.Warn("Could not find import:", "path", fullPath, "srcPath", srcDir, "error", err) 53 } 54 continue 55 } else { 56 utils.Logger.Debug("Found package in dir", "dir", pkg.Dir, "name", pkg.ImportPath) 57 } 58 pkgAlias = pkg.Name 59 } 60 61 imports[pkgAlias] = fullPath 62 } 63 } 64 65 // Returns a valid import string from the path 66 // using the build.Defaul.GOPATH to determine the root 67 func importPathFromPath(root, basePath string) string { 68 vendorTest := filepath.Join(basePath, "vendor") 69 if len(root) > len(vendorTest) && root[:len(vendorTest)] == vendorTest { 70 return filepath.ToSlash(root[len(vendorTest)+1:]) 71 } 72 for _, gopath := range filepath.SplitList(build.Default.GOPATH) { 73 srcPath := filepath.Join(gopath, "src") 74 if strings.HasPrefix(root, srcPath) { 75 return filepath.ToSlash(root[len(srcPath)+1:]) 76 } 77 } 78 79 srcPath := filepath.Join(build.Default.GOROOT, "src", "pkg") 80 if strings.HasPrefix(root, srcPath) { 81 utils.Logger.Warn("Code path should be in GOPATH, but is in GOROOT:", "path", root) 82 return filepath.ToSlash(root[len(srcPath)+1:]) 83 } 84 85 utils.Logger.Error("Unexpected! Code path is not in GOPATH:", "path", root) 86 return "" 87 }