GitRoot
Craft your forge, Build your project, Grow your community freely
1// SPDX-FileCopyrightText: 2026 Romain Maneschi <romain@gitroot.dev>
2//
3// SPDX-License-Identifier: EUPL-1.2
4
5package main
6
7import (
8 "bytes"
9 "fmt"
10 "go/types"
11 "os"
12 "path/filepath"
13 "slices"
14 "strings"
15)
16
17type LangToGenerate interface {
18 Extension() string
19 TemplateStruct(g *Generate, f *FileToGen, st Struct) (string, []string)
20 TemplateEnum(en Enum, variants []string) string
21 FormatFuncName(fn Func) string
22 FormatParams(sig *types.Signature, isMethod bool, currentFile string, locations map[string]string) (string, []string)
23 FormatReturnType(sig *types.Signature, currentFile string, locations map[string]string) string
24 FormatExportFunc(wasmName string, funcName string) string
25 FormatImportFunc(wasmName string, funcName string, paramsList string, returnType string) string
26}
27
28func (g *Generate) generateFile(f *FileToGen, lang LangToGenerate, intoDir string) (string, string, error) {
29 relativeSubPath := strings.TrimPrefix(f.OriginFilePath, g.fromDir)
30 outputFile := filepath.Join(intoDir, "src", relativeSubPath)
31 dirToCreate, filename := filepath.Split(outputFile)
32 finalFile := filepath.Join(dirToCreate, strings.TrimSuffix(filename, ".go")+lang.Extension())
33
34 previousContent, err := os.ReadFile(finalFile)
35 if err != nil {
36 fmt.Printf("π No previous content %s\n", finalFile)
37 previousContent = []byte{}
38 }
39
40 var fileContent strings.Builder
41 var imports []string
42
43 for _, st := range f.Structs {
44 content, localImports := lang.TemplateStruct(g, f, st)
45 fileContent.WriteString(content + "\n")
46 for _, imp := range localImports {
47 if imp != "" && !slices.Contains(imports, imp) {
48 imports = append(imports, imp)
49 }
50 }
51 }
52
53 for _, en := range f.Enums {
54 var variants []string
55
56 for _, val := range en.Values {
57 cleanVariant := val
58 if strings.HasPrefix(val, en.TypeName) && val != en.TypeName {
59 cleanVariant = strings.TrimPrefix(val, en.TypeName)
60 }
61
62 variants = append(variants, cleanVariant)
63 }
64
65 fileContent.WriteString(lang.TemplateEnum(en, variants) + "\n")
66 }
67
68 //TODO no method today because body is impossible but maybe find a way to add only that ?
69 // methodsByStruct := make(map[string][]Method)
70 // for _, m := range f.Methods {
71 // methodsByStruct[m.StructName] = append(methodsByStruct[m.StructName], m)
72 // }
73
74 // for structName, methods := range methodsByStruct {
75 // cleanStructName := stringy.New(structName).PascalCase().Get()
76 // fileContent.WriteString(fmt.Sprintf("impl %s {\n", cleanStructName))
77
78 // for _, m := range methods {
79 // paramsList, extraImports := lang.FormatParams(m.Sig, true, f.OriginFilePath, g.structLocations)
80 // for _, imp := range extraImports {
81 // if imp != "" && !slices.Contains(imports, imp) {
82 // imports = append(imports, imp)
83 // }
84 // }
85
86 // returnType := lang.FormatReturnType(m.Sig, f.OriginFilePath, g.structLocations)
87
88 // funcName := stringy.New(m.Name).SnakeCase().ToLower()
89 // fileContent.WriteString(fmt.Sprintf(" pub fn %s(%s)%s {\n unimplemented!();\n }\n\n", funcName, paramsList, returnType))
90 // }
91 // fileContent.WriteString("}\n\n")
92 // }
93
94 for _, fn := range f.Funcs {
95 funcName := lang.FormatFuncName(fn)
96 if fn.Wasm == WasmExport && !bytes.Contains(previousContent, []byte(funcName)) {
97 exportTemplate := lang.FormatExportFunc(fn.Name, funcName)
98 fileContent.WriteString(exportTemplate + "\n")
99 } else if !bytes.Contains(previousContent, []byte(funcName)) {
100 paramsList, extraImports := lang.FormatParams(fn.Sig, false, f.OriginFilePath, g.structLocations)
101 for _, imp := range extraImports {
102 if imp != "" && !slices.Contains(imports, imp) {
103 imports = append(imports, imp)
104 }
105 }
106 returnType := lang.FormatReturnType(fn.Sig, f.OriginFilePath, g.structLocations)
107 fileContent.WriteString(lang.FormatImportFunc(fn.Name, funcName, paramsList, returnType))
108 }
109 }
110
111 if fileContent.Len() == 0 {
112 fmt.Printf("π’ nothing to write %s\n", finalFile)
113 return "", "", nil
114 }
115
116 if err := os.MkdirAll(dirToCreate, os.ModePerm); err != nil {
117 return "", "", fmt.Errorf("impossible de crΓ©er le dossier %s: %w", dirToCreate, err)
118 }
119
120 slices.Sort(imports)
121
122 var finalBuffer strings.Builder
123 finalBuffer.WriteString(header)
124
125 for _, imp := range imports {
126 finalBuffer.WriteString(imp + "\n")
127 }
128
129 finalBuffer.WriteString("\n")
130 finalBuffer.WriteString(fileContent.String())
131
132 return finalFile, finalBuffer.String(), nil
133}