Skip to content

Commit 712614a

Browse files
alexandre-dauboishenderkes
authored andcommitted
fix: support filename other than ext.go and keep local vars on generation
1 parent b93c55c commit 712614a

7 files changed

Lines changed: 124 additions & 23 deletions

File tree

internal/extgen/gofile.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ type goTemplateData struct {
2222
BaseName string
2323
Imports []string
2424
Constants []phpConstant
25+
Variables []string
2526
InternalFunctions []string
2627
Functions []phpFunction
2728
Classes []phpClass
@@ -39,7 +40,7 @@ func (gg *GoFileGenerator) generate() error {
3940

4041
func (gg *GoFileGenerator) buildContent() (string, error) {
4142
sourceAnalyzer := SourceAnalyzer{}
42-
imports, internalFunctions, err := sourceAnalyzer.analyze(gg.generator.SourceFile)
43+
imports, variables, internalFunctions, err := sourceAnalyzer.analyze(gg.generator.SourceFile)
4344
if err != nil {
4445
return "", fmt.Errorf("analyzing source file: %w", err)
4546
}
@@ -59,6 +60,7 @@ func (gg *GoFileGenerator) buildContent() (string, error) {
5960
BaseName: gg.generator.BaseName,
6061
Imports: filteredImports,
6162
Constants: gg.generator.Constants,
63+
Variables: variables,
6264
InternalFunctions: internalFunctions,
6365
Functions: gg.generator.Functions,
6466
Classes: classes,

internal/extgen/hfile.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ type HeaderGenerator struct {
1717
}
1818

1919
type TemplateData struct {
20+
BaseName string
2021
HeaderGuard string
2122
Constants []phpConstant
2223
Classes []phpClass
@@ -50,6 +51,7 @@ func (hg *HeaderGenerator) buildContent() (string, error) {
5051

5152
var buf bytes.Buffer
5253
err = tmpl.Execute(&buf, TemplateData{
54+
BaseName: hg.generator.BaseName,
5355
HeaderGuard: headerGuard,
5456
Constants: hg.generator.Constants,
5557
Classes: hg.generator.Classes,

internal/extgen/hfile_test.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
package extgen
22

33
import (
4-
"github.com/stretchr/testify/require"
54
"path/filepath"
65
"strings"
76
"testing"
87

8+
"github.com/stretchr/testify/require"
9+
910
"github.com/stretchr/testify/assert"
1011
)
1112

@@ -43,7 +44,7 @@ func TestHeaderGenerator_BuildContent(t *testing.T) {
4344
"#ifndef _SIMPLE_H",
4445
"#define _SIMPLE_H",
4546
"#include <php.h>",
46-
"extern zend_module_entry ext_module_entry;",
47+
"extern zend_module_entry simple_module_entry;",
4748
"#endif",
4849
},
4950
},
@@ -128,7 +129,7 @@ func TestHeaderGenerator_BasicStructure(t *testing.T) {
128129

129130
expectedElements := []string{
130131
"#include <php.h>",
131-
"extern zend_module_entry ext_module_entry;",
132+
"extern zend_module_entry structtest_module_entry;",
132133
}
133134

134135
for _, element := range expectedElements {
@@ -264,7 +265,7 @@ func TestHeaderGenerator_MinimalContent(t *testing.T) {
264265
"#ifndef _MINIMAL_H",
265266
"#define _MINIMAL_H",
266267
"#include <php.h>",
267-
"extern zend_module_entry ext_module_entry;",
268+
"extern zend_module_entry minimal_module_entry;",
268269
"#endif",
269270
}
270271

@@ -287,7 +288,7 @@ func testHeaderBasicStructure(t *testing.T, content, baseName string) {
287288
"#ifndef _" + headerGuard,
288289
"#define _" + headerGuard,
289290
"#include <php.h>",
290-
"extern zend_module_entry ext_module_entry;",
291+
"extern zend_module_entry test_extension_module_entry;",
291292
"#endif",
292293
}
293294

internal/extgen/srcanalyzer.go

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ import (
1010

1111
type SourceAnalyzer struct{}
1212

13-
func (sa *SourceAnalyzer) analyze(filename string) (imports []string, internalFunctions []string, err error) {
13+
func (sa *SourceAnalyzer) analyze(filename string) (imports []string, variables []string, internalFunctions []string, err error) {
1414
fset := token.NewFileSet()
1515
node, err := parser.ParseFile(fset, filename, nil, parser.ParseComments)
1616
if err != nil {
17-
return nil, nil, fmt.Errorf("parsing file: %w", err)
17+
return nil, nil, nil, fmt.Errorf("parsing file: %w", err)
1818
}
1919

2020
for _, imp := range node.Imports {
@@ -30,12 +30,58 @@ func (sa *SourceAnalyzer) analyze(filename string) (imports []string, internalFu
3030

3131
sourceContent, err := os.ReadFile(filename)
3232
if err != nil {
33-
return nil, nil, fmt.Errorf("reading source file: %w", err)
33+
return nil, nil, nil, fmt.Errorf("reading source file: %w", err)
3434
}
3535

36+
variables = sa.extractVariables(string(sourceContent))
3637
internalFunctions = sa.extractInternalFunctions(string(sourceContent))
3738

38-
return imports, internalFunctions, nil
39+
return imports, variables, internalFunctions, nil
40+
}
41+
42+
func (sa *SourceAnalyzer) extractVariables(content string) []string {
43+
lines := strings.Split(content, "\n")
44+
var (
45+
variables []string
46+
currentVar strings.Builder
47+
inVarBlock bool
48+
parenCount int
49+
)
50+
51+
for _, line := range lines {
52+
trimmedLine := strings.TrimSpace(line)
53+
54+
if strings.HasPrefix(trimmedLine, "var ") && !inVarBlock {
55+
if strings.Contains(trimmedLine, "(") {
56+
inVarBlock = true
57+
parenCount = 1
58+
currentVar.Reset()
59+
currentVar.WriteString(line + "\n")
60+
} else {
61+
variables = append(variables, strings.TrimSpace(line))
62+
}
63+
} else if inVarBlock {
64+
currentVar.WriteString(line + "\n")
65+
66+
for _, char := range line {
67+
switch char {
68+
case '(':
69+
parenCount++
70+
case ')':
71+
parenCount--
72+
}
73+
}
74+
75+
if parenCount == 0 {
76+
varContent := currentVar.String()
77+
variables = append(variables, strings.TrimSpace(varContent))
78+
inVarBlock = false
79+
currentVar.Reset()
80+
}
81+
}
82+
}
83+
84+
return variables
3985
}
4086

4187
func (sa *SourceAnalyzer) extractInternalFunctions(content string) []string {

internal/extgen/srcanalyzer_test.go

Lines changed: 55 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ func TestSourceAnalyzer_Analyze(t *testing.T) {
1414
name string
1515
sourceContent string
1616
expectedImports []string
17+
expectedVariables []string
1718
expectedFunctions []string
1819
expectError bool
1920
}{
@@ -34,7 +35,8 @@ func regularFunction() {
3435
func exportedFunction() string {
3536
return "exported"
3637
}`,
37-
expectedImports: []string{`"fmt"`, `"strings"`},
38+
expectedImports: []string{`"fmt"`, `"strings"`},
39+
expectedVariables: nil,
3840
expectedFunctions: []string{
3941
`func regularFunction() {
4042
fmt.Println("hello")
@@ -53,7 +55,8 @@ import (
5355
)
5456
5557
func test() {}`,
56-
expectedImports: []string{`custom "fmt"`, `. "strings"`, `_ "os"`},
58+
expectedImports: []string{`custom "fmt"`, `. "strings"`, `_ "os"`},
59+
expectedVariables: nil,
5760
expectedFunctions: []string{
5861
`func test() {}`,
5962
},
@@ -82,7 +85,8 @@ func internalTwo() string {
8285
func exportedTwo() bool {
8386
return true
8487
}`,
85-
expectedImports: []string{},
88+
expectedImports: []string{},
89+
expectedVariables: nil,
8690
expectedFunctions: []string{
8791
`func internalOne() {
8892
// some code
@@ -116,7 +120,8 @@ func exportedComplex() {
116120
}
117121
fmt.Println(obj)
118122
}`,
119-
expectedImports: []string{},
123+
expectedImports: []string{},
124+
expectedVariables: nil,
120125
expectedFunctions: []string{
121126
`func complexFunction() {
122127
if true {
@@ -163,10 +168,50 @@ func shouldNotBeExported() {}
163168
func normalFunction() {
164169
//export_php:function inside function should not count
165170
}`,
166-
expectedImports: []string{},
171+
expectedImports: []string{},
172+
expectedVariables: nil,
167173
expectedFunctions: []string{
168174
`func normalFunction() {
169175
//export_php:function inside function should not count
176+
}`,
177+
},
178+
expectError: false,
179+
},
180+
{
181+
name: "file with variable blocks",
182+
sourceContent: `package main
183+
184+
import (
185+
"sync"
186+
)
187+
188+
var (
189+
mu sync.RWMutex
190+
store = map[string]struct {
191+
val string
192+
expires int64
193+
}{}
194+
)
195+
196+
var singleVar = "test"
197+
198+
func testFunction() {
199+
// test function
200+
}`,
201+
expectedImports: []string{`"sync"`},
202+
expectedVariables: []string{
203+
`var (
204+
mu sync.RWMutex
205+
store = map[string]struct {
206+
val string
207+
expires int64
208+
}{}
209+
)`,
210+
`var singleVar = "test"`,
211+
},
212+
expectedFunctions: []string{
213+
`func testFunction() {
214+
// test function
170215
}`,
171216
},
172217
expectError: false,
@@ -181,7 +226,7 @@ func normalFunction() {
181226
require.NoError(t, os.WriteFile(filename, []byte(tt.sourceContent), 0644))
182227

183228
analyzer := &SourceAnalyzer{}
184-
imports, functions, err := analyzer.analyze(filename)
229+
imports, variables, functions, err := analyzer.analyze(filename)
185230

186231
if tt.expectError {
187232
assert.Error(t, err, "expected error")
@@ -194,6 +239,7 @@ func normalFunction() {
194239
assert.Equal(t, tt.expectedImports, imports, "imports mismatch")
195240
}
196241

242+
assert.Equal(t, tt.expectedVariables, variables, "variables mismatch")
197243
assert.Len(t, functions, len(tt.expectedFunctions), "function count mismatch")
198244

199245
for i, expected := range tt.expectedFunctions {
@@ -207,7 +253,7 @@ func TestSourceAnalyzer_Analyze_InvalidFile(t *testing.T) {
207253
analyzer := &SourceAnalyzer{}
208254

209255
t.Run("nonexistent file", func(t *testing.T) {
210-
_, _, err := analyzer.analyze("/nonexistent/file.go")
256+
_, _, _, err := analyzer.analyze("/nonexistent/file.go")
211257
assert.Error(t, err, "expected error for nonexistent file")
212258
})
213259

@@ -222,7 +268,7 @@ func TestSourceAnalyzer_Analyze_InvalidFile(t *testing.T) {
222268

223269
require.NoError(t, os.WriteFile(filename, []byte(invalidContent), 0644))
224270

225-
_, _, err := analyzer.analyze(filename)
271+
_, _, _, err := analyzer.analyze(filename)
226272
assert.Error(t, err, "expected error for invalid syntax")
227273
})
228274
}
@@ -372,7 +418,7 @@ func internalTwo() {
372418
analyzer := &SourceAnalyzer{}
373419

374420
for b.Loop() {
375-
_, _, err := analyzer.analyze(filename)
421+
_, _, _, err := analyzer.analyze(filename)
376422
require.NoError(b, err)
377423
}
378424
}

internal/extgen/templates/extension.go.tpl

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,21 @@ package {{.PackageName}}
55
#include "{{.BaseName}}.h"
66
*/
77
import "C"
8-
import "runtime/cgo"
98
{{- range .Imports}}
109
import {{.}}
1110
{{- end}}
1211

1312
func init() {
14-
frankenphp.RegisterExtension(unsafe.Pointer(&C.ext_module_entry))
13+
frankenphp.RegisterExtension(unsafe.Pointer(&C.{{.BaseName}}_module_entry))
1514
}
16-
{{range .Constants}}
15+
{{- range .Constants}}
1716
const {{.Name}} = {{.Value}}
1817
{{- end}}
18+
19+
{{ range .Variables}}
20+
{{.}}
21+
{{- end}}
22+
1923
{{range .InternalFunctions}}
2024
{{.}}
2125
{{- end}}

internal/extgen/templates/extension.h.tpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#include <php.h>
55
#include <stdint.h>
66

7-
extern zend_module_entry ext_module_entry;
7+
extern zend_module_entry {{.BaseName}}_module_entry;
88

99
{{if .Constants}}
1010
/* User defined constants */{{end}}

0 commit comments

Comments
 (0)