processor/result.go GO 140 lines View on github.com → Search inside
1// SPDX-License-Identifier: MIT23package processor45import (6	"fmt"7	"os"8	"path/filepath"9	"regexp"10	"runtime"11	"strings"1213	"github.com/boyter/gocodewalker"14)1516// ProcessResult runs the same pipeline as Process but returns structured results17// instead of formatting to stdout. Useful for programmatic consumers like MCP servers.18func ProcessResult() ([]LanguageSummary, error) {19	ProcessConstants()20	processFlags()21	cleanVisitedPaths()22	cleanDuplicates()2324	if len(DirFilePaths) == 0 {25		DirFilePaths = append(DirFilePaths, ".")26	}2728	filePaths := []string{}29	dirPaths := []string{}3031	for _, f := range DirFilePaths {32		fpath := filepath.Clean(f)3334		s, err := os.Stat(fpath)35		if err != nil {36			return nil, fmt.Errorf("file or directory could not be read: %s", fpath)37		}3839		if s.IsDir() {40			dirPaths = append(dirPaths, fpath)41		} else {42			filePaths = append(filePaths, fpath)43		}44	}4546	SortBy = strings.ToLower(SortBy)47	ctx := processorContext{remap: newRemapConfig(RemapAll, RemapUnknown)}4849	printDebugF("NumCPU: %d", runtime.NumCPU())50	printDebugF("SortBy: %s", SortBy)51	printDebugF("PathDenyList: %v", PathDenyList)5253	potentialFilesQueue := make(chan *gocodewalker.File, FileListQueueSize)54	fileListQueue := make(chan *FileJob, FileListQueueSize)55	fileSummaryJobQueue := make(chan *FileJob, FileSummaryJobQueueSize)5657	fileWalker := gocodewalker.NewParallelFileWalker(dirPaths, potentialFilesQueue)58	fileWalker.SetErrorHandler(func(e error) bool {59		printError(e.Error())60		return true61	})62	fileWalker.IgnoreGitIgnore = GitIgnore63	fileWalker.IgnoreIgnoreFile = Ignore64	fileWalker.IgnoreGitModules = GitModuleIgnore65	fileWalker.IncludeHidden = true66	fileWalker.ExcludeDirectory = PathDenyList67	fileWalker.SetConcurrency(DirectoryWalkerJobWorkers)6869	if !SccIgnore {70		fileWalker.CustomIgnore = []string{".sccignore"}71	}72	fileWalker.CustomIgnoreFiles = IgnoreFiles7374	var excludePathRegexes []*regexp.Regexp75	for _, exclude := range Exclude {76		regexpResult, err := regexp.Compile(exclude)77		if err == nil {78			fileWalker.ExcludeFilenameRegex = append(fileWalker.ExcludeFilenameRegex, regexpResult)79			fileWalker.ExcludeDirectoryRegex = append(fileWalker.ExcludeDirectoryRegex, regexpResult)80			excludePathRegexes = append(excludePathRegexes, regexpResult)81		} else {82			printError(err.Error())83		}84	}8586	go func() {87		err := fileWalker.Start()88		if err != nil {89			printError(err.Error())90		}91	}()9293	go func() {94		for _, f := range filePaths {95			fileInfo, err := os.Lstat(f)96			if err != nil {97				continue98			}99100			fileJob := newFileJob(f, f, fileInfo)101			if fileJob != nil {102				fileListQueue <- fileJob103			}104		}105106		for fi := range potentialFilesQueue {107			shouldExclude := false108			for _, re := range excludePathRegexes {109				if re.MatchString(fi.Location) {110					shouldExclude = true111					break112				}113			}114			if shouldExclude {115				continue116			}117118			fileInfo, err := os.Lstat(fi.Location)119			if err != nil {120				continue121			}122123			if !fileInfo.IsDir() {124				fileJob := newFileJob(fi.Location, fi.Filename, fileInfo)125				if fileJob != nil {126					fileListQueue <- fileJob127				}128			}129		}130		close(fileListQueue)131	}()132133	go ctx.fileProcessorWorker(fileListQueue, fileSummaryJobQueue)134135	language := aggregateLanguageSummary(fileSummaryJobQueue)136	language = sortLanguageSummary(language)137138	return language, nil139}

Code quality findings 7

Goroutine without waitgroup or channel; risks resource leaks or race conditions
warning correctness goroutine-without-sync
go func() {
Ensure errors are handled or logged
warning correctness unhandled-error
if err != nil {
Multiple appends without pre-allocation; use make() with capacity when size is known
info performance append-without-prealloc
DirFilePaths = append(DirFilePaths, ".")
Multiple appends without pre-allocation; use make() with capacity when size is known
info performance append-without-prealloc
dirPaths = append(dirPaths, fpath)
Multiple appends without pre-allocation; use make() with capacity when size is known
info performance append-without-prealloc
fileWalker.ExcludeFilenameRegex = append(fileWalker.ExcludeFilenameRegex, regexpResult)
Multiple appends without pre-allocation; use make() with capacity when size is known
info performance append-without-prealloc
fileWalker.ExcludeDirectoryRegex = append(fileWalker.ExcludeDirectoryRegex, regexpResult)
Multiple appends without pre-allocation; use make() with capacity when size is known
info performance append-without-prealloc
excludePathRegexes = append(excludePathRegexes, regexpResult)

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.