goでimport文をチェックする実装はそんなに難しくないので。
実装内容を網羅していない。
主要な所をひっぱってきただけ。
実際はソースコードで。
ソースコード
importが空白の場合は残念
build.go
if path == "" {
return p, fmt.Errorf("import %q: invalid import path", path)
}
path変数はチェック対象のimport文で指定した文字列の1つ
ローカルインポート判定
build.go
// IsLocalImport reports whether the import path is
// a local import path, like ".", "..", "./foo", or "../foo".
func IsLocalImport(path string) bool {
return path == "." || path == ".." ||
strings.HasPrefix(path, "./") || strings.HasPrefix(path, "../")
}
ローカルインポート時は事前チェック無し
ここではエラーで止めていない。
とりあえず、実際に読み込んでみてエラーになったらダメというやり方。
(no such file or directoryエラー)
GOROOT、GOPATHの中になくてもOK
これより以下はローカルインポートでは無い場合
絶対パスは残念
build.go
if strings.HasPrefix(path, "/") {
return p, fmt.Errorf("import %q: cannot import absolute path", path)
}
Vendorは GOROOT もしくは GOPATH の中
if searchVendor(ctxt.GOROOT, true) {
goto Found
}
for _, root := range gopath {
if searchVendor(root, false) {
goto Found
}
}
searchVendorの引数は
searchVendor := func(root string, isGoroot bool) bool {...}
import文で指定のモノがみつかったら goto Found
Vendorを確認するディレクトリかどうかのチェック
searchVendor := func(root string, isGoroot bool) bool {
sub, ok := ctxt.hasSubdir(root, srcDir)
if !ok || !strings.HasPrefix(sub, "src/") || strings.Contains(sub, "/testdata/") {
return false
}
この辺りはひっかかりそう。
GOROOTのsrc内を確認
if ctxt.GOROOT != "" {
dir := ctxt.joinPath(ctxt.GOROOT, "src", path)
isDir := ctxt.isDir(dir)
binaryOnly = !isDir && mode&AllowBinary != 0 && pkga != "" && ctxt.isFile(ctxt.joinPath(ctxt.GOROOT, pkga))
if isDir || binaryOnly {
p.Dir = dir
p.Goroot = true
p.Root = ctxt.GOROOT
goto Found
}
tried.goroot = dir
}
みつかったら goto Found
みつからなかったら tried.goroot 変数にいれとく(エラー表示用目的)
path変数はimportで書いた文字列
GOPATH のsrc内を確認
for _, root := range gopath {
dir := ctxt.joinPath(root, "src", path)
isDir := ctxt.isDir(dir)
binaryOnly = !isDir && mode&AllowBinary != 0 && pkga != "" && ctxt.isFile(ctxt.joinPath(root, pkga))
if isDir || binaryOnly {
p.Dir = dir
p.Root = root
goto Found
}
tried.gopath = append(tried.gopath, dir)
}
gopathに設定したpathの数だけチェック
import文がどれにも合致しなかったら残念
build.go
return p, fmt.Errorf("cannot find package %q in any of:\n%s", path, strings.Join(paths, "\n"))