示例#1
0
func (ctx *Context) getFileTags(pathname string, f *ast.File) ([]string, error) {
	_, filenameExt := filepath.Split(pathname)

	if strings.HasSuffix(pathname, ".go") == false {
		return nil, nil
	}
	var err error
	if f == nil {
		f, err = parser.ParseFile(token.NewFileSet(), pathname, nil, parser.ImportsOnly|parser.ParseComments)
		if err != nil {
			return nil, err
		}
	}

	filename := filenameExt[:len(filenameExt)-3]

	l := strings.Split(filename, "_")
	tags := make([]string, 0)

	if n := len(l); n > 0 && l[n-1] == "test" {
		l = l[:n-1]
		tags = append(tags, "test")
	}
	n := len(l)
	if n >= 2 && knownOS[l[n-2]] && knownArch[l[n-1]] {
		tags = append(tags, l[n-2])
		tags = append(tags, l[n-1])
	}
	if n >= 1 && knownOS[l[n-1]] {
		tags = append(tags, l[n-1])
	}
	if n >= 1 && knownArch[l[n-1]] {
		tags = append(tags, l[n-1])
	}

	const buildPrefix = "// +build "
	for _, cc := range f.Comments {
		for _, c := range cc.List {
			if strings.HasPrefix(c.Text, buildPrefix) {
				text := strings.TrimPrefix(c.Text, buildPrefix)
				ss := strings.Fields(text)
				for _, s := range ss {
					tags = append(tags, strings.Split(s, ",")...)
				}
			}
		}
	}
	return tags, nil
}
示例#2
0
// addFileImports is called from loadPackage and resolveUnknown.
func (ctx *Context) addFileImports(pathname, gopath string) error {
	dir, filenameExt := filepath.Split(pathname)
	importPath := pathos.FileTrimPrefix(dir, gopath)
	importPath = pathos.SlashToImportPath(importPath)
	importPath = strings.TrimPrefix(importPath, "/")
	importPath = strings.TrimSuffix(importPath, "/")

	if strings.HasSuffix(pathname, ".go") == false {
		return nil
	}
	// No need to add the same file more then once.
	for _, pkg := range ctx.Package {
		if pathos.FileStringEquals(pkg.Dir, dir) == false {
			continue
		}
		for _, f := range pkg.Files {
			if pathos.FileStringEquals(f.Path, pathname) {
				return nil
			}
		}
		for _, f := range pkg.ignoreFile {
			if pathos.FileStringEquals(f, filenameExt) {
				return nil
			}
		}
	}
	f, err := parser.ParseFile(token.NewFileSet(), pathname, nil, parser.ImportsOnly|parser.ParseComments)
	if err != nil {
		return err
	}

	tags, err := ctx.getFileTags(pathname, f)
	if err != nil {
		return err
	}

	pkg, found := ctx.Package[importPath]
	if !found {
		status := StatusUnknown
		if f.Name.Name == "main" {
			status = StatusProgram
		}
		pkg = ctx.setPackage(dir, importPath, importPath, gopath, status)
		ctx.Package[importPath] = pkg
	}
	if pkg.Status != StatusLocal && pkg.Status != StatusProgram {
		for _, tag := range tags {
			for _, ignore := range ctx.ignoreTag {
				if tag == ignore {
					pkg.ignoreFile = append(pkg.ignoreFile, filenameExt)
					return nil
				}
			}
		}
	}
	pf := &File{
		Package: pkg,
		Path:    pathname,
		Imports: make([]string, len(f.Imports)),
	}
	pkg.Files = append(pkg.Files, pf)
	for i := range f.Imports {
		imp := f.Imports[i].Path.Value
		imp, err = strconv.Unquote(imp)
		if err != nil {
			return err
		}
		if strings.HasPrefix(imp, "./") {
			imp = path.Join(importPath, imp)
		}
		pf.Imports[i] = imp
		err = ctx.addSingleImport(pkg.Dir, imp)
		if err != nil {
			return err
		}
	}

	// Record any import comment for file.
	var ic *ast.Comment
	if f.Name != nil {
		pos := f.Name.Pos()
	big:
		// Find the next comment after the package name.
		for _, cblock := range f.Comments {
			for _, c := range cblock.List {
				if c.Pos() > pos {
					ic = c
					break big
				}
			}
		}
	}
	if ic != nil {
		// If it starts with the import text, assume it is the import comment and remove.
		if index := strings.Index(ic.Text, " import "); index > 0 && index < 5 {
			q := strings.TrimSpace(ic.Text[index+len(" import "):])
			pf.ImportComment, err = strconv.Unquote(q)
			if err != nil {
				pf.ImportComment = q
			}
		}
	}

	return nil
}