Repository: goplus/gop
Pull request #1393 (2023-07-04 03:35:18)

classfile field var support tag
support .gopx classfile field tag

Rect.gopx
```
import "bytes"
var (
	*bytes.Buffer "spec:\"buffer\""
	a int "json:\"a\""
	b int
)
func test(){}
```
autogen_gop.go
```
package main

import bytes "bytes"

type Rect struct {
	*bytes.Buffer "spec:\"buffer\""
	a             int "json:\"a\""
	b             int
}

func (this *Rect) test() {
}
```



Patch:
diff --git a/.gitattributes b/.gitattributes
index b541ff26..5cbe6c61 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -2,4 +2,5 @@
 *.golden text eol=lf
 
 *.gop text eol=lf
-*.go text eol=lf
\ No newline at end of file
+*.go text eol=lf
+*.gopx text eol=lf
diff --git a/ast/ast.go b/ast/ast.go
index 544cb8d5..521971d3 100644
--- a/ast/ast.go
+++ b/ast/ast.go
@@ -956,6 +956,7 @@ type (
 		Doc     *CommentGroup // associated documentation; or nil
 		Names   []*Ident      // value names (len(Names) > 0)
 		Type    Expr          // value type; or nil
+		Tag     *BasicLit     // classfile field tag; or nil
 		Values  []Expr        // initial values; or nil
 		Comment *CommentGroup // line comments; or nil
 	}
diff --git a/cl/compile.go b/cl/compile.go
index bb396960..3736a67b 100644
--- a/cl/compile.go
+++ b/cl/compile.go
@@ -591,9 +591,11 @@ func preloadGopFile(p *gox.Package, ctx *blockCtx, file string, f *ast.File, con
 				}
 				pkg := p.Types
 				var flds []*types.Var
+				var tags []string
 				chk := newCheckRedecl()
 				if len(baseTypeName) != 0 {
 					flds = append(flds, types.NewField(pos, pkg, baseTypeName, baseType, true))
+					tags = append(tags, "")
 					chk.chkRedecl(ctx, baseTypeName, pos)
 				}
 				if spxClass && parent.gmxSettings != nil && parent.gameClass != "" {
@@ -602,6 +604,7 @@ func preloadGopFile(p *gox.Package, ctx *blockCtx, file string, f *ast.File, con
 					if !chk.chkRedecl(ctx, name, pos) {
 						fld := types.NewField(pos, pkg, name, typ, true)
 						flds = append(flds, fld)
+						tags = append(tags, "")
 					}
 				}
 				for _, v := range specs {
@@ -618,9 +621,10 @@ func preloadGopFile(p *gox.Package, ctx *blockCtx, file string, f *ast.File, con
 							continue
 						}
 						flds = append(flds, types.NewField(name.Pos(), pkg, name.Name, typ, embed))
+						tags = append(tags, toFieldTag(spec.Tag))
 					}
 				}
-				decl.InitType(p, types.NewStruct(flds, nil))
+				decl.InitType(p, types.NewStruct(flds, tags))
 			}
 			parent.tylds = append(parent.tylds, ld)
 		}
