...

Source file src/github.com/rogpeppe/go-internal/imports/scan.go

Documentation: github.com/rogpeppe/go-internal/imports

     1  // Copyright 2018 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package imports
     6  
     7  import (
     8  	"fmt"
     9  	"io/ioutil"
    10  	"os"
    11  	"path/filepath"
    12  	"sort"
    13  	"strconv"
    14  	"strings"
    15  )
    16  
    17  func ScanDir(dir string, tags map[string]bool) ([]string, []string, error) {
    18  	infos, err := ioutil.ReadDir(dir)
    19  	if err != nil {
    20  		return nil, nil, err
    21  	}
    22  	var files []string
    23  	for _, info := range infos {
    24  		name := info.Name()
    25  		if info.Mode().IsRegular() && !strings.HasPrefix(name, "_") && strings.HasSuffix(name, ".go") && MatchFile(name, tags) {
    26  			files = append(files, filepath.Join(dir, name))
    27  		}
    28  	}
    29  	return scanFiles(files, tags, false)
    30  }
    31  
    32  func ScanFiles(files []string, tags map[string]bool) ([]string, []string, error) {
    33  	return scanFiles(files, tags, true)
    34  }
    35  
    36  func scanFiles(files []string, tags map[string]bool, explicitFiles bool) ([]string, []string, error) {
    37  	imports := make(map[string]bool)
    38  	testImports := make(map[string]bool)
    39  	numFiles := 0
    40  Files:
    41  	for _, name := range files {
    42  		r, err := os.Open(name)
    43  		if err != nil {
    44  			return nil, nil, err
    45  		}
    46  		var list []string
    47  		data, err := ReadImports(r, false, &list)
    48  		r.Close()
    49  		if err != nil {
    50  			return nil, nil, fmt.Errorf("reading %s: %v", name, err)
    51  		}
    52  
    53  		// import "C" is implicit requirement of cgo tag.
    54  		// When listing files on the command line (explicitFiles=true)
    55  		// we do not apply build tag filtering but we still do apply
    56  		// cgo filtering, so no explicitFiles check here.
    57  		// Why? Because we always have, and it's not worth breaking
    58  		// that behavior now.
    59  		for _, path := range list {
    60  			if path == `"C"` && !tags["cgo"] && !tags["*"] {
    61  				continue Files
    62  			}
    63  		}
    64  
    65  		if !explicitFiles && !ShouldBuild(data, tags) {
    66  			continue
    67  		}
    68  		numFiles++
    69  		m := imports
    70  		if strings.HasSuffix(name, "_test.go") {
    71  			m = testImports
    72  		}
    73  		for _, p := range list {
    74  			q, err := strconv.Unquote(p)
    75  			if err != nil {
    76  				continue
    77  			}
    78  			m[q] = true
    79  		}
    80  	}
    81  	if numFiles == 0 {
    82  		return nil, nil, ErrNoGo
    83  	}
    84  	return keys(imports), keys(testImports), nil
    85  }
    86  
    87  var ErrNoGo = fmt.Errorf("no Go source files")
    88  
    89  func keys(m map[string]bool) []string {
    90  	var list []string
    91  	for k := range m {
    92  		list = append(list, k)
    93  	}
    94  	sort.Strings(list)
    95  	return list
    96  }
    97  

View as plain text