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))
+}