1
2
3
4
5 package packages
6
7
8
9 import (
10 "context"
11 "encoding/json"
12 "errors"
13 "fmt"
14 "go/ast"
15 "go/parser"
16 "go/scanner"
17 "go/token"
18 "go/types"
19 "io"
20 "log"
21 "os"
22 "path/filepath"
23 "runtime"
24 "strings"
25 "sync"
26 "time"
27
28 "golang.org/x/sync/errgroup"
29
30 "golang.org/x/tools/go/gcexportdata"
31 "golang.org/x/tools/internal/gocommand"
32 "golang.org/x/tools/internal/packagesinternal"
33 "golang.org/x/tools/internal/typesinternal"
34 "golang.org/x/tools/internal/versions"
35 )
36
37
38
39
40
41
42
43
44 type LoadMode int
45
46 const (
47
48 NeedName LoadMode = 1 << iota
49
50
51 NeedFiles
52
53
54 NeedCompiledGoFiles
55
56
57
58 NeedImports
59
60
61 NeedDeps
62
63
64 NeedExportFile
65
66
67 NeedTypes
68
69
70 NeedSyntax
71
72
73 NeedTypesInfo
74
75
76 NeedTypesSizes
77
78
79 needInternalDepsErrors
80
81
82
83 needInternalForTest
84
85
86
87 typecheckCgo
88
89
90 NeedModule
91
92
93 NeedEmbedFiles
94
95
96 NeedEmbedPatterns
97 )
98
99 const (
100
101
102 LoadFiles = NeedName | NeedFiles | NeedCompiledGoFiles
103
104
105
106 LoadImports = LoadFiles | NeedImports
107
108
109
110 LoadTypes = LoadImports | NeedTypes | NeedTypesSizes
111
112
113
114 LoadSyntax = LoadTypes | NeedSyntax | NeedTypesInfo
115
116
117
118 LoadAllSyntax = LoadSyntax | NeedDeps
119
120
121 NeedExportsFile = NeedExportFile
122 )
123
124
125
126
127 type Config struct {
128
129 Mode LoadMode
130
131
132
133
134 Context context.Context
135
136
137
138
139
140 Logf func(format string, args ...interface{})
141
142
143
144
145 Dir string
146
147
148
149
150
151
152
153
154
155 Env []string
156
157
158 gocmdRunner *gocommand.Runner
159
160
161
162 BuildFlags []string
163
164
165 modFile string
166
167
168 modFlag string
169
170
171
172 Fset *token.FileSet
173
174
175
176
177
178
179
180
181
182
183
184
185
186 ParseFile func(fset *token.FileSet, filename string, src []byte) (*ast.File, error)
187
188
189
190
191
192
193
194
195
196
197
198
199
200 Tests bool
201
202
203
204
205
206
207
208 Overlay map[string][]byte
209 }
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225 func Load(cfg *Config, patterns ...string) ([]*Package, error) {
226 ld := newLoader(cfg)
227 response, external, err := defaultDriver(&ld.Config, patterns...)
228 if err != nil {
229 return nil, err
230 }
231
232 ld.sizes = types.SizesFor(response.Compiler, response.Arch)
233 if ld.sizes == nil && ld.Config.Mode&(NeedTypes|NeedTypesSizes|NeedTypesInfo) != 0 {
234
235 if external {
236
237
238
239 ld.sizes = types.SizesFor("gc", runtime.GOARCH)
240 if ld.sizes == nil {
241 ld.sizes = types.SizesFor("gc", "amd64")
242 }
243 } else {
244
245
246 return nil, fmt.Errorf("can't determine type sizes for compiler %q on GOARCH %q",
247 response.Compiler, response.Arch)
248 }
249 }
250
251 return ld.refine(response)
252 }
253
254
255
256
257
258
259 func defaultDriver(cfg *Config, patterns ...string) (*DriverResponse, bool, error) {
260 const (
261
262
263 windowsArgMax = 32767
264
265
266 maxEnvSize = 16384
267
268
269
270
271
272 safeArgMax = windowsArgMax - maxEnvSize
273 )
274 chunks, err := splitIntoChunks(patterns, safeArgMax)
275 if err != nil {
276 return nil, false, err
277 }
278
279 if driver := findExternalDriver(cfg); driver != nil {
280 response, err := callDriverOnChunks(driver, cfg, chunks)
281 if err != nil {
282 return nil, false, err
283 } else if !response.NotHandled {
284 return response, true, nil
285 }
286
287 }
288
289 response, err := callDriverOnChunks(goListDriver, cfg, chunks)
290 if err != nil {
291 return nil, false, err
292 }
293 return response, false, err
294 }
295
296
297
298 func splitIntoChunks(patterns []string, argMax int) ([][]string, error) {
299 if argMax <= 0 {
300 return nil, errors.New("failed to split patterns into chunks, negative safe argMax value")
301 }
302 var chunks [][]string
303 charsInChunk := 0
304 nextChunkStart := 0
305 for i, v := range patterns {
306 vChars := len(v)
307 if vChars > argMax {
308
309 return nil, errors.New("failed to split patterns into chunks, a pattern is too long")
310 }
311 charsInChunk += vChars + 1
312 if charsInChunk > argMax {
313 chunks = append(chunks, patterns[nextChunkStart:i])
314 nextChunkStart = i
315 charsInChunk = vChars
316 }
317 }
318
319 if nextChunkStart < len(patterns) {
320 chunks = append(chunks, patterns[nextChunkStart:])
321 }
322 return chunks, nil
323 }
324
325 func callDriverOnChunks(driver driver, cfg *Config, chunks [][]string) (*DriverResponse, error) {
326 if len(chunks) == 0 {
327 return driver(cfg)
328 }
329 responses := make([]*DriverResponse, len(chunks))
330 errNotHandled := errors.New("driver returned NotHandled")
331 var g errgroup.Group
332 for i, chunk := range chunks {
333 i := i
334 chunk := chunk
335 g.Go(func() (err error) {
336 responses[i], err = driver(cfg, chunk...)
337 if responses[i] != nil && responses[i].NotHandled {
338 err = errNotHandled
339 }
340 return err
341 })
342 }
343 if err := g.Wait(); err != nil {
344 if errors.Is(err, errNotHandled) {
345 return &DriverResponse{NotHandled: true}, nil
346 }
347 return nil, err
348 }
349 return mergeResponses(responses...), nil
350 }
351
352 func mergeResponses(responses ...*DriverResponse) *DriverResponse {
353 if len(responses) == 0 {
354 return nil
355 }
356 response := newDeduper()
357 response.dr.NotHandled = false
358 response.dr.Compiler = responses[0].Compiler
359 response.dr.Arch = responses[0].Arch
360 response.dr.GoVersion = responses[0].GoVersion
361 for _, v := range responses {
362 response.addAll(v)
363 }
364 return response.dr
365 }
366
367
368 type Package struct {
369
370
371
372
373
374
375 ID string
376
377
378 Name string
379
380
381 PkgPath string
382
383
384
385 Errors []Error
386
387
388 TypeErrors []types.Error
389
390
391
392
393
394 GoFiles []string
395
396
397
398
399 CompiledGoFiles []string
400
401
402
403 OtherFiles []string
404
405
406
407 EmbedFiles []string
408
409
410
411 EmbedPatterns []string
412
413
414
415
416 IgnoredFiles []string
417
418
419
420 ExportFile string
421
422
423
424 Imports map[string]*Package
425
426
427
428
429
430
431
432
433
434 Types *types.Package
435
436
437
438 Fset *token.FileSet
439
440
441
442 IllTyped bool
443
444
445
446
447
448
449
450
451
452 Syntax []*ast.File
453
454
455
456 TypesInfo *types.Info
457
458
459 TypesSizes types.Sizes
460
461
462 forTest string
463
464
465 depsErrors []*packagesinternal.PackageError
466
467
468 Module *Module
469 }
470
471
472 type Module struct {
473 Path string
474 Version string
475 Replace *Module
476 Time *time.Time
477 Main bool
478 Indirect bool
479 Dir string
480 GoMod string
481 GoVersion string
482 Error *ModuleError
483 }
484
485
486 type ModuleError struct {
487 Err string
488 }
489
490 func init() {
491 packagesinternal.GetForTest = func(p interface{}) string {
492 return p.(*Package).forTest
493 }
494 packagesinternal.GetDepsErrors = func(p interface{}) []*packagesinternal.PackageError {
495 return p.(*Package).depsErrors
496 }
497 packagesinternal.SetModFile = func(config interface{}, value string) {
498 config.(*Config).modFile = value
499 }
500 packagesinternal.SetModFlag = func(config interface{}, value string) {
501 config.(*Config).modFlag = value
502 }
503 packagesinternal.TypecheckCgo = int(typecheckCgo)
504 packagesinternal.DepsErrors = int(needInternalDepsErrors)
505 packagesinternal.ForTest = int(needInternalForTest)
506 }
507
508
509 type Error struct {
510 Pos string
511 Msg string
512 Kind ErrorKind
513 }
514
515
516
517
518 type ErrorKind int
519
520 const (
521 UnknownError ErrorKind = iota
522 ListError
523 ParseError
524 TypeError
525 )
526
527 func (err Error) Error() string {
528 pos := err.Pos
529 if pos == "" {
530 pos = "-"
531 }
532 return pos + ": " + err.Msg
533 }
534
535
536
537
538
539
540 type flatPackage struct {
541 ID string
542 Name string `json:",omitempty"`
543 PkgPath string `json:",omitempty"`
544 Errors []Error `json:",omitempty"`
545 GoFiles []string `json:",omitempty"`
546 CompiledGoFiles []string `json:",omitempty"`
547 OtherFiles []string `json:",omitempty"`
548 EmbedFiles []string `json:",omitempty"`
549 EmbedPatterns []string `json:",omitempty"`
550 IgnoredFiles []string `json:",omitempty"`
551 ExportFile string `json:",omitempty"`
552 Imports map[string]string `json:",omitempty"`
553 }
554
555
556
557
558
559
560
561
562
563
564 func (p *Package) MarshalJSON() ([]byte, error) {
565 flat := &flatPackage{
566 ID: p.ID,
567 Name: p.Name,
568 PkgPath: p.PkgPath,
569 Errors: p.Errors,
570 GoFiles: p.GoFiles,
571 CompiledGoFiles: p.CompiledGoFiles,
572 OtherFiles: p.OtherFiles,
573 EmbedFiles: p.EmbedFiles,
574 EmbedPatterns: p.EmbedPatterns,
575 IgnoredFiles: p.IgnoredFiles,
576 ExportFile: p.ExportFile,
577 }
578 if len(p.Imports) > 0 {
579 flat.Imports = make(map[string]string, len(p.Imports))
580 for path, ipkg := range p.Imports {
581 flat.Imports[path] = ipkg.ID
582 }
583 }
584 return json.Marshal(flat)
585 }
586
587
588
589 func (p *Package) UnmarshalJSON(b []byte) error {
590 flat := &flatPackage{}
591 if err := json.Unmarshal(b, &flat); err != nil {
592 return err
593 }
594 *p = Package{
595 ID: flat.ID,
596 Name: flat.Name,
597 PkgPath: flat.PkgPath,
598 Errors: flat.Errors,
599 GoFiles: flat.GoFiles,
600 CompiledGoFiles: flat.CompiledGoFiles,
601 OtherFiles: flat.OtherFiles,
602 EmbedFiles: flat.EmbedFiles,
603 EmbedPatterns: flat.EmbedPatterns,
604 ExportFile: flat.ExportFile,
605 }
606 if len(flat.Imports) > 0 {
607 p.Imports = make(map[string]*Package, len(flat.Imports))
608 for path, id := range flat.Imports {
609 p.Imports[path] = &Package{ID: id}
610 }
611 }
612 return nil
613 }
614
615 func (p *Package) String() string { return p.ID }
616
617
618 type loaderPackage struct {
619 *Package
620 importErrors map[string]error
621 loadOnce sync.Once
622 color uint8
623 needsrc bool
624 needtypes bool
625 initial bool
626 goVersion int
627 }
628
629
630 type loader struct {
631 pkgs map[string]*loaderPackage
632 Config
633 sizes types.Sizes
634 parseCache map[string]*parseValue
635 parseCacheMu sync.Mutex
636 exportMu sync.Mutex
637
638
639
640
641
642
643
644 requestedMode LoadMode
645 }
646
647 type parseValue struct {
648 f *ast.File
649 err error
650 ready chan struct{}
651 }
652
653 func newLoader(cfg *Config) *loader {
654 ld := &loader{
655 parseCache: map[string]*parseValue{},
656 }
657 if cfg != nil {
658 ld.Config = *cfg
659
660 ld.Config.Logf = cfg.Logf
661 }
662 if ld.Config.Logf == nil {
663
664
665 if debug {
666 ld.Config.Logf = log.Printf
667 } else {
668 ld.Config.Logf = func(format string, args ...interface{}) {}
669 }
670 }
671 if ld.Config.Mode == 0 {
672 ld.Config.Mode = NeedName | NeedFiles | NeedCompiledGoFiles
673 }
674 if ld.Config.Env == nil {
675 ld.Config.Env = os.Environ()
676 }
677 if ld.Config.gocmdRunner == nil {
678 ld.Config.gocmdRunner = &gocommand.Runner{}
679 }
680 if ld.Context == nil {
681 ld.Context = context.Background()
682 }
683 if ld.Dir == "" {
684 if dir, err := os.Getwd(); err == nil {
685 ld.Dir = dir
686 }
687 }
688
689
690 ld.requestedMode = ld.Mode
691 ld.Mode = impliedLoadMode(ld.Mode)
692
693 if ld.Mode&NeedTypes != 0 || ld.Mode&NeedSyntax != 0 {
694 if ld.Fset == nil {
695 ld.Fset = token.NewFileSet()
696 }
697
698
699
700 if ld.ParseFile == nil {
701 ld.ParseFile = func(fset *token.FileSet, filename string, src []byte) (*ast.File, error) {
702 const mode = parser.AllErrors | parser.ParseComments
703 return parser.ParseFile(fset, filename, src, mode)
704 }
705 }
706 }
707
708 return ld
709 }
710
711
712
713 func (ld *loader) refine(response *DriverResponse) ([]*Package, error) {
714 roots := response.Roots
715 rootMap := make(map[string]int, len(roots))
716 for i, root := range roots {
717 rootMap[root] = i
718 }
719 ld.pkgs = make(map[string]*loaderPackage)
720
721 var initial = make([]*loaderPackage, len(roots))
722 for _, pkg := range response.Packages {
723 rootIndex := -1
724 if i, found := rootMap[pkg.ID]; found {
725 rootIndex = i
726 }
727
728
729
730 exportDataInvalid := len(ld.Overlay) > 0 || pkg.ExportFile == "" && pkg.PkgPath != "unsafe"
731
732
733 needtypes := (ld.Mode&NeedTypes|NeedTypesInfo != 0 && (rootIndex >= 0 || ld.Mode&NeedDeps != 0))
734
735
736 needsrc := ((ld.Mode&(NeedSyntax|NeedTypesInfo) != 0 && (rootIndex >= 0 || ld.Mode&NeedDeps != 0)) ||
737
738
739 (ld.Mode&(NeedTypes|NeedTypesInfo) != 0 && exportDataInvalid)) && pkg.PkgPath != "unsafe"
740 lpkg := &loaderPackage{
741 Package: pkg,
742 needtypes: needtypes,
743 needsrc: needsrc,
744 goVersion: response.GoVersion,
745 }
746 ld.pkgs[lpkg.ID] = lpkg
747 if rootIndex >= 0 {
748 initial[rootIndex] = lpkg
749 lpkg.initial = true
750 }
751 }
752 for i, root := range roots {
753 if initial[i] == nil {
754 return nil, fmt.Errorf("root package %v is missing", root)
755 }
756 }
757
758 if ld.Mode&NeedImports != 0 {
759
760
761 const (
762 white = 0
763 grey = 1
764 black = 2
765 )
766
767
768
769
770
771
772
773
774
775
776
777
778 var stack []*loaderPackage
779 var visit func(lpkg *loaderPackage) bool
780 visit = func(lpkg *loaderPackage) bool {
781 switch lpkg.color {
782 case black:
783 return lpkg.needsrc
784 case grey:
785 panic("internal error: grey node")
786 }
787 lpkg.color = grey
788 stack = append(stack, lpkg)
789 stubs := lpkg.Imports
790 lpkg.Imports = make(map[string]*Package, len(stubs))
791 for importPath, ipkg := range stubs {
792 var importErr error
793 imp := ld.pkgs[ipkg.ID]
794 if imp == nil {
795
796 importErr = fmt.Errorf("missing package: %q", ipkg.ID)
797 } else if imp.color == grey {
798 importErr = fmt.Errorf("import cycle: %s", stack)
799 }
800 if importErr != nil {
801 if lpkg.importErrors == nil {
802 lpkg.importErrors = make(map[string]error)
803 }
804 lpkg.importErrors[importPath] = importErr
805 continue
806 }
807
808 if visit(imp) {
809 lpkg.needsrc = true
810 }
811 lpkg.Imports[importPath] = imp.Package
812 }
813
814
815
816 if lpkg.needsrc && ld.Mode&NeedTypes != 0 {
817 for _, ipkg := range lpkg.Imports {
818 ld.pkgs[ipkg.ID].needtypes = true
819 }
820 }
821
822
823
824 if ld.Mode&NeedTypesSizes != 0 {
825 lpkg.TypesSizes = ld.sizes
826 }
827 stack = stack[:len(stack)-1]
828 lpkg.color = black
829
830 return lpkg.needsrc
831 }
832
833
834 for _, lpkg := range initial {
835 visit(lpkg)
836 }
837
838 } else {
839
840
841 for _, lpkg := range initial {
842 lpkg.Imports = nil
843 }
844 }
845
846
847
848 if ld.Mode&NeedTypes != 0 || ld.Mode&NeedSyntax != 0 {
849 var wg sync.WaitGroup
850 for _, lpkg := range initial {
851 wg.Add(1)
852 go func(lpkg *loaderPackage) {
853 ld.loadRecursive(lpkg)
854 wg.Done()
855 }(lpkg)
856 }
857 wg.Wait()
858 }
859
860
861
862 if err := ld.Context.Err(); err != nil {
863 return nil, err
864 }
865
866 result := make([]*Package, len(initial))
867 for i, lpkg := range initial {
868 result[i] = lpkg.Package
869 }
870 for i := range ld.pkgs {
871
872
873 if ld.requestedMode&NeedName == 0 {
874 ld.pkgs[i].Name = ""
875 ld.pkgs[i].PkgPath = ""
876 }
877 if ld.requestedMode&NeedFiles == 0 {
878 ld.pkgs[i].GoFiles = nil
879 ld.pkgs[i].OtherFiles = nil
880 ld.pkgs[i].IgnoredFiles = nil
881 }
882 if ld.requestedMode&NeedEmbedFiles == 0 {
883 ld.pkgs[i].EmbedFiles = nil
884 }
885 if ld.requestedMode&NeedEmbedPatterns == 0 {
886 ld.pkgs[i].EmbedPatterns = nil
887 }
888 if ld.requestedMode&NeedCompiledGoFiles == 0 {
889 ld.pkgs[i].CompiledGoFiles = nil
890 }
891 if ld.requestedMode&NeedImports == 0 {
892 ld.pkgs[i].Imports = nil
893 }
894 if ld.requestedMode&NeedExportFile == 0 {
895 ld.pkgs[i].ExportFile = ""
896 }
897 if ld.requestedMode&NeedTypes == 0 {
898 ld.pkgs[i].Types = nil
899 ld.pkgs[i].Fset = nil
900 ld.pkgs[i].IllTyped = false
901 }
902 if ld.requestedMode&NeedSyntax == 0 {
903 ld.pkgs[i].Syntax = nil
904 }
905 if ld.requestedMode&NeedTypesInfo == 0 {
906 ld.pkgs[i].TypesInfo = nil
907 }
908 if ld.requestedMode&NeedTypesSizes == 0 {
909 ld.pkgs[i].TypesSizes = nil
910 }
911 if ld.requestedMode&NeedModule == 0 {
912 ld.pkgs[i].Module = nil
913 }
914 }
915
916 return result, nil
917 }
918
919
920
921
922
923 func (ld *loader) loadRecursive(lpkg *loaderPackage) {
924 lpkg.loadOnce.Do(func() {
925
926 var wg sync.WaitGroup
927 for _, ipkg := range lpkg.Imports {
928 imp := ld.pkgs[ipkg.ID]
929 wg.Add(1)
930 go func(imp *loaderPackage) {
931 ld.loadRecursive(imp)
932 wg.Done()
933 }(imp)
934 }
935 wg.Wait()
936 ld.loadPackage(lpkg)
937 })
938 }
939
940
941
942
943
944 func (ld *loader) loadPackage(lpkg *loaderPackage) {
945 if lpkg.PkgPath == "unsafe" {
946
947 lpkg.Types = types.Unsafe
948 lpkg.Fset = ld.Fset
949 lpkg.Syntax = []*ast.File{}
950 lpkg.TypesInfo = new(types.Info)
951 lpkg.TypesSizes = ld.sizes
952 return
953 }
954
955
956
957
958 lpkg.Types = types.NewPackage(lpkg.PkgPath, lpkg.Name)
959 lpkg.Fset = ld.Fset
960
961
962
963
964
965 if ld.Context.Err() != nil {
966 return
967 }
968
969
970
971
972
973
974
975
976 if !lpkg.needtypes && !lpkg.needsrc {
977 return
978 }
979 if !lpkg.needsrc {
980 if err := ld.loadFromExportData(lpkg); err != nil {
981 lpkg.Errors = append(lpkg.Errors, Error{
982 Pos: "-",
983 Msg: err.Error(),
984 Kind: UnknownError,
985 })
986 }
987 return
988 }
989
990 appendError := func(err error) {
991
992 var errs []Error
993 switch err := err.(type) {
994 case Error:
995
996 errs = append(errs, err)
997
998 case *os.PathError:
999
1000 errs = append(errs, Error{
1001 Pos: err.Path + ":1",
1002 Msg: err.Err.Error(),
1003 Kind: ParseError,
1004 })
1005
1006 case scanner.ErrorList:
1007
1008 for _, err := range err {
1009 errs = append(errs, Error{
1010 Pos: err.Pos.String(),
1011 Msg: err.Msg,
1012 Kind: ParseError,
1013 })
1014 }
1015
1016 case types.Error:
1017
1018 lpkg.TypeErrors = append(lpkg.TypeErrors, err)
1019 errs = append(errs, Error{
1020 Pos: err.Fset.Position(err.Pos).String(),
1021 Msg: err.Msg,
1022 Kind: TypeError,
1023 })
1024
1025 default:
1026
1027 errs = append(errs, Error{
1028 Pos: "-",
1029 Msg: err.Error(),
1030 Kind: UnknownError,
1031 })
1032
1033
1034 log.Printf("internal error: error %q (%T) without position", err, err)
1035 }
1036
1037 lpkg.Errors = append(lpkg.Errors, errs...)
1038 }
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056 var runtimeVersion int
1057 if _, err := fmt.Sscanf(runtime.Version(), "go1.%d", &runtimeVersion); err == nil && runtimeVersion < lpkg.goVersion {
1058 defer func() {
1059 if len(lpkg.Errors) > 0 {
1060 appendError(Error{
1061 Pos: "-",
1062 Msg: fmt.Sprintf("This application uses version go1.%d of the source-processing packages but runs version go1.%d of 'go list'. It may fail to process source files that rely on newer language features. If so, rebuild the application using a newer version of Go.", runtimeVersion, lpkg.goVersion),
1063 Kind: UnknownError,
1064 })
1065 }
1066 }()
1067 }
1068
1069 if ld.Config.Mode&NeedTypes != 0 && len(lpkg.CompiledGoFiles) == 0 && lpkg.ExportFile != "" {
1070
1071
1072 appendError(Error{"-", fmt.Sprintf("sources missing for package %s", lpkg.ID), ParseError})
1073 _ = ld.loadFromExportData(lpkg)
1074
1075 return
1076 }
1077
1078 files, errs := ld.parseFiles(lpkg.CompiledGoFiles)
1079 for _, err := range errs {
1080 appendError(err)
1081 }
1082
1083 lpkg.Syntax = files
1084 if ld.Config.Mode&NeedTypes == 0 {
1085 return
1086 }
1087
1088
1089
1090
1091 if ld.Context.Err() != nil {
1092 return
1093 }
1094
1095 lpkg.TypesInfo = &types.Info{
1096 Types: make(map[ast.Expr]types.TypeAndValue),
1097 Defs: make(map[*ast.Ident]types.Object),
1098 Uses: make(map[*ast.Ident]types.Object),
1099 Implicits: make(map[ast.Node]types.Object),
1100 Instances: make(map[*ast.Ident]types.Instance),
1101 Scopes: make(map[ast.Node]*types.Scope),
1102 Selections: make(map[*ast.SelectorExpr]*types.Selection),
1103 }
1104 versions.InitFileVersions(lpkg.TypesInfo)
1105 lpkg.TypesSizes = ld.sizes
1106
1107 importer := importerFunc(func(path string) (*types.Package, error) {
1108 if path == "unsafe" {
1109 return types.Unsafe, nil
1110 }
1111
1112
1113 ipkg := lpkg.Imports[path]
1114 if ipkg == nil {
1115 if err := lpkg.importErrors[path]; err != nil {
1116 return nil, err
1117 }
1118
1119
1120
1121
1122 return nil, fmt.Errorf("no metadata for %s", path)
1123 }
1124
1125 if ipkg.Types != nil && ipkg.Types.Complete() {
1126 return ipkg.Types, nil
1127 }
1128 log.Fatalf("internal error: package %q without types was imported from %q", path, lpkg)
1129 panic("unreachable")
1130 })
1131
1132
1133 tc := &types.Config{
1134 Importer: importer,
1135
1136
1137
1138
1139 IgnoreFuncBodies: ld.Mode&NeedDeps == 0 && !lpkg.initial,
1140
1141 Error: appendError,
1142 Sizes: ld.sizes,
1143 }
1144 if lpkg.Module != nil && lpkg.Module.GoVersion != "" {
1145 tc.GoVersion = "go" + lpkg.Module.GoVersion
1146 }
1147 if (ld.Mode & typecheckCgo) != 0 {
1148 if !typesinternal.SetUsesCgo(tc) {
1149 appendError(Error{
1150 Msg: "typecheckCgo requires Go 1.15+",
1151 Kind: ListError,
1152 })
1153 return
1154 }
1155 }
1156
1157 typErr := types.NewChecker(tc, ld.Fset, lpkg.Types, lpkg.TypesInfo).Files(lpkg.Syntax)
1158 lpkg.importErrors = nil
1159
1160
1161
1162
1163
1164 if typErr != nil && len(lpkg.Errors) == 0 && len(lpkg.Syntax) > 0 {
1165 if msg := typErr.Error(); strings.HasPrefix(msg, "package requires newer Go version") {
1166 appendError(types.Error{
1167 Fset: ld.Fset,
1168 Pos: lpkg.Syntax[0].Package,
1169 Msg: msg,
1170 })
1171 }
1172 }
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182 if tc.FakeImportC {
1183 outer:
1184 for _, f := range lpkg.Syntax {
1185 for _, imp := range f.Imports {
1186 if imp.Path.Value == `"C"` {
1187 err := types.Error{Fset: ld.Fset, Pos: imp.Pos(), Msg: `import "C" ignored`}
1188 appendError(err)
1189 break outer
1190 }
1191 }
1192 }
1193 }
1194
1195
1196
1197 if typErr != nil && len(lpkg.Errors) == 0 {
1198 appendError(typErr)
1199 }
1200
1201
1202 illTyped := len(lpkg.Errors) > 0
1203 if !illTyped {
1204 for _, imp := range lpkg.Imports {
1205 if imp.IllTyped {
1206 illTyped = true
1207 break
1208 }
1209 }
1210 }
1211 lpkg.IllTyped = illTyped
1212 }
1213
1214
1215
1216 type importerFunc func(path string) (*types.Package, error)
1217
1218 func (f importerFunc) Import(path string) (*types.Package, error) { return f(path) }
1219
1220
1221
1222 var ioLimit = make(chan bool, 20)
1223
1224 func (ld *loader) parseFile(filename string) (*ast.File, error) {
1225 ld.parseCacheMu.Lock()
1226 v, ok := ld.parseCache[filename]
1227 if ok {
1228
1229 ld.parseCacheMu.Unlock()
1230 <-v.ready
1231 } else {
1232
1233 v = &parseValue{ready: make(chan struct{})}
1234 ld.parseCache[filename] = v
1235 ld.parseCacheMu.Unlock()
1236
1237 var src []byte
1238 for f, contents := range ld.Config.Overlay {
1239 if sameFile(f, filename) {
1240 src = contents
1241 }
1242 }
1243 var err error
1244 if src == nil {
1245 ioLimit <- true
1246 src, err = os.ReadFile(filename)
1247 <-ioLimit
1248 }
1249 if err != nil {
1250 v.err = err
1251 } else {
1252 v.f, v.err = ld.ParseFile(ld.Fset, filename, src)
1253 }
1254
1255 close(v.ready)
1256 }
1257 return v.f, v.err
1258 }
1259
1260
1261
1262
1263
1264
1265
1266 func (ld *loader) parseFiles(filenames []string) ([]*ast.File, []error) {
1267 var wg sync.WaitGroup
1268 n := len(filenames)
1269 parsed := make([]*ast.File, n)
1270 errors := make([]error, n)
1271 for i, file := range filenames {
1272 wg.Add(1)
1273 go func(i int, filename string) {
1274 parsed[i], errors[i] = ld.parseFile(filename)
1275 wg.Done()
1276 }(i, file)
1277 }
1278 wg.Wait()
1279
1280
1281 var o int
1282 for _, f := range parsed {
1283 if f != nil {
1284 parsed[o] = f
1285 o++
1286 }
1287 }
1288 parsed = parsed[:o]
1289
1290 o = 0
1291 for _, err := range errors {
1292 if err != nil {
1293 errors[o] = err
1294 o++
1295 }
1296 }
1297 errors = errors[:o]
1298
1299 return parsed, errors
1300 }
1301
1302
1303
1304 func sameFile(x, y string) bool {
1305 if x == y {
1306
1307
1308
1309
1310
1311
1312 return true
1313 }
1314 if strings.EqualFold(filepath.Base(x), filepath.Base(y)) {
1315 if xi, err := os.Stat(x); err == nil {
1316 if yi, err := os.Stat(y); err == nil {
1317 return os.SameFile(xi, yi)
1318 }
1319 }
1320 }
1321 return false
1322 }
1323
1324
1325
1326
1327 func (ld *loader) loadFromExportData(lpkg *loaderPackage) error {
1328 if lpkg.PkgPath == "" {
1329 log.Fatalf("internal error: Package %s has no PkgPath", lpkg)
1330 }
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344 ld.exportMu.Lock()
1345 defer ld.exportMu.Unlock()
1346
1347 if tpkg := lpkg.Types; tpkg != nil && tpkg.Complete() {
1348 return nil
1349 }
1350
1351 lpkg.IllTyped = true
1352
1353 if lpkg.ExportFile == "" {
1354
1355 return fmt.Errorf("no export data file")
1356 }
1357 f, err := os.Open(lpkg.ExportFile)
1358 if err != nil {
1359 return err
1360 }
1361 defer f.Close()
1362
1363
1364
1365
1366
1367
1368
1369 r, err := gcexportdata.NewReader(f)
1370 if err != nil {
1371 return fmt.Errorf("reading %s: %v", lpkg.ExportFile, err)
1372 }
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395 view := make(map[string]*types.Package)
1396 seen := make(map[*loaderPackage]bool)
1397 var visit func(pkgs map[string]*Package)
1398 visit = func(pkgs map[string]*Package) {
1399 for _, p := range pkgs {
1400 lpkg := ld.pkgs[p.ID]
1401 if !seen[lpkg] {
1402 seen[lpkg] = true
1403 view[lpkg.PkgPath] = lpkg.Types
1404 visit(lpkg.Imports)
1405 }
1406 }
1407 }
1408 visit(lpkg.Imports)
1409
1410 viewLen := len(view) + 1
1411
1412
1413 tpkg, err := gcexportdata.Read(r, ld.Fset, view, lpkg.PkgPath)
1414 if err != nil {
1415 return fmt.Errorf("reading %s: %v", lpkg.ExportFile, err)
1416 }
1417 if _, ok := view["go.shape"]; ok {
1418
1419
1420 viewLen++
1421 }
1422 if viewLen != len(view) {
1423 log.Panicf("golang.org/x/tools/go/packages: unexpected new packages during load of %s", lpkg.PkgPath)
1424 }
1425
1426 lpkg.Types = tpkg
1427 lpkg.IllTyped = false
1428 return nil
1429 }
1430
1431
1432 func impliedLoadMode(loadMode LoadMode) LoadMode {
1433 if loadMode&(NeedDeps|NeedTypes|NeedTypesInfo) != 0 {
1434
1435 loadMode |= NeedImports
1436 }
1437
1438 return loadMode
1439 }
1440
1441 func usesExportData(cfg *Config) bool {
1442 return cfg.Mode&NeedExportFile != 0 || cfg.Mode&NeedTypes != 0 && cfg.Mode&NeedDeps == 0
1443 }
1444
1445 var _ interface{} = io.Discard
1446
View as plain text