1. Support unparam linter and fix found issues
2. Replace forked mvdan.cc/lint and mvdan.cc/interfacer with the
upstream ones
3. Minimize forked megacheck: move the most of it's code to this repo
4. Use golang.org/x/tools/go/ssa import path instead of custom fork
paths
5. In golang.org/x/tools/go/{ssa,callgraph} use changed code from
honnef.co/go/tools
6. Add megacheck.check-unexported option: it found some issues in
the repo, fixed them all
		
	
			
		
			
				
	
	
		
			128 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			128 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package astcache
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"go/ast"
 | 
						|
	"go/parser"
 | 
						|
	"go/token"
 | 
						|
	"os"
 | 
						|
	"path/filepath"
 | 
						|
 | 
						|
	"github.com/golangci/golangci-lint/pkg/logutils"
 | 
						|
	"golang.org/x/tools/go/loader"
 | 
						|
)
 | 
						|
 | 
						|
type File struct {
 | 
						|
	F    *ast.File
 | 
						|
	Fset *token.FileSet
 | 
						|
	Name string
 | 
						|
	Err  error
 | 
						|
}
 | 
						|
 | 
						|
type Cache struct {
 | 
						|
	m   map[string]*File
 | 
						|
	s   []*File
 | 
						|
	log logutils.Log
 | 
						|
}
 | 
						|
 | 
						|
func NewCache(log logutils.Log) *Cache {
 | 
						|
	return &Cache{
 | 
						|
		m:   map[string]*File{},
 | 
						|
		log: log,
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (c Cache) Get(filename string) *File {
 | 
						|
	return c.m[filepath.Clean(filename)]
 | 
						|
}
 | 
						|
 | 
						|
func (c Cache) GetOrParse(filename string) *File {
 | 
						|
	f := c.m[filename]
 | 
						|
	if f != nil {
 | 
						|
		return f
 | 
						|
	}
 | 
						|
 | 
						|
	c.log.Infof("Parse AST for file %s on demand", filename)
 | 
						|
	c.parseFile(filename, nil)
 | 
						|
	return c.m[filename]
 | 
						|
}
 | 
						|
 | 
						|
func (c Cache) GetAllValidFiles() []*File {
 | 
						|
	return c.s
 | 
						|
}
 | 
						|
 | 
						|
func (c *Cache) prepareValidFiles() {
 | 
						|
	files := make([]*File, 0, len(c.m))
 | 
						|
	for _, f := range c.m {
 | 
						|
		if f.Err != nil || f.F == nil {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		files = append(files, f)
 | 
						|
	}
 | 
						|
	c.s = files
 | 
						|
}
 | 
						|
 | 
						|
func LoadFromProgram(prog *loader.Program, log logutils.Log) (*Cache, error) {
 | 
						|
	c := NewCache(log)
 | 
						|
 | 
						|
	root, err := os.Getwd()
 | 
						|
	if err != nil {
 | 
						|
		return nil, fmt.Errorf("can't get working dir: %s", err)
 | 
						|
	}
 | 
						|
 | 
						|
	for _, pkg := range prog.InitialPackages() {
 | 
						|
		for _, f := range pkg.Files {
 | 
						|
			pos := prog.Fset.Position(f.Pos())
 | 
						|
			if pos.Filename == "" {
 | 
						|
				continue
 | 
						|
			}
 | 
						|
 | 
						|
			relPath, err := filepath.Rel(root, pos.Filename)
 | 
						|
			if err != nil {
 | 
						|
				c.log.Warnf("Can't get relative path for %s and %s: %s",
 | 
						|
					root, pos.Filename, err)
 | 
						|
				continue
 | 
						|
			}
 | 
						|
 | 
						|
			c.m[relPath] = &File{
 | 
						|
				F:    f,
 | 
						|
				Fset: prog.Fset,
 | 
						|
				Name: relPath,
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	c.prepareValidFiles()
 | 
						|
	return c, nil
 | 
						|
}
 | 
						|
 | 
						|
func (c *Cache) parseFile(filePath string, fset *token.FileSet) {
 | 
						|
	if fset == nil {
 | 
						|
		fset = token.NewFileSet()
 | 
						|
	}
 | 
						|
 | 
						|
	f, err := parser.ParseFile(fset, filePath, nil, parser.ParseComments) // comments needed by e.g. golint
 | 
						|
	c.m[filePath] = &File{
 | 
						|
		F:    f,
 | 
						|
		Fset: fset,
 | 
						|
		Err:  err,
 | 
						|
		Name: filePath,
 | 
						|
	}
 | 
						|
	if err != nil {
 | 
						|
		c.log.Warnf("Can't parse AST of %s: %s", filePath, err)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func LoadFromFiles(files []string, log logutils.Log) (*Cache, error) { //nolint:unparam
 | 
						|
	c := NewCache(log)
 | 
						|
 | 
						|
	fset := token.NewFileSet()
 | 
						|
	for _, filePath := range files {
 | 
						|
		filePath = filepath.Clean(filePath)
 | 
						|
		c.parseFile(filePath, fset)
 | 
						|
	}
 | 
						|
 | 
						|
	c.prepareValidFiles()
 | 
						|
	return c, nil
 | 
						|
}
 |