package quality import ( "os" "path/filepath" "strings" ) // LanguageConfig represents configuration for a programming language type LanguageConfig struct { Name string `json:"name"` Extensions []string `json:"extensions"` MarkerFiles []string `json:"marker_files"` DefaultSrc string `json:"default_src"` } // GetSupportedLanguages returns all supported languages func GetSupportedLanguages() []LanguageConfig { return []LanguageConfig{ { Name: "go", Extensions: []string{".go"}, MarkerFiles: []string{"go.mod", "go.sum"}, DefaultSrc: ".", }, { Name: "typescript", Extensions: []string{".ts", ".tsx"}, MarkerFiles: []string{"package.json", "tsconfig.json"}, DefaultSrc: "src", }, { Name: "python", Extensions: []string{".py"}, MarkerFiles: []string{"requirements.txt", "setup.py", "pyproject.toml"}, DefaultSrc: ".", }, { Name: "java", Extensions: []string{".java"}, MarkerFiles: []string{"pom.xml", "build.gradle"}, DefaultSrc: "src/main/java", }, { Name: "rust", Extensions: []string{".rs"}, MarkerFiles: []string{"Cargo.toml"}, DefaultSrc: "src", }, { Name: "javascript", Extensions: []string{".js", ".jsx"}, MarkerFiles: []string{"package.json"}, DefaultSrc: "src", }, { Name: "csharp", Extensions: []string{".cs"}, MarkerFiles: []string{"*.csproj", "*.sln"}, DefaultSrc: ".", }, { Name: "dart", Extensions: []string{".dart"}, MarkerFiles: []string{"pubspec.yaml"}, DefaultSrc: "lib", }, } } // DefaultFileFinder implements FileFinder interface type DefaultFileFinder struct{} // NewDefaultFileFinder creates a new default file finder func NewDefaultFileFinder() *DefaultFileFinder { return &DefaultFileFinder{} } // FindFiles returns source files for the given path and language func (f *DefaultFileFinder) FindFiles(path string, language string) ([]string, error) { languages := GetSupportedLanguages() var extensions []string // Find language config for _, lang := range languages { if lang.Name == language { extensions = lang.Extensions break } } // Default to Go extensions if not found if len(extensions) == 0 { extensions = []string{".go"} } var files []string err := filepath.Walk(path, func(filePath string, info os.FileInfo, err error) error { if err != nil { return err } // Skip directories if info.IsDir() { // Skip hidden directories and common exclude dirs base := filepath.Base(filePath) if filePath != path && (strings.HasPrefix(base, ".") || base == "node_modules" || base == "vendor") { return filepath.SkipDir } return nil } // Check file extension ext := filepath.Ext(filePath) for _, langExt := range extensions { if ext == langExt { files = append(files, filePath) break } } return nil }) return files, err } // IsSourceFile checks if a file is a source file for the language func (f *DefaultFileFinder) IsSourceFile(path string, language string) bool { languages := GetSupportedLanguages() var extensions []string // Find language config for _, lang := range languages { if lang.Name == language { extensions = lang.Extensions break } } // Default to Go extensions if not found if len(extensions) == 0 { extensions = []string{".go"} } ext := filepath.Ext(path) for _, langExt := range extensions { if ext == langExt { return true } } return false } // DetectLanguage attempts to auto-detect the project language from marker files func DetectLanguage(path string) string { languages := GetSupportedLanguages() // Check for marker files in order of specificity for _, lang := range languages { for _, marker := range lang.MarkerFiles { markerPath := filepath.Join(path, marker) if _, err := filepath.Glob(markerPath); err == nil { // Check if any files match the pattern matches, _ := filepath.Glob(markerPath) if len(matches) > 0 { return lang.Name } } } } // Default to Go if no markers found return "go" }