Repository: daixiang0/gci
Pull request #138 (2023-02-16 01:01:45)

remove hardcoded stdlib packages
currently the standard list is hardcoded, we can load this from x/tools/go/packages, which is already a dependency.
This means whenever for the same release, different toolchains install could have different the package list. So we don't have to manually maintain this list to include everything stdlib

unit tested

daixiang0: I have a question: if we use 1.9 toolchain, users use 1.10, the newer packages cannot be detected, is it right? If so, we can not use this way.
xytan0056: > I have a question: if we use 1.9 toolchain, users use 1.10, the newer packages cannot be detected, is it right? If so, we can not use this way.

indeed. Maybe I need to reword the PR. But wouldn't we already have this issue with current implementation? The hardcoded list cannot cover all packages, so might as well make it accustomed to users' toolchains. e.g.
```
func main() {
        pkgs, err := packages.Load(nil, "std")
        if err != nil {
                panic(err)
        }

        fmt.Println(pkgs)
        // go1.16.1 run ./... => 212
        // go1.18.3 run ./... => 233
        // go1.19.4 run ./... => 241
        fmt.Println(len(pkgs)) 
}
```
I believe when users run `go1.x.x install` it'll refer to that version
daixiang0: You are right, please fix CI then we can get it.
daixiang0: @xytan0056 thanks for your contribution!

