-
Notifications
You must be signed in to change notification settings - Fork 446
Expand file tree
/
Copy pathgofile.go
More file actions
136 lines (113 loc) · 3.28 KB
/
gofile.go
File metadata and controls
136 lines (113 loc) · 3.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package extgen
import (
"bytes"
_ "embed"
"fmt"
"path/filepath"
"strings"
"text/template"
"github.com/Masterminds/sprig/v3"
)
//go:embed templates/extension.go.tpl
var goFileContent string
type GoFileGenerator struct {
generator *Generator
}
type goTemplateData struct {
PackageName string
BaseName string
Imports []string
Constants []phpConstant
InternalFunctions []string
Functions []phpFunction
Classes []phpClass
Module *phpModule
HasInitFunction bool
}
func (gg *GoFileGenerator) generate() error {
filename := filepath.Join(gg.generator.BuildDir, gg.generator.BaseName+".go")
content, err := gg.buildContent()
if err != nil {
return fmt.Errorf("building Go file content: %w", err)
}
return writeFile(filename, content)
}
func (gg *GoFileGenerator) buildContent() (string, error) {
sourceAnalyzer := SourceAnalyzer{}
imports, internalFunctions, err := sourceAnalyzer.analyze(gg.generator.SourceFile)
if err != nil {
return "", fmt.Errorf("analyzing source file: %w", err)
}
filteredImports := make([]string, 0, len(imports))
for _, imp := range imports {
if imp != `"C"` {
filteredImports = append(filteredImports, imp)
}
}
classes := make([]phpClass, len(gg.generator.Classes))
copy(classes, gg.generator.Classes)
// Check if there's already an init() function in the source file
hasInitFunction := false
for _, fn := range internalFunctions {
if strings.HasPrefix(fn, "func init()") {
hasInitFunction = true
fmt.Printf("Warning: An init() function already exists in the source file. Make sure to call frankenphp.RegisterExtension(unsafe.Pointer(&C.ext_module_entry)) in your init function.\n")
break
}
}
templateContent, err := gg.getTemplateContent(goTemplateData{
PackageName: SanitizePackageName(gg.generator.BaseName),
BaseName: gg.generator.BaseName,
Imports: filteredImports,
Constants: gg.generator.Constants,
InternalFunctions: internalFunctions,
Functions: gg.generator.Functions,
Classes: classes,
Module: gg.generator.Module,
HasInitFunction: hasInitFunction,
})
if err != nil {
return "", fmt.Errorf("executing template: %w", err)
}
return templateContent, nil
}
func (gg *GoFileGenerator) getTemplateContent(data goTemplateData) (string, error) {
funcMap := sprig.FuncMap()
funcMap["phpTypeToGoType"] = gg.phpTypeToGoType
funcMap["isStringOrArray"] = func(t phpType) bool {
return t == phpString || t == phpArray
}
funcMap["isVoid"] = func(t phpType) bool {
return t == phpVoid
}
tmpl := template.Must(template.New("gofile").Funcs(funcMap).Parse(goFileContent))
var buf bytes.Buffer
if err := tmpl.Execute(&buf, data); err != nil {
return "", err
}
return buf.String(), nil
}
type GoMethodSignature struct {
MethodName string
Params []GoParameter
ReturnType string
}
type GoParameter struct {
Name string
Type string
}
func (gg *GoFileGenerator) phpTypeToGoType(phpT phpType) string {
typeMap := map[phpType]string{
phpString: "string",
phpInt: "int64",
phpFloat: "float64",
phpBool: "bool",
phpArray: "*frankenphp.Array",
phpMixed: "interface{}",
phpVoid: "",
}
if goType, exists := typeMap[phpT]; exists {
return goType
}
return "interface{}"
}