Code refactoring for bpa operator
[icn.git] / cmd / bpa-operator / vendor / golang.org / x / tools / go / packages / golist_overlay.go
1 package packages
2
3 import (
4         "go/parser"
5         "go/token"
6         "path/filepath"
7         "strconv"
8         "strings"
9 )
10
11 // processGolistOverlay provides rudimentary support for adding
12 // files that don't exist on disk to an overlay. The results can be
13 // sometimes incorrect.
14 // TODO(matloob): Handle unsupported cases, including the following:
15 // - test files
16 // - adding test and non-test files to test variants of packages
17 // - determining the correct package to add given a new import path
18 // - creating packages that don't exist
19 func processGolistOverlay(cfg *Config, response *driverResponse) (modifiedPkgs, needPkgs []string, err error) {
20         havePkgs := make(map[string]string) // importPath -> non-test package ID
21         needPkgsSet := make(map[string]bool)
22         modifiedPkgsSet := make(map[string]bool)
23
24         for _, pkg := range response.Packages {
25                 // This is an approximation of import path to id. This can be
26                 // wrong for tests, vendored packages, and a number of other cases.
27                 havePkgs[pkg.PkgPath] = pkg.ID
28         }
29
30 outer:
31         for path, contents := range cfg.Overlay {
32                 base := filepath.Base(path)
33                 if strings.HasSuffix(path, "_test.go") {
34                         // Overlays don't support adding new test files yet.
35                         // TODO(matloob): support adding new test files.
36                         continue
37                 }
38                 dir := filepath.Dir(path)
39                 for _, pkg := range response.Packages {
40                         var dirContains, fileExists bool
41                         for _, f := range pkg.GoFiles {
42                                 if sameFile(filepath.Dir(f), dir) {
43                                         dirContains = true
44                                 }
45                                 if filepath.Base(f) == base {
46                                         fileExists = true
47                                 }
48                         }
49                         if dirContains {
50                                 if !fileExists {
51                                         pkg.GoFiles = append(pkg.GoFiles, path) // TODO(matloob): should the file just be added to GoFiles?
52                                         pkg.CompiledGoFiles = append(pkg.CompiledGoFiles, path)
53                                         modifiedPkgsSet[pkg.ID] = true
54                                 }
55                                 imports, err := extractImports(path, contents)
56                                 if err != nil {
57                                         // Let the parser or type checker report errors later.
58                                         continue outer
59                                 }
60                                 for _, imp := range imports {
61                                         _, found := pkg.Imports[imp]
62                                         if !found {
63                                                 needPkgsSet[imp] = true
64                                                 // TODO(matloob): Handle cases when the following block isn't correct.
65                                                 // These include imports of test variants, imports of vendored packages, etc.
66                                                 id, ok := havePkgs[imp]
67                                                 if !ok {
68                                                         id = imp
69                                                 }
70                                                 pkg.Imports[imp] = &Package{ID: id}
71                                         }
72                                 }
73                                 continue outer
74                         }
75                 }
76         }
77
78         needPkgs = make([]string, 0, len(needPkgsSet))
79         for pkg := range needPkgsSet {
80                 needPkgs = append(needPkgs, pkg)
81         }
82         modifiedPkgs = make([]string, 0, len(modifiedPkgsSet))
83         for pkg := range modifiedPkgsSet {
84                 modifiedPkgs = append(modifiedPkgs, pkg)
85         }
86         return modifiedPkgs, needPkgs, err
87 }
88
89 func extractImports(filename string, contents []byte) ([]string, error) {
90         f, err := parser.ParseFile(token.NewFileSet(), filename, contents, parser.ImportsOnly) // TODO(matloob): reuse fileset?
91         if err != nil {
92                 return nil, err
93         }
94         var res []string
95         for _, imp := range f.Imports {
96                 quotedPath := imp.Path.Value
97                 path, err := strconv.Unquote(quotedPath)
98                 if err != nil {
99                         return nil, err
100                 }
101                 res = append(res, path)
102         }
103         return res, nil
104 }