Patch:
diff --git a/pkg/section/parser.go b/pkg/section/parser.go
index 9834dcd..57e5a35 100644
--- a/pkg/section/parser.go
+++ b/pkg/section/parser.go
@@ -22,7 +22,7 @@ func Parse(data []string) (SectionList, error) {
 		if s == "default" {
 			list = append(list, Default{})
 		} else if s == "standard" {
-			list = append(list, Standard{})
+			list = append(list, NewStandard())
 		} else if s == "newline" {
 			list = append(list, NewLine{})
 		} else if strings.HasPrefix(s, "prefix(") && len(d) > 8 {
diff --git a/pkg/section/section.go b/pkg/section/section.go
index cc0a43f..b84ba2c 100644
--- a/pkg/section/section.go
+++ b/pkg/section/section.go
@@ -28,7 +28,7 @@ func (list SectionList) String() []string {
 }
 
 func DefaultSections() SectionList {
-	return SectionList{Standard{}, Default{}}
+	return SectionList{NewStandard(), Default{}}
 }
 
 func DefaultSectionSeparators() SectionList {
diff --git a/pkg/section/standard.go b/pkg/section/standard.go
index 26c7e9d..223c6b5 100644
--- a/pkg/section/standard.go
+++ b/pkg/section/standard.go
@@ -1,16 +1,33 @@
 package section
 
 import (
+	"golang.org/x/tools/go/packages"
+
 	"github.com/daixiang0/gci/pkg/parse"
 	"github.com/daixiang0/gci/pkg/specificity"
 )
 
 const StandardType = "standard"
 
-type Standard struct{}
+type Standard struct {
+	standardPackages map[string]struct{}
+}
+
+func NewStandard() Standard {
+	pkgs, err := packages.Load(nil, "std")
+	if err != nil {
+		panic(err)
+	}
+
+	standardPackages := make(map[string]struct{})
+	for _, p := range pkgs {
+		standardPackages[p.PkgPath] = struct{}{}
+	}
+	return Standard{standardPackages: standardPackages}
+}
 
 func (s Standard) MatchSpecificity(spec *parse.GciImports) specificity.MatchSpecificity {
-	if isStandard(spec.Path) {
+	if _, ok := s.standardPackages[spec.Path]; ok {
 		return specificity.StandardMatch{}
 	}
 	return specificity.MisMatch{}
@@ -23,8 +40,3 @@ func (s Standard) String() string {
 func (s Standard) Type() string {
 	return StandardType
 }
-
-func isStandard(pkg string) bool {
-	_, ok := standardPackages[pkg]
-	return ok
-}
diff --git a/pkg/section/standard_list.go b/pkg/section/standard_list.go
deleted file mode 100644
index 62decfe..0000000
--- a/pkg/section/standard_list.go
+++ /dev/null
@@ -1,160 +0,0 @@
-package section
-
-// Code generated based on go1.19.2. DO NOT EDIT.
-
-var standardPackages = map[string]struct{}{
-	"archive/tar":          {},
-	"archive/zip":          {},
-	"bufio":                {},
-	"bytes":                {},
-	"compress/bzip2":       {},
-	"compress/flate":       {},
-	"compress/gzip":        {},
-	"compress/lzw":         {},
-	"compress/zlib":        {},
-	"container/heap":       {},
-	"container/list":       {},
-	"container/ring":       {},
-	"context":              {},
-	"crypto":               {},
-	"crypto/aes":           {},
-	"crypto/cipher":        {},
-	"crypto/des":           {},
-	"crypto/dsa":           {},
-	"crypto/ecdsa":         {},
-	"crypto/ed25519":       {},
-	"crypto/elliptic":      {},
-	"crypto/hmac":          {},
-	"crypto/md5":           {},
-	"crypto/rand":          {},
-	"crypto/rc4":           {},
-	"crypto/rsa":           {},
-	"crypto/sha1":          {},
-	"crypto/sha256":        {},
-	"crypto/sha512":        {},
-	"crypto/subtle":        {},
-	"crypto/tls":           {},
-	"crypto/x509":          {},
-	"crypto/x509/pkix":     {},
-	"database/sql":         {},
-	"database/sql/driver":  {},
-	"debug/buildinfo":      {},
-	"debug/dwarf":          {},
-	"debug/elf":            {},
-	"debug/gosym":          {},
-	"debug/macho":          {},
-	"debug/pe":             {},
-	"debug/plan9obj":       {},
-	"embed":                {},
-	"encoding":             {},
-	"encoding/ascii85":     {},
-	"encoding/asn1":        {},
-	"encoding/base32":      {},
-	"encoding/base64":      {},
-	"encoding/binary":      {},
-	"encoding/csv":         {},
-	"encoding/gob":         {},
-	"encoding/hex":         {},
-	"encoding/json":        {},
-	"encoding/pem":         {},
-	"encoding/xml":         {},
-	"errors":               {},
-	"expvar":               {},
-	"flag":                 {},
-	"fmt":                  {},
-	"go/ast":               {},
-	"go/build":             {},
-	"go/build/constraint":  {},
-	"go/constant":          {},
-	"go/doc":               {},
-	"go/doc/comment":       {},
-	"go/format":            {},
-	"go/importer":          {},
-	"go/parser":            {},
-	"go/printer":           {},
-	"go/scanner":           {},
-	"go/token":             {},
-	"go/types":             {},
-	"hash":                 {},
-	"hash/adler32":         {},
-	"hash/crc32":           {},
-	"hash/crc64":           {},
-	"hash/fnv":             {},
-	"hash/maphash":         {},
-	"html":                 {},
-	"html/template":        {},
-	"image":                {},
-	"image/color":          {},
-	"image/color/palette":  {},
-	"image/draw":           {},
-	"image/gif":            {},
-	"image/jpeg":           {},
-	"image/png":            {},
-	"index/suffixarray":    {},
-	"io":                   {},
-	"io/fs":                {},
-	"io/ioutil":            {},
-	"log":                  {},
-	"log/syslog":           {},
-	"math":                 {},
-	"math/big":             {},
-	"math/bits":            {},
-	"math/cmplx":           {},
-	"math/rand":            {},
-	"mime":                 {},
-	"mime/multipart":       {},
-	"mime/quotedprintable": {},
-	"net":                  {},
-	"net/http":             {},
-	"net/http/cgi":         {},
-	"net/http/cookiejar":   {},
-	"net/http/fcgi":        {},
-	"net/http/httptest":    {},
-	"net/http/httptrace":   {},
-	"net/http/httputil":    {},
-	"net/http/pprof":       {},
-	"net/mail":             {},
-	"net/netip":            {},
-	"net/rpc":              {},
-	"net/rpc/jsonrpc":      {},
-	"net/smtp":             {},
-	"net/textproto":        {},
-	"net/url":              {},
-	"os":                   {},
-	"os/exec":              {},
-	"os/signal":            {},
-	"os/user":              {},
-	"path":                 {},
-	"path/filepath":        {},
-	"plugin":               {},
-	"reflect":              {},
-	"regexp":               {},
-	"regexp/syntax":        {},
-	"runtime":              {},
-	"runtime/cgo":          {},
-	"runtime/debug":        {},
-	"runtime/metrics":      {},
-	"runtime/pprof":        {},
-	"runtime/race":         {},
-	"runtime/trace":        {},
-	"sort":                 {},
-	"strconv":              {},
-	"strings":              {},
-	"sync":                 {},
-	"sync/atomic":          {},
-	"syscall":              {},
-	"testing":              {},
-	"testing/fstest":       {},
-	"testing/iotest":       {},
-	"testing/quick":        {},
-	"text/scanner":         {},
-	"text/tabwriter":       {},
-	"text/template":        {},
-	"text/template/parse":  {},
-	"time":                 {},
-	"time/tzdata":          {},
-	"unicode":              {},
-	"unicode/utf16":        {},
-	"unicode/utf8":         {},
-	"unsafe":               {},
-}


Test patch:
diff --git a/pkg/section/standard_test.go b/pkg/section/standard_test.go
index 2209402..aba4a13 100644
--- a/pkg/section/standard_test.go
+++ b/pkg/section/standard_test.go
@@ -7,14 +7,15 @@ import (
 )
 
 func TestStandardPackageSpecificity(t *testing.T) {
+	standard := NewStandard()
 	testCases := []specificityTestData{
-		{"context", Standard{}, specificity.StandardMatch{}},
-		{"contexts", Standard{}, specificity.MisMatch{}},
-		{"crypto", Standard{}, specificity.StandardMatch{}},
-		{"crypto1", Standard{}, specificity.MisMatch{}},
-		{"crypto/ae", Standard{}, specificity.MisMatch{}},
-		{"crypto/aes", Standard{}, specificity.StandardMatch{}},
-		{"crypto/aes2", Standard{}, specificity.MisMatch{}},
+		{"context", standard, specificity.StandardMatch{}},
+		{"contexts", standard, specificity.MisMatch{}},
+		{"crypto", standard, specificity.StandardMatch{}},
+		{"crypto1", standard, specificity.MisMatch{}},
+		{"crypto/ae", standard, specificity.MisMatch{}},
+		{"crypto/aes", standard, specificity.StandardMatch{}},
+		{"crypto/aes2", standard, specificity.MisMatch{}},
 	}
 	testSpecificity(t, testCases)
 }