diff --git a/parser/parser.go b/parser/parser.go
index dbb8cc0e..21e206b1 100644
--- a/parser/parser.go
+++ b/parser/parser.go
@@ -3354,6 +3354,7 @@ func (p *parser) parseValueSpec(doc *ast.CommentGroup, keyword token.Token, iota
 	pos := p.pos
 	var idents []*ast.Ident
 	var typ ast.Expr
+	var tag *ast.BasicLit
 	var values []ast.Expr
 	if p.mode&ParseGoPlusClass != 0 && p.topScope == p.pkgScope && p.varDeclCnt == 1 {
 		var starPos token.Pos
@@ -3394,6 +3395,10 @@ func (p *parser) parseValueSpec(doc *ast.CommentGroup, keyword token.Token, iota
 				p.error(p.pos, "syntax error: cannot assign value to field in class file")
 			}
 		}
+		if p.tok == token.STRING {
+			tag = &ast.BasicLit{ValuePos: p.pos, Kind: p.tok, Value: p.lit}
+			p.next()
+		}
 		p.expect(token.SEMICOLON)
 	} else {
 		idents = p.parseIdentList()
@@ -3424,6 +3429,7 @@ func (p *parser) parseValueSpec(doc *ast.CommentGroup, keyword token.Token, iota
 		Doc:     doc,
 		Names:   idents,
 		Type:    typ,
+		Tag:     tag,
 		Values:  values,
 		Comment: p.lineComment,
 	}
diff --git a/printer/nodes.go b/printer/nodes.go
index 1eaa4b19..67b2452c 100644
--- a/printer/nodes.go
+++ b/printer/nodes.go
@@ -1619,6 +1619,14 @@ func (p *printer) valueSpec(s *ast.ValueSpec, keepType bool) {
 	if s.Type != nil {
 		p.expr(s.Type)
 	}
+	if s.Tag != nil {
+		if len(s.Names) > 0 {
+			p.print(vtab)
+		}
+		p.print(vtab)
+		p.expr(s.Tag)
+		extraTabs--
+	}
 	if s.Values != nil {
 		p.print(vtab, token.ASSIGN, blank)
 		p.exprList(token.NoPos, s.Values, 1, 0, token.NoPos, false)


Test patch:
diff --git a/cl/compile_test.go b/cl/compile_test.go
index 695686c9..46f238c4 100644
--- a/cl/compile_test.go
+++ b/cl/compile_test.go
@@ -4381,6 +4381,27 @@ type Rect struct {
 	*bytes.Buffer
 }
 
+func (this *Rect) test() {
+}
+`, "Rect.gopx")
+	gopClTestFile(t, `
+import "bytes"
+var (
+	*bytes.Buffer "spec:\"buffer\""
+	a int "json:\"a\""
+	b int
+)
+func test(){}
+`, `package main
+
+import bytes "bytes"
+
+type Rect struct {
+	*bytes.Buffer "spec:\"buffer\""
+	a             int "json:\"a\""
+	b             int
+}
+
 func (this *Rect) test() {
 }
 `, "Rect.gopx")
diff --git a/parser/_testdata/gopxtest/bar.gopx b/parser/_testdata/gopxtest/bar.gopx
index 95178287..ebb1b146 100644
--- a/parser/_testdata/gopxtest/bar.gopx
+++ b/parser/_testdata/gopxtest/bar.gopx
@@ -1,10 +1,10 @@
 var (
-	A
+	A `json:"a"`
 	*B
 	x, y string
-	C.A
-	*C.B
-	v int
+	C.A  `json:"ca"`
+	*C.B `json:"b"`
+	v    int `json:"v"`
 )
 
 type A struct{}
diff --git a/parser/_testdata/gopxtest/parser.expect b/parser/_testdata/gopxtest/parser.expect
index 7a290bcc..e8e3f13e 100644
--- a/parser/_testdata/gopxtest/parser.expect
+++ b/parser/_testdata/gopxtest/parser.expect
@@ -8,6 +8,10 @@ ast.GenDecl:
       Type:
         ast.Ident:
           Name: A
+      Tag:
+        ast.BasicLit:
+          Kind: STRING
+          Value: `json:"a"`
     ast.ValueSpec:
       Type:
         ast.StarExpr:
@@ -32,6 +36,10 @@ ast.GenDecl:
           Sel:
             ast.Ident:
               Name: A
+      Tag:
+        ast.BasicLit:
+          Kind: STRING
+          Value: `json:"ca"`
     ast.ValueSpec:
       Type:
         ast.StarExpr:
@@ -43,6 +51,10 @@ ast.GenDecl:
               Sel:
                 ast.Ident:
                   Name: B
+      Tag:
+        ast.BasicLit:
+          Kind: STRING
+          Value: `json:"b"`
     ast.ValueSpec:
       Names:
         ast.Ident:
@@ -50,6 +62,10 @@ ast.GenDecl:
       Type:
         ast.Ident:
           Name: int
+      Tag:
+        ast.BasicLit:
+          Kind: STRING
+          Value: `json:"v"`
 ast.GenDecl:
   Tok: type
   Specs:
diff --git a/printer/gop_test.go b/printer/gop_test.go
index f9996874..19b4fd58 100644
--- a/printer/gop_test.go
+++ b/printer/gop_test.go
@@ -121,7 +121,11 @@ func testFrom(t *testing.T, fpath, sel string, mode int) {
 
 	if (mode & excludeFormatSource) == 0 {
 		t.Run("format.Source "+fpath, func(t *testing.T) {
-			res, err := format.Source(src, false, fpath)
+			var class bool
+			if filepath.Ext(fpath) == ".gopx" {
+				class = true
+			}
+			res, err := format.Source(src, class, fpath)
 			if err != nil {
 				t.Fatal("Source failed:", err)
 			}
@@ -132,7 +136,11 @@ func testFrom(t *testing.T, fpath, sel string, mode int) {
 	if (mode & excludeFormatNode) == 0 {
 		t.Run("format.Node "+fpath, func(t *testing.T) {
 			fset := token.NewFileSet()
-			f, err := parser.ParseFile(fset, fpath, src, parser.ParseComments)
+			m := parser.ParseComments
+			if filepath.Ext(fpath) == ".gopx" {
+				m |= parser.ParseGoPlusClass
+			}
+			f, err := parser.ParseFile(fset, fpath, src, m)
 			if err != nil {
 				t.Fatal(err)
 			}
@@ -182,7 +190,8 @@ func TestFromParse(t *testing.T) {
 			return err
 		}
 		name := info.Name()
-		if !info.IsDir() && filepath.Ext(name) == ".gop" {
+		ext := filepath.Ext(name)
+		if !info.IsDir() && (ext == ".gop" || ext == ".gopx") {
 			testFrom(t, path, sel, 0)
 		}
 		return nil