/ common / utils / code_language.go
code_language.go
  1  // Copyright (c) 2024-2026 Tencent Zhuque Lab. All rights reserved.
  2  //
  3  // Licensed under the Apache License, Version 2.0 (the "License");
  4  // you may not use this file except in compliance with the License.
  5  // You may obtain a copy of the License at
  6  //
  7  //     http://www.apache.org/licenses/LICENSE-2.0
  8  //
  9  // Unless required by applicable law or agreed to in writing, software
 10  // distributed under the License is distributed on an "AS IS" BASIS,
 11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12  // See the License for the specific language governing permissions and
 13  // limitations under the License.
 14  //
 15  // Requirement: Any integration or derivative work must explicitly attribute
 16  // Tencent Zhuque Lab (https://github.com/Tencent/AI-Infra-Guard) in its
 17  // documentation or user interface, as detailed in the NOTICE file.
 18  
 19  package utils
 20  
 21  import (
 22  	"io/fs"
 23  	"path/filepath"
 24  	"sort"
 25  	"strings"
 26  	"sync"
 27  )
 28  
 29  func classifyLanguage(ext string) string {
 30  	// 扩展名与编程语言映射表(可根据需求扩展)
 31  	var extToLang = map[string]string{
 32  		".go":    "Go",
 33  		".py":    "Python",
 34  		".java":  "Java",
 35  		".rs":    "Rust",
 36  		".php":   "PHP",
 37  		".rb":    "Ruby",
 38  		".swift": "Swift",
 39  		".c":     "C",
 40  		".h":     "C",
 41  		".cpp":   "C++",
 42  		".hpp":   "C++",
 43  		".js":    "JavaScript",
 44  		".ts":    "TypeScript",
 45  		".html":  "HTML",
 46  		".css":   "CSS",
 47  		".sql":   "SQL",
 48  		".sh":    "Shell",
 49  	}
 50  
 51  	if lang, exists := extToLang[ext]; exists {
 52  		return lang
 53  	}
 54  	return ""
 55  }
 56  
 57  func AnalyzeLanguage(dir string) map[string]int {
 58  	var wg sync.WaitGroup
 59  	mu := sync.Mutex{}
 60  	stats := make(map[string]int)
 61  
 62  	filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
 63  		if err != nil || d.IsDir() {
 64  			return nil
 65  		}
 66  
 67  		wg.Add(1)
 68  		go func() {
 69  			defer wg.Done()
 70  
 71  			ext := strings.ToLower(filepath.Ext(path))
 72  			lang := classifyLanguage(ext)
 73  			if lang == "" {
 74  				return
 75  			}
 76  			mu.Lock()
 77  			stats[lang]++
 78  			mu.Unlock()
 79  		}()
 80  
 81  		return nil
 82  	})
 83  
 84  	wg.Wait()
 85  	return stats
 86  }
 87  
 88  type LanguageCount struct {
 89  	Language string
 90  	Count    int
 91  }
 92  
 93  func GetTopLanguage(stats map[string]int) string {
 94  	if len(stats) == 0 {
 95  		return "Other"
 96  	}
 97  
 98  	// 将 map 转换为结构体切片
 99  	var list []LanguageCount
100  	for lang, count := range stats {
101  		list = append(list, LanguageCount{Language: lang, Count: count})
102  	}
103  
104  	// 按文件数量降序排序
105  	sort.Slice(list, func(i, j int) bool {
106  		return list[i].Count > list[j].Count // 降序排列
107  	})
108  
109  	return list[0].Language
110  }