diff --git a/main.go b/main.go index f1a95cc..4436abd 100644 --- a/main.go +++ b/main.go @@ -2,12 +2,13 @@ package main import ( "flag" + "fmt" + "path/filepath" "strings" _ "embed" logger "git.site.quack-lab.dev/dave/cylogger" - utils "git.site.quack-lab.dev/dave/cyutils" ) func main() { @@ -23,16 +24,34 @@ func main() { return } - // TODO: Implement parsing enums somehow - // TODO: Implement some sort of switching (between a class and an enum) - utils.WithWorkers(10, files, func(worker int, file string) { - class, err := ParseClass(file) - if err != nil { - logger.Error("Error parsing file: %v", err) - return + // Group files by their base class name (without [Client]/[Server]) + classGroups := make(map[string][]string) + for _, file := range files { + // Extract base class name from filename + baseName := extractBaseClassName(file) + classGroups[baseName] = append(classGroups[baseName], file) + } + + // Process each group + for baseName, groupFiles := range classGroups { + if len(groupFiles) == 1 { + // Single file, process normally + class, err := ParseClass(groupFiles[0]) + if err != nil { + logger.Error("Error parsing file: %v", err) + continue + } + class.Write(*outdir, classTemplate) + } else { + // Multiple files for same class, merge them + mergedClass, err := MergeClasses(groupFiles) + if err != nil { + logger.Error("Error merging classes for %s: %v", baseName, err) + continue + } + mergedClass.Write(*outdir, classTemplate) } - class.Write(*outdir, classTemplate) - }) + } } func MapType(t string) string { @@ -110,3 +129,86 @@ func IsReservedKeyword(t string) bool { } return false } + +// extractBaseClassName extracts the base class name from a filename +// e.g., "Player [Client].html" -> "Player" +func extractBaseClassName(filename string) string { + // Extract filename without path + base := filepath.Base(filename) + // Remove .html extension + base = strings.TrimSuffix(base, ".html") + // Remove [Client] or [Server] suffix + base = strings.ReplaceAll(base, " [Client]", "") + base = strings.ReplaceAll(base, " [Server]", "") + return base +} + +// MergeClasses merges multiple class files into a single class +func MergeClasses(files []string) (*Class, error) { + if len(files) == 0 { + return nil, fmt.Errorf("no files to merge") + } + + // Parse all classes + var classes []*Class + var baseName string + + for _, file := range files { + class, err := ParseClass(file) + if err != nil { + return nil, fmt.Errorf("error parsing %s: %w", file, err) + } + classes = append(classes, class) + + // Use the first class name as base + if baseName == "" { + baseName = class.ClassName + } + } + + // Merge all classes into the first one + merged := classes[0] + + // Create maps to track methods and fields by name + methodMap := make(map[string]*Method) + fieldMap := make(map[string]*Field) + + // Add methods from all classes, handling duplicates + for _, class := range classes { + for _, method := range class.Methods { + if existing, exists := methodMap[method.Name]; exists { + // Method exists in multiple contexts, update availability + if !strings.Contains(existing.Comment, "[Client/Server]") { + if strings.Contains(existing.Comment, "[Client]") && strings.Contains(method.Comment, "[Server]") { + existing.Comment = "[Client/Server] " + strings.TrimPrefix(existing.Comment, "[Client] ") + } else if strings.Contains(existing.Comment, "[Server]") && strings.Contains(method.Comment, "[Client]") { + existing.Comment = "[Client/Server] " + strings.TrimPrefix(existing.Comment, "[Server] ") + } + } + } else { + // New method, add it + methodMap[method.Name] = &method + } + } + + // Add fields from all classes, avoiding duplicates + for _, field := range class.Fields { + if _, exists := fieldMap[field.Name]; !exists { + fieldMap[field.Name] = &field + } + } + } + + // Convert maps back to slices + merged.Methods = make([]Method, 0, len(methodMap)) + for _, method := range methodMap { + merged.Methods = append(merged.Methods, *method) + } + + merged.Fields = make([]Field, 0, len(fieldMap)) + for _, field := range fieldMap { + merged.Fields = append(merged.Fields, *field) + } + + return merged, nil +}