Repository: goplus/gop
Pull request #1368 (2023-05-26 03:00:45)

fix empty struct argument call for gop style
fix https://github.com/goplus/gop/issues/1367

```
func CreateBox(name string, opt Option) {
	println(name,opt)
}

CreateBox("box",{Size:1}) // ok
CreateBox("box",{}) // fixed build pass
```


Patch:
diff --git a/cl/expr.go b/cl/expr.go
index 99e7624a..5d185db1 100644
--- a/cl/expr.go
+++ b/cl/expr.go
@@ -683,12 +683,15 @@ const (
 	compositeLitKeyVal = 1
 )
 
-func checkCompositeLitElts(ctx *blockCtx, elts []ast.Expr) (kind int) {
+func checkCompositeLitElts(ctx *blockCtx, elts []ast.Expr, onlyStruct bool) (kind int) {
 	for _, elt := range elts {
 		if _, ok := elt.(*ast.KeyValueExpr); ok {
 			return compositeLitKeyVal
 		}
 	}
+	if len(elts) == 0 && onlyStruct {
+		return compositeLitKeyVal
+	}
 	return compositeLitVal
 }
 
@@ -793,7 +796,7 @@ func getUnderlying(ctx *blockCtx, typ types.Type) types.Type {
 func compileCompositeLit(ctx *blockCtx, v *ast.CompositeLit, expected types.Type, onlyStruct bool) {
 	var hasPtr bool
 	var typ, underlying types.Type
-	var kind = checkCompositeLitElts(ctx, v.Elts)
+	var kind = checkCompositeLitElts(ctx, v.Elts, onlyStruct)
 	if v.Type != nil {
 		typ = toType(ctx, v.Type)
 		underlying = getUnderlying(ctx, typ)
diff --git a/parser/parser.go b/parser/parser.go
index 3d6f9fc0..c217b70a 100644
--- a/parser/parser.go
+++ b/parser/parser.go
@@ -25,6 +25,7 @@
 // treated like an ordinary parameter list and thus may contain multiple
 // entries where the spec permits exactly one. Consequently, the corresponding
 // field in the AST (ast.FuncDecl.Recv) field is not restricted to one entry.
+//
 package parser
 
 import (
@@ -197,6 +198,7 @@ var unresolved = new(ast.Object)
 // the object it denotes. If no object is found and collectUnresolved is
 // set, x is marked as unresolved and collected in the list of unresolved
 // identifiers.
+//
 func (p *parser) tryResolve(x ast.Expr, collectUnresolved bool) {
 	// nothing to do if x is not an identifier or the blank identifier
 	ident, _ := x.(*ast.Ident)
@@ -314,6 +316,7 @@ func (p *parser) consumeComment() (comment *ast.Comment, endline int) {
 // comments list, and return it together with the line at which
 // the last comment in the group ends. A non-comment token or n
 // empty lines terminate a comment group.
+//
 func (p *parser) consumeCommentGroup(n int) (comments *ast.CommentGroup, endline int) {
 	var list []*ast.Comment
 	endline = p.file.Line(p.pos)
@@ -344,6 +347,7 @@ func (p *parser) consumeCommentGroup(n int) (comments *ast.CommentGroup, endline
 //
 // Lead and line comments may be considered documentation that is
 // stored in the AST.
+//
 func (p *parser) next() {
 	p.leadComment = nil
 	p.lineComment = nil
@@ -445,6 +449,7 @@ func (p *parser) expect2(tok token.Token) (pos token.Pos) {
 
 // expectClosing is like expect but provides a better error message
 // for the common case of a missing comma before a newline.
+//
 func (p *parser) expectClosing(tok token.Token, context string) token.Pos {
 	if p.tok != tok && p.tok == token.SEMICOLON && p.lit == "\n" {
 		p.error(p.pos, "missing ',' before newline in "+context)
@@ -566,6 +571,7 @@ var exprEnd = map[token.Token]bool{
 // token positions are invalid due to parse errors, the resulting end position
 // may be past the file's EOF position, which would lead to panics if used
 // later on.
+//
 func (p *parser) safePos(pos token.Pos) (res token.Pos) {
 	defer func() {
 		if recover() != nil {
@@ -1591,6 +1597,7 @@ func (p *parser) parseFuncTypeOrLit() ast.Expr {
 // parseOperand may return an expression or a raw type (incl. array
 // types of the form [...]T. Callers must verify the result.
 // If lhs is set and the result is an identifier, it is not resolved.
+//
 func (p *parser) parseOperand(lhs, allowTuple, allowCmd bool) (x ast.Expr, isTuple bool) {
 	if p.trace {
 		defer un(trace(p, "Operand"))
@@ -2192,14 +2199,7 @@ L:
 			} else {
 				break L
 			}
-		case token.NOT:
-			if allowCmd && p.isCmd(x) {
-				x = p.parseCallOrConversion(p.checkExprOrType(x), true)
-			} else {
-				x = &ast.ErrWrapExpr{X: x, Tok: token.NOT, TokPos: p.pos}
-				p.next()
-			}
-		case token.QUESTION:
+		case token.NOT, token.QUESTION:
 			x = &ast.ErrWrapExpr{X: x, Tok: p.tok, TokPos: p.pos}
 			p.next()
 		default:


Test patch:
diff --git a/cl/compile_test.go b/cl/compile_test.go
index a05508e3..53972caa 100644
--- a/cl/compile_test.go
+++ b/cl/compile_test.go
@@ -2011,6 +2011,8 @@ func bar(conf ...Config) {
 
 foo({A: 1})
 bar({A: 2})
+foo({})
+bar({})
 `, `package main
 
 type Config struct {
@@ -2024,6 +2026,8 @@ func bar(conf ...Config) {
 func main() {
 	foo(&Config{A: 1})
 	bar(Config{A: 2})
+	foo(&Config{})
+	bar(Config{})
 }
 `)
 }
@@ -4267,40 +4271,3 @@ func main() {
 }
 `)
 }
-
-func TestCommandNotExpr(t *testing.T) {
-	gopClTest(t, `
-println !true
-`, `package main
-
-import fmt "fmt"
-
-func main() {
-	fmt.Println(false)
-}
-`)
-	gopClTest(t, `
-a := true
-println !a
-`, `package main
-
-import fmt "fmt"
-
-func main() {
-	a := true
-	fmt.Println(!a)
-}
-`)
-	gopClTest(t, `
-println !func() bool { return true }()
-`, `package main
-
-import fmt "fmt"
-
-func main() {
-	fmt.Println(!func() bool {
-		return true
-	}())
-}
-`)
-}
diff --git a/parser/_testdata/cmdlinestyle3/cmd3.gop b/parser/_testdata/cmdlinestyle3/cmd3.gop
index 921db5f9..b1f81ffd 100644
--- a/parser/_testdata/cmdlinestyle3/cmd3.gop
+++ b/parser/_testdata/cmdlinestyle3/cmd3.gop
@@ -1,2 +1,1 @@
 println &x
-println !x
diff --git a/parser/_testdata/cmdlinestyle3/parser.expect b/parser/_testdata/cmdlinestyle3/parser.expect
index 8335924b..762e943c 100644
--- a/parser/_testdata/cmdlinestyle3/parser.expect
+++ b/parser/_testdata/cmdlinestyle3/parser.expect
@@ -25,15 +25,3 @@ ast.FuncDecl:
                   X:
                     ast.Ident:
                       Name: x
-        ast.ExprStmt:
-          X:
-            ast.CallExpr:
-              Fun:
-                ast.Ident:
-                  Name: println
-              Args:
-                ast.UnaryExpr:
-                  Op: !
-                  X:
-                    ast.Ident:
-                      Name: x