github.com/wiselike/revel-cmd@v1.2.1/parser/imports.go (about)

     1  package parser
     2  
     3  import (
     4  	"go/ast"
     5  	"go/build"
     6  	"go/token"
     7  	"path/filepath"
     8  	"strings"
     9  
    10  	"github.com/wiselike/revel-cmd/utils"
    11  )
    12  
    13  // Add imports to the map from the source dir.
    14  func addImports(imports map[string]string, decl ast.Decl, srcDir string) {
    15  	genDecl, ok := decl.(*ast.GenDecl)
    16  	if !ok {
    17  		return
    18  	}
    19  
    20  	if genDecl.Tok != token.IMPORT {
    21  		return
    22  	}
    23  
    24  	for _, spec := range genDecl.Specs {
    25  		importSpec := spec.(*ast.ImportSpec)
    26  		var pkgAlias string
    27  		if importSpec.Name != nil {
    28  			pkgAlias = importSpec.Name.Name
    29  			if pkgAlias == "_" {
    30  				continue
    31  			}
    32  		}
    33  		quotedPath := importSpec.Path.Value // e.g. "\"sample/app/models\""
    34  		if quotedPath == `"C"` {
    35  			continue
    36  		}
    37  		fullPath := quotedPath[1 : len(quotedPath)-1] // Remove the quotes
    38  
    39  		// If the package was not aliased (common case), we have to import it
    40  		// to see what the package name is.
    41  		// TODO: Can improve performance here a lot:
    42  		// 1. Do not import everything over and over again.  Keep a cache.
    43  		// 2. Exempt the standard library; their directories always match the package name.
    44  		// 3. Can use build.FindOnly and then use parser.ParseDir with mode PackageClauseOnly
    45  		if pkgAlias == "" {
    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  }