github.com/alecthomas/golangci-lint@v1.4.2-0.20180609094924-581a3564ff68/pkg/lint/astcache/astcache.go (about)

     1  package astcache
     2  
     3  import (
     4  	"fmt"
     5  	"go/ast"
     6  	"go/parser"
     7  	"go/token"
     8  	"os"
     9  	"path/filepath"
    10  
    11  	"github.com/sirupsen/logrus"
    12  	"golang.org/x/tools/go/loader"
    13  )
    14  
    15  type File struct {
    16  	F    *ast.File
    17  	Fset *token.FileSet
    18  	Name string
    19  	err  error
    20  }
    21  
    22  type Cache struct {
    23  	m map[string]*File
    24  	s []*File
    25  }
    26  
    27  func (c Cache) GetAllValidFiles() []*File {
    28  	return c.s
    29  }
    30  
    31  func (c *Cache) prepareValidFiles() {
    32  	files := make([]*File, 0, len(c.m))
    33  	for _, f := range c.m {
    34  		if f.err != nil || f.F == nil {
    35  			continue
    36  		}
    37  		files = append(files, f)
    38  	}
    39  	c.s = files
    40  }
    41  
    42  func LoadFromProgram(prog *loader.Program) (*Cache, error) {
    43  	c := &Cache{
    44  		m: map[string]*File{},
    45  	}
    46  
    47  	root, err := os.Getwd()
    48  	if err != nil {
    49  		return nil, fmt.Errorf("can't get working dir: %s", err)
    50  	}
    51  
    52  	for _, pkg := range prog.InitialPackages() {
    53  		for _, f := range pkg.Files {
    54  			pos := prog.Fset.Position(f.Pos())
    55  			if pos.Filename == "" {
    56  				continue
    57  			}
    58  
    59  			relPath, err := filepath.Rel(root, pos.Filename)
    60  			if err != nil {
    61  				logrus.Warnf("Can't get relative path for %s and %s: %s",
    62  					root, pos.Filename, err)
    63  				continue
    64  			}
    65  
    66  			c.m[relPath] = &File{
    67  				F:    f,
    68  				Fset: prog.Fset,
    69  				Name: relPath,
    70  			}
    71  		}
    72  	}
    73  
    74  	c.prepareValidFiles()
    75  	return c, nil
    76  }
    77  
    78  func LoadFromFiles(files []string) *Cache {
    79  	c := &Cache{
    80  		m: map[string]*File{},
    81  	}
    82  	fset := token.NewFileSet()
    83  	for _, filePath := range files {
    84  		f, err := parser.ParseFile(fset, filePath, nil, parser.ParseComments) // comments needed by e.g. golint
    85  		c.m[filePath] = &File{
    86  			F:    f,
    87  			Fset: fset,
    88  			err:  err,
    89  			Name: filePath,
    90  		}
    91  	}
    92  
    93  	c.prepareValidFiles()
    94  	return c
    95  }