You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by sr...@apache.org on 2024/09/04 17:10:06 UTC
(plc4x) 02/02: feat(plc4go/plc4xGenerator): add pointer support
This is an automated email from the ASF dual-hosted git repository.
sruehl pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git
commit 9ba4867a031daca6e2c51fca6fc64f31859f21bf
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Wed Sep 4 19:09:51 2024 +0200
feat(plc4go/plc4xGenerator): add pointer support
+ add tests for better debugging
---
plc4go/tools/plc4xGenerator/ExampleStruct_test.go | 26 ++++++++++
plc4go/tools/plc4xGenerator/main.go | 61 +++++++++++++++++++----
plc4go/tools/plc4xGenerator/main_test.go | 43 ++++++++++++++++
3 files changed, 119 insertions(+), 11 deletions(-)
diff --git a/plc4go/tools/plc4xGenerator/ExampleStruct_test.go b/plc4go/tools/plc4xGenerator/ExampleStruct_test.go
new file mode 100644
index 0000000000..00d3ecc4ae
--- /dev/null
+++ b/plc4go/tools/plc4xGenerator/ExampleStruct_test.go
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package main
+
+type Example struct {
+ aField *uint16
+ bField string
+ cField int
+}
diff --git a/plc4go/tools/plc4xGenerator/main.go b/plc4go/tools/plc4xGenerator/main.go
index 8c454cc248..3aaa548b96 100644
--- a/plc4go/tools/plc4xGenerator/main.go
+++ b/plc4go/tools/plc4xGenerator/main.go
@@ -44,6 +44,8 @@ var (
suffix = flag.String("suffix", "", "suffix for all generated files")
buildTags = flag.String("tags", "", "comma-separated list of build tags to apply")
licenseFile = flag.String("licenseFile", ".plc4xLicencer.header", "file containing the license (will be searched upwards)")
+ tests = flag.Bool("tests", false, "look at test files")
+ pkgIndex = flag.Int("pkgIndex", -1, "package index (can enforce a different index if multiple packages are found)")
verbose = flag.Bool("verbose", false, "verbosity")
)
@@ -56,6 +58,8 @@ func Usage() {
flag.PrintDefaults()
}
+var outputFile string // only used for test
+
func main() {
log.SetFlags(0)
log.SetPrefix("plc4xGenerator: ")
@@ -134,10 +138,12 @@ func main() {
outputName = filepath.Join(directory, strings.ReplaceAll(file, ext, "")+*suffix+ext)
}
+ log.Printf("Writing to %s\n", outputName)
err := os.WriteFile(outputName, src, 0644)
if err != nil {
log.Fatalf("writing output: %s", err)
}
+ outputFile = outputName
}
// isDirectory reports whether the named file is a directory.
@@ -183,17 +189,23 @@ type Package struct {
func (g *Generator) parsePackage(patterns []string, tags []string) {
cfg := &packages.Config{
Mode: packages.NeedName | packages.NeedTypes | packages.NeedTypesInfo | packages.NeedSyntax,
- Tests: false,
+ Tests: *tests,
BuildFlags: []string{fmt.Sprintf("-tags=%s", strings.Join(tags, " "))},
}
pkgs, err := packages.Load(cfg, patterns...)
if err != nil {
log.Fatal(err)
}
+ index := 0
+ if *pkgIndex > 0 {
+ index = *pkgIndex
+ }
if len(pkgs) != 1 {
- log.Fatalf("error: %d packages found", len(pkgs))
+ if *pkgIndex < 0 {
+ log.Fatalf("error: %d packages found (%v)", len(pkgs), pkgs)
+ }
}
- g.addPackage(pkgs[0])
+ g.addPackage(pkgs[index])
}
// addPackage adds a type checked Package and its syntax files to the generator.
@@ -373,28 +385,40 @@ func (g *Generator) generate(typeName string) {
fmt.Printf("no support yet for %#q\n", fieldType)
continue
case *ast.Ident:
+ deref := ""
+ indentTimes := 0
+ if needsDereference {
+ deref = "*"
+ indentTimes++
+ g.Printf("if d.%s != nil {", field.name)
+ }
switch fieldType.Name {
case "byte":
- g.Printf(byteFieldSerialize, "d."+field.name, fieldNameUntitled)
+ g.Printf(indent(indentTimes, byteFieldSerialize), deref+"d."+field.name, fieldNameUntitled)
case "int":
- g.Printf(int64FieldSerialize, "int64(d."+field.name+")", fieldNameUntitled)
+ g.Printf(indent(indentTimes, int64FieldSerialize), "int64("+deref+"d."+field.name+")", fieldNameUntitled)
case "int32":
- g.Printf(int32FieldSerialize, "int32(d."+field.name+")", fieldNameUntitled)
+ g.Printf(indent(indentTimes, int32FieldSerialize), "int32("+deref+"d."+field.name+")", fieldNameUntitled)
+ case "uint16":
+ g.Printf(indent(indentTimes, uint16FieldSerialize), deref+"d."+field.name, fieldNameUntitled)
case "uint32":
- g.Printf(uint32FieldSerialize, "d."+field.name, fieldNameUntitled)
+ g.Printf(indent(indentTimes, uint32FieldSerialize), deref+"d."+field.name, fieldNameUntitled)
case "bool":
- g.Printf(boolFieldSerialize, "d."+field.name, fieldNameUntitled)
+ g.Printf(indent(indentTimes, boolFieldSerialize), deref+"d."+field.name, fieldNameUntitled)
case "string":
- g.Printf(stringFieldSerialize, "d."+field.name, fieldNameUntitled)
+ g.Printf(indent(indentTimes, stringFieldSerialize), deref+"d."+field.name, fieldNameUntitled)
case "error":
- g.Printf(errorFieldSerialize, "d."+field.name, fieldNameUntitled)
+ g.Printf(indent(indentTimes, errorFieldSerialize), deref+"d."+field.name, fieldNameUntitled)
default:
fmt.Printf("\t no support implemented for Ident with type %v\n", fieldType)
g.Printf("{\n")
- g.Printf("_value := fmt.Sprintf(\"%%v\", d.%s)\n", fieldName)
+ g.Printf("_value := fmt.Sprintf(\"%%v\", "+deref+"d.%s)\n", fieldName)
g.Printf(stringFieldSerialize, "_value", fieldNameUntitled)
g.Printf("}\n")
}
+ if needsDereference {
+ g.Printf("}")
+ }
case *ast.ArrayType:
if eltType, ok := fieldType.Elt.(*ast.Ident); ok && eltType.Name == "byte" {
g.Printf("if err := writeBuffer.WriteByteArray(%s, d.%s); err != nil {\n", fieldNameUntitled, field.name)
@@ -618,6 +642,15 @@ func (f *File) genDecl(node ast.Node) bool {
return false
}
+func indent(times int, input string) string {
+ if times == 0 {
+ return input
+ }
+ lines := strings.Split(input, "\n")
+ indents := strings.Repeat("\t", times)
+ return indents + strings.Join(lines, "\n"+indents)
+}
+
var stringerTemplate = `
func (d *%s) String() string {
writeBuffer := utils.NewWriteBufferBoxBasedWithOptions(true, true)
@@ -689,6 +722,12 @@ var int64FieldSerialize = `
}
`
+var uint16FieldSerialize = `
+ if err := writeBuffer.WriteUint16(%[2]s, 16, %[1]s); err != nil {
+ return err
+ }
+`
+
var uint32FieldSerialize = `
if err := writeBuffer.WriteUint32(%[2]s, 32, %[1]s); err != nil {
return err
diff --git a/plc4go/tools/plc4xGenerator/main_test.go b/plc4go/tools/plc4xGenerator/main_test.go
new file mode 100644
index 0000000000..4cd4f7d01d
--- /dev/null
+++ b/plc4go/tools/plc4xGenerator/main_test.go
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package main
+
+import (
+ "github.com/stretchr/testify/require"
+ "os"
+ "path"
+ "testing"
+ "time"
+
+ "github.com/apache/plc4x/plc4go/spi/utils"
+)
+
+func TestBanana(t *testing.T) {
+ typeNames = utils.MakePtr("Example")
+ suffix = utils.MakePtr("_test")
+ tests = utils.MakePtr(true)
+ pkgIndex = utils.MakePtr(1)
+ output = utils.MakePtr(path.Join(t.TempDir(), "aTestOutput.go"))
+ main()
+ time.Sleep(1 * time.Second)
+ file, err := os.ReadFile(outputFile)
+ require.NoError(t, err)
+ t.Logf("Output:\n%s", string(file))
+}