Skip to content

Commit b2f861f

Browse files
committed
More test cases for ParseFieldPath
1 parent 082e20c commit b2f861f

File tree

2 files changed

+27
-13
lines changed

2 files changed

+27
-13
lines changed

internal/convgen/parse/struct.go

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,21 @@ func (ps structParsers) parse(p *Parser, expr ast.Expr, owner typeinfo.Type) (*P
2929
}
3030

3131
if len(path.StructField) == 0 {
32-
panic(1)
32+
panic("unreachable: struct field must be at least one")
3333
}
3434
if len(path.StructField) == 1 {
3535
return nil, codefmt.Errorf(p, expr, "cannot use %t itself as a field", owner)
3636
}
3737
return path, nil
3838
}
3939

40-
func (ps structParsers) walk(p *Parser, expr ast.Expr, owner typeinfo.Type) (*Path, error) {
40+
func (ps structParsers) walk(p *Parser, expr ast.Expr, owner typeinfo.Type) (*Path, error) { // nolint:gocyclo
4141
expr = ast.Unparen(expr)
4242

43+
if !owner.Deref().IsNamed() {
44+
return nil, codefmt.Errorf(p, expr, "field of anonymous struct is not supported")
45+
}
46+
4347
// Unwrap convgen.Field~ function calls
4448
// e.g., convgen.FieldGetter(T{}.GetField) -> T{}.GetField
4549
if call, ok := expr.(*ast.CallExpr); ok {
@@ -51,51 +55,55 @@ func (ps structParsers) walk(p *Parser, expr ast.Expr, owner typeinfo.Type) (*Pa
5155

5256
switch x := expr.(type) {
5357
case *ast.CompositeLit:
58+
err := codefmt.Errorf(p, expr, "field should belong to %t{}; got %c", owner, expr)
59+
5460
// Expression: T{}
5561
if len(x.Elts) != 0 {
5662
// T{...}
57-
return nil, codefmt.Errorf(p, expr, "field should belong to %t{} with empty braces; got %c", owner, expr)
63+
return nil, err
5864
}
5965

6066
id, ok := ast.Unparen(x.Type).(*ast.Ident)
6167
if !ok {
6268
// struct{}{}
63-
return nil, codefmt.Errorf(p, expr, "field cannot belong to anonymous struct")
69+
return nil, err
6470
}
6571

6672
t := typeinfo.TypeOf(p.Pkg().TypesInfo.TypeOf(id))
6773
if !t.Identical(owner.Deref()) {
6874
// U{} where U != T
69-
return nil, codefmt.Errorf(p, expr, "field should belong to %t{}; got %c", owner, expr)
75+
return nil, err
7076
}
7177

7278
obj := p.Pkg().TypesInfo.ObjectOf(id)
7379
return &Path{StructField: []types.Object{obj}, Pos: id.Pos()}, nil
7480

7581
case *ast.CallExpr:
82+
err := codefmt.Errorf(p, expr, "field should belong to (*%t)(nil); got %c", owner, expr)
83+
7684
// Expression: (*T)(nil)
7785
if len(x.Args) != 1 || !p.IsNil(x.Args[0]) {
7886
// (nil) expected but got (), (nonil), (...)
79-
return nil, codefmt.Errorf(p, expr, "field should belong to (*%t)(nil); got %c", owner, expr)
87+
return nil, err
8088
}
8189

8290
fun := ast.Unparen(x.Fun)
8391
star, ok := fun.(*ast.StarExpr)
8492
if !ok {
8593
// f(nil) where f != *T
86-
return nil, codefmt.Errorf(p, expr, "field should belong to (*%t)(nil); got %c", owner, expr)
94+
return nil, err
8795
}
8896

8997
id, ok := ast.Unparen(star.X).(*ast.Ident)
9098
if !ok {
9199
// (*struct{})(nil)
92-
return nil, codefmt.Errorf(p, expr, "field cannot belong to anonymous struct")
100+
return nil, err
93101
}
94102

95103
t := typeinfo.TypeOf(p.Pkg().TypesInfo.TypeOf(id))
96104
if !t.Identical(owner.Deref()) {
97105
// (*U)(nil) where U != T
98-
return nil, codefmt.Errorf(p, expr, "field should belong to (*%t)(nil); got %c", owner, expr)
106+
return nil, err
99107
}
100108

101109
obj := p.Pkg().TypesInfo.ObjectOf(id)

testdata/analysis/ParseFieldPath/testdata.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,30 @@ func f(...any) X { return X{} }
1414
var Case1 = convgen.Struct[X, X](nil,
1515
convgen.Match(X{}.A, X{}.A.B), // ok
1616
convgen.Match(X{}.A, X{}), // want `cannot use X itself as a field`
17-
convgen.Match(X{}.A, X{Y{1}}.A.B), // want `field should belong to X\{\} with empty braces; got X\{Y\{1\}\}`
17+
convgen.Match(X{}.A, X{Y{1}}.A.B), // want `field should belong to X\{\}; got X\{Y\{1\}\}`
1818
convgen.Match(X{}.A, Y{}.B), // want `field should belong to X\{\}; got Y\{\}`
19-
convgen.Match(X{}.A, struct{ A Y }{}.A.B), // want `field cannot belong to anonymous struct`
19+
convgen.Match(X{}.A, struct{ A Y }{}.A.B), // want `field should belong to X\{\}; got struct\{ A Y \}\{\}`
2020

2121
convgen.Match(X{}.A, (*X)(nil).A.B), // ok
2222
convgen.Match(X{}.A, f().A.B), // want `field should belong to \(\*X\)\(nil\); got f\(\)`
2323
convgen.Match(X{}.A, f(nil).A.B), // want `field should belong to \(\*X\)\(nil\); got f\(nil\)`
2424
convgen.Match(X{}.A, f(1).A.B), // want `field should belong to \(\*X\)\(nil\); got f\(1\)`
2525
convgen.Match(X{}.A, (*Y)(nil).B), // want `field should belong to \(\*X\)\(nil\); got \(\*Y\)\(nil\)`
26-
convgen.Match(X{}.A, (*struct{ A Y })(nil).A.B), // want `field cannot belong to anonymous struct`
26+
convgen.Match(X{}.A, (*struct{ A Y })(nil).A.B), // want `field should belong to \(\*X\)\(nil\); got \(\*struct\{ A Y \}\)\(nil\)`
2727

2828
convgen.Match(X{}.A, (&X{}).A.B), // ok
2929
convgen.Match(X{}.A, &(&X{}).A.B), // ok
3030
convgen.Match(X{}.A, (*(&X{})).A.B), // ok
31+
32+
convgen.Match(X{}.A, 0), // want `invalid field expression; got 0`
33+
convgen.Match(X{}.A, []X{}), // want `field should belong to X\{\}; got \[\]X\{\}`
34+
convgen.Match(X{}.A, map[int]X{}), // want `field should belong to X\{\}; got map\[int\]X\{\}`
3135
)
3236

3337
var Case2 = convgen.Struct[X, struct{ X }](nil,
34-
convgen.Match(X{}.A, struct{ X }{}.X.A.B), // want `field cannot belong to anonymous struct`
38+
convgen.Match(X{}.A, struct{ X }{}.X.A.B), // want `field of anonymous struct is not supported`
39+
convgen.Match(X{}.A, struct{ X }{}.X), // want `field of anonymous struct is not supported`
40+
convgen.Match(X{}.A, 0), // want `field of anonymous struct is not supported`
3541
)
3642

3743
type Z struct {

0 commit comments

Comments
 (0)