Apply gci import order changes

This commit is contained in:
github-actions[bot]
2026-01-12 01:56:41 +00:00
parent dd1dba383f
commit 5fe4eec236
5 changed files with 86 additions and 87 deletions

View File

@ -40,8 +40,8 @@ type PackageKind int
const (
KindInternal PackageKind = iota // Internal to main module
KindExternal // External dependency
KindStdLib // Standard library
KindExternal // External dependency
KindStdLib // Standard library
)
// PackageInfo represents unified information about a Go package.
@ -79,11 +79,11 @@ type FilterOptions struct {
// It centralizes visited tracking, depth management, and filtering logic
// to ensure consistent behavior across different output formats.
type TraversalContext struct {
visited map[string]bool // Track visited packages to prevent cycles
depth int // Current traversal depth
maxDepth int // Maximum traversal depth
options *FilterOptions // Filtering criteria
store *PackageStore // Reference to package store
visited map[string]bool // Track visited packages to prevent cycles
depth int // Current traversal depth
maxDepth int // Maximum traversal depth
options *FilterOptions // Filtering criteria
store *PackageStore // Reference to package store
}
// PackageStore manages a collection of packages and provides unified data access.
@ -91,10 +91,10 @@ type TraversalContext struct {
// It replaces the scattered data access patterns in the original analyzer.
type PackageStore struct {
packages map[string]*PackageInfo // Package data indexed by import path
modulePrefix string // Main module path (from go.mod)
sortedPkgs []string // Cached sorted package list
internalCount int // Cached count of internal packages
externalCount int // Cached count of external packages
modulePrefix string // Main module path (from go.mod)
sortedPkgs []string // Cached sorted package list
internalCount int // Cached count of internal packages
externalCount int // Cached count of external packages
}
// analyzer handles dependency analysis.
@ -105,9 +105,9 @@ type analyzer struct {
edges map[string]bool
store *PackageStore // New unified package store
// Module-level dependency data (from go mod graph)
modules map[string]*ModuleInfo // All modules indexed by path
moduleGraph map[string][]string // Module dependency graph: module -> dependencies
directModules map[string]bool // Direct dependencies (from go.mod require)
modules map[string]*ModuleInfo // All modules indexed by path
moduleGraph map[string][]string // Module dependency graph: module -> dependencies
directModules map[string]bool // Direct dependencies (from go.mod require)
}
// ModuleInfo represents a Go module dependency.
@ -169,12 +169,13 @@ func (a *analyzer) detectModulePrefix() string {
// loadPackages loads package information using go list with optimized approach.
// OPTIMIZATION: Reduced from 3 separate go list calls to 2 efficient calls:
// Previously:
// 1. go list -json %s (target packages only)
// 2. go list -json -deps %s (with dependencies)
// 3. go list -json -m all (all modules)
// 1. go list -json %s (target packages only)
// 2. go list -json -deps %s (with dependencies)
// 3. go list -json -m all (all modules)
//
// Now (optimized):
// 1. go list -json -m all (all modules - fast, definitive)
// 2. go list -json -deps ./... (all packages with dependencies)
// 1. go list -json -m all (all modules - fast, definitive)
// 2. go list -json -deps ./... (all packages with dependencies)
func (a *analyzer) loadPackages(ctx context.Context, pkgPath string) error {
// First, load module information - this is fast and provides module metadata
// Load all module dependencies using go list -m all
@ -659,13 +660,13 @@ func (a *analyzer) convertInputToFilterOptions(in Input) *FilterOptions {
IncludeStdLib: !in.NoStd,
Depth: in.Depth,
}
// Apply default: if neither internal nor external, include internal only
if !in.Internal && !in.External {
opts.IncludeInternal = true
opts.IncludeExternal = false
}
return opts
}
@ -736,14 +737,14 @@ func (opts *FilterOptions) Normalize(modulePrefix string) error {
opts.IncludeInternal = true
opts.IncludeExternal = false
}
// Always include stdlib by default unless explicitly excluded
if opts.IncludeStdLib == false {
// This is the default (NoStd=true), stdlib is excluded
} else {
opts.IncludeStdLib = true
}
return nil
}
@ -764,7 +765,7 @@ func (opts *FilterOptions) ShouldInclude(pkg *PackageInfo) bool {
return false
}
}
return true
}
@ -783,26 +784,26 @@ func (tc *TraversalContext) GetDependencies(pkg string) []string {
if !ok {
return []string{}
}
result := make([]string, 0)
seen := make(map[string]bool)
for _, dep := range pkgInfo.Imports {
if seen[dep] {
continue
}
depInfo, ok := tc.store.packages[dep]
if !ok {
continue
}
if tc.options.ShouldInclude(depInfo) {
seen[dep] = true
result = append(result, dep)
}
}
return result
}
@ -819,7 +820,7 @@ func (a *analyzer) shortName(pkg string, group bool) string {
}
return short
}
// For external packages, handle grouping differently
if group {
return a.getExternalGroup(pkg)
@ -833,7 +834,7 @@ func (a *analyzer) getExternalGroup(pkg string) string {
if a.isStdLib(pkg) {
return "stdlib"
}
// For external packages, group by domain/organization
parts := gstr.Split(pkg, "/")
if len(parts) > 0 {
@ -870,7 +871,7 @@ func (a *analyzer) getSortedPackages() []string {
func (a *analyzer) collectEdges(in Input) map[string]bool {
opts := a.convertInputToFilterOptions(in)
opts.Normalize(a.modulePrefix)
store := a.buildPackageStore()
edges := make(map[string]bool)
visited := make(map[string]bool)
@ -898,7 +899,7 @@ func (a *analyzer) collectEdgesRecursiveNew(pkgPath string, opts *FilterOptions,
visited[pkgPath] = true
fromName := a.shortName(pkgPath, in.Group)
for _, dep := range pkgInfo.Imports {
depInfo, ok := store.packages[dep]
if !ok || !opts.ShouldInclude(depInfo) {
@ -918,10 +919,10 @@ func (a *analyzer) collectEdgesRecursiveNew(pkgPath string, opts *FilterOptions,
// getDependencyStats returns statistics about dependencies using new system.
func (a *analyzer) getDependencyStats(_ Input) map[string]any {
stats := make(map[string]any)
var internalCount, externalCount, stdlibCount int
externalGroups := make(map[string]int)
store := a.buildPackageStore()
opts := &FilterOptions{
IncludeInternal: true,
@ -929,12 +930,12 @@ func (a *analyzer) getDependencyStats(_ Input) map[string]any {
IncludeStdLib: true,
Depth: 0,
}
for _, pkgInfo := range store.packages {
if !opts.ShouldInclude(pkgInfo) {
continue
}
if pkgInfo.IsStdLib {
stdlibCount++
} else if pkgInfo.Kind == KindInternal {
@ -945,13 +946,13 @@ func (a *analyzer) getDependencyStats(_ Input) map[string]any {
externalGroups[group]++
}
}
stats["total"] = len(store.packages)
stats["internal"] = internalCount
stats["external"] = externalCount
stats["stdlib"] = stdlibCount
stats["external_groups"] = externalGroups
return stats
}
@ -966,7 +967,7 @@ func (ps *PackageStore) TraverseDependencies(
options: options,
store: ps,
}
result := make([]string, 0)
ps.traverseRecursive(root, ctx, &result)
return result
@ -981,22 +982,22 @@ func (ps *PackageStore) traverseRecursive(
if ctx.maxDepth > 0 && ctx.depth >= ctx.maxDepth {
return
}
if ctx.Visit(pkg) {
return // Already visited
}
pkgInfo, ok := ps.packages[pkg]
if !ok {
return
}
if !ctx.options.ShouldInclude(pkgInfo) {
return // Filtered out
}
*result = append(*result, pkg)
ctx.depth++
for _, dep := range pkgInfo.Imports {
ps.traverseRecursive(dep, ctx, result)
@ -1010,7 +1011,7 @@ func (ps *PackageStore) TraverseReverse(
options *FilterOptions,
) []string {
result := make([]string, 0)
// Build reverse dependency map on-the-fly
for _, pkg := range ps.packages {
for _, dep := range pkg.Imports {
@ -1019,7 +1020,7 @@ func (ps *PackageStore) TraverseReverse(
}
}
}
sort.Strings(result)
return result
}
@ -1027,7 +1028,7 @@ func (ps *PackageStore) TraverseReverse(
// buildPackageStore converts current analyzer state to PackageStore for new traversal system.
func (a *analyzer) buildPackageStore() *PackageStore {
store := newPackageStore(a.modulePrefix)
// Convert go packages to PackageInfo
for path, goPkg := range a.packages {
pkgInfo := &PackageInfo{
@ -1039,7 +1040,7 @@ func (a *analyzer) buildPackageStore() *PackageStore {
pkgInfo.Kind = store.identifyPackageKind(pkgInfo)
store.packages[path] = pkgInfo
}
return store
}
@ -1047,16 +1048,16 @@ func (a *analyzer) buildPackageStore() *PackageStore {
func (a *analyzer) getFilteredPackages(in Input) []*PackageInfo {
opts := a.convertInputToFilterOptions(in)
opts.Normalize(a.modulePrefix)
store := a.buildPackageStore()
result := make([]*PackageInfo, 0)
for _, pkgInfo := range store.packages {
if opts.ShouldInclude(pkgInfo) {
result = append(result, pkgInfo)
}
}
return result
}
@ -1066,16 +1067,16 @@ func (a *analyzer) getFilteredDependencies(pkgPath string, in Input) []string {
if !ok {
return []string{}
}
opts := a.convertInputToFilterOptions(in)
opts.Normalize(a.modulePrefix)
store := a.buildPackageStore()
ctx := &TraversalContext{
visited: make(map[string]bool),
options: opts,
store: store,
}
return ctx.GetDependencies(pkgPath)
}

View File

@ -104,4 +104,4 @@ func TestDependencyStats(t *testing.T) {
t.Assert(stats["external"], 1)
t.Assert(stats["stdlib"], 1)
})
}
}

View File

@ -48,7 +48,7 @@ func (a *analyzer) generateTree(in Input) string {
fmt.Fprintf(&sb, " Internal: %v\n", stats["internal"])
fmt.Fprintf(&sb, " External: %v\n", stats["external"])
fmt.Fprintf(&sb, " Standard library: %v\n", stats["stdlib"])
if groups, ok := stats["external_groups"].(map[string]int); ok && len(groups) > 0 {
sb.WriteString(" External groups:\n")
for group, count := range groups {
@ -77,10 +77,10 @@ func (a *analyzer) generateTree(in Input) string {
if !ok || !opts.ShouldInclude(pkgInfo) {
continue
}
shortName := a.shortName(pkgPath, in.Group)
sb.WriteString(shortName + "\n")
// Use new traversal system
a.printTreeNodeNew(&sb, pkgPath, "", in, ctx, 0)
}
@ -114,8 +114,6 @@ func (a *analyzer) findRootPackages() []string {
return roots
}
// printTreeNodeNew prints tree node using new traversal system.
func (a *analyzer) printTreeNodeNew(sb *strings.Builder, pkgPath string, prefix string, in Input, ctx *TraversalContext, depth int) {
if ctx.maxDepth > 0 && depth >= ctx.maxDepth {
@ -163,16 +161,16 @@ func (a *analyzer) printTreeNodeNew(sb *strings.Builder, pkgPath string, prefix
// generateList generates simple list output using new traversal system.
func (a *analyzer) generateList(in Input) string {
var sb strings.Builder
// Prepare options
opts := a.convertInputToFilterOptions(in)
opts.Normalize(a.modulePrefix)
// Add statistics header if showing external dependencies
if in.External {
stats := a.getDependencyStats(in)
sb.WriteString("# Dependency Statistics\n")
fmt.Fprintf(&sb, "# Total: %v, Internal: %v, External: %v, Stdlib: %v\n",
fmt.Fprintf(&sb, "# Total: %v, Internal: %v, External: %v, Stdlib: %v\n",
stats["total"], stats["internal"], stats["external"], stats["stdlib"])
sb.WriteString("\n")
}
@ -278,7 +276,7 @@ func (a *analyzer) generateJSON(in Input) string {
store := a.buildPackageStore()
result := make(map[string]any)
// Add dependency nodes
nodes := make([]*depNode, 0)
for _, pkgPath := range a.getSortedPackages() {
@ -293,10 +291,10 @@ func (a *analyzer) generateJSON(in Input) string {
nodes = append(nodes, node)
}
result["dependencies"] = nodes
// Add statistics
result["statistics"] = a.getDependencyStats(in)
// Add metadata
result["metadata"] = map[string]any{
"module": a.modulePrefix,
@ -307,7 +305,7 @@ func (a *analyzer) generateJSON(in Input) string {
"external": in.External,
"nostd": in.NoStd,
}
data, err := json.MarshalIndent(result, "", " ")
if err != nil {
return fmt.Sprintf("Error: %v", err)
@ -361,7 +359,7 @@ func (a *analyzer) buildDepNode(pkg *goPackage, in Input, depth int) *depNode {
func (a *analyzer) generateReverse(in Input) string {
opts := a.convertInputToFilterOptions(in)
opts.Normalize(a.modulePrefix)
store := a.buildPackageStore()
// Build reverse dependency map

View File

@ -195,7 +195,7 @@ func (a *analyzer) handleGraphAPI(w http.ResponseWriter, r *http.Request, in Inp
return
}
}
data := a.buildModuleGraphData(in)
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(data)
@ -288,13 +288,13 @@ func (a *analyzer) handlePackagesAPI(w http.ResponseWriter, r *http.Request, in
UsedByCount: usedByMap[shortName],
})
}
// Add statistics to response
result := map[string]any{
"packages": packages,
"statistics": a.getDependencyStats(in),
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(result)
}
@ -398,7 +398,7 @@ func (a *analyzer) handleTreeAPI(w http.ResponseWriter, r *http.Request, in Inpu
return
}
}
output := a.generateModuleTree(in)
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
w.Write([]byte(output))
@ -442,7 +442,7 @@ func (a *analyzer) handleListAPI(w http.ResponseWriter, r *http.Request, in Inpu
return
}
}
output := a.generateModuleList(in)
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
w.Write([]byte(output))
@ -880,7 +880,7 @@ func (s *serverState) handleAnalyzeAPI(w http.ResponseWriter, r *http.Request) {
// IMPORTANT: Load module dependencies from the actual module directory
// We need to run commands in moduleDir context to get the correct direct/indirect info
// Running in tempDir would show everything as indirect since we're not using them there
// IMPORTANT: Load direct dependencies info FIRST
// This must be done before parsing go mod graph so that IsDirect flag is correct
listModCmd := exec.Command("go", "list", "-m", "-json", "all")
@ -1051,7 +1051,7 @@ func (a *analyzer) handleModulesAPI(w http.ResponseWriter, in Input) {
return
}
}
modules := a.getFilteredModules(in)
// Build module list

View File

@ -41,7 +41,7 @@ func Test_FilterOptions_Normalize(t *testing.T) {
IncludeStdLib: false,
}
opts.Normalize("github.com/gogf/gf/v2")
// After normalization, internal should be included by default
t.Assert(opts.IncludeInternal, true)
t.Assert(opts.IncludeExternal, false)
@ -57,7 +57,7 @@ func Test_FilterOptions_ShouldInclude(t *testing.T) {
IncludeExternal: false,
IncludeStdLib: true,
}
internalPkg := &PackageInfo{
Kind: KindInternal,
IsStdLib: false,
@ -70,7 +70,7 @@ func Test_FilterOptions_ShouldInclude(t *testing.T) {
Kind: KindStdLib,
IsStdLib: true,
}
t.Assert(opts.ShouldInclude(internalPkg), true)
t.Assert(opts.ShouldInclude(externalPkg), false)
t.Assert(opts.ShouldInclude(stdlibPkg), true)
@ -83,7 +83,7 @@ func Test_TraversalContext_Visit(t *testing.T) {
ctx := &TraversalContext{
visited: make(map[string]bool),
}
// First visit should return false
t.Assert(ctx.Visit("pkg1"), false)
// Second visit should return true
@ -105,7 +105,7 @@ func Test_GuessModuleRoot(t *testing.T) {
{"github.com/gogf/gf/v2/os/gfile", "github.com/gogf/gf/v2"},
{"github.com/gogf/gf/v2/os", "github.com/gogf/gf/v2"},
}
for _, test := range tests {
result := guessModuleRoot(test.input)
t.AssertEQ(result, test.expect)
@ -117,7 +117,7 @@ func Test_GuessModuleRoot(t *testing.T) {
func Test_ConvertInputToFilterOptions(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
a := newAnalyzer()
input := Input{
Internal: true,
External: false,
@ -126,9 +126,9 @@ func Test_ConvertInputToFilterOptions(t *testing.T) {
Direct: false,
Depth: 3,
}
opts := a.convertInputToFilterOptions(input)
t.Assert(opts.IncludeInternal, true)
t.Assert(opts.IncludeExternal, false)
t.Assert(opts.IncludeStdLib, false) // NoStd=true means !IncludeStdLib
@ -239,16 +239,16 @@ func Test_Dep_Group(t *testing.T) {
func Test_ModuleLevel_Direct(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
ctx := gctx.New()
// Test module level with direct only
in := Input{
Module: true,
Direct: true,
Format: "list",
}
t.Logf("Input.Module: %v, Input.Direct: %v", in.Module, in.Direct)
_, err := Dep.Index(ctx, in)
t.AssertNil(err)
})