Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d96b6de

Browse files
author
Elias Naur
committed
internal/importers: skip unexported embedded fields
When determining if a Go struct embeds prefixed types, don't consider unexported fields. This is important to avoid references cycles with the Android databinding library; see the reverse example for details. Change-Id: Ia820ca7ba4d1ec11a1f48651fac248eb753aad75 Reviewed-on: https://go-review.googlesource.com/35188 Reviewed-by: David Crawshaw <[email protected]>
1 parent 034bc70 commit d96b6de

File tree

4 files changed

+33
-9
lines changed

4 files changed

+33
-9
lines changed

example/reverse/reverse/reverse.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,25 @@ import (
1111
"Java/android/support/v7/app"
1212
gopkg "Java/reverse"
1313
rlayout "Java/reverse/R/layout"
14+
"Java/reverse/databinding"
1415
"Java/reverse/databinding/ActivityMainBinding"
1516
)
1617

1718
type MainActivity struct {
1819
app.AppCompatActivity
20+
binding databinding.ActivityMainBinding
1921
}
2022

2123
func (a *MainActivity) OnCreate(this gopkg.MainActivity, b os.Bundle) {
2224
this.Super().OnCreate(b)
2325
db := DataBindingUtil.SetContentView(this, rlayout.Activity_main)
24-
mainBind := ActivityMainBinding.Cast(db)
25-
mainBind.SetAct(this)
26+
a.binding = ActivityMainBinding.Cast(db)
27+
a.binding.SetAct(this)
28+
}
29+
30+
func (a *MainActivity) OnDestroy(this gopkg.MainActivity) {
31+
a.binding = nil // break reference cycle
32+
this.Super().OnDestroy()
2633
}
2734

2835
func (a *MainActivity) GetLabel() string {

internal/importers/ast.go

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,9 @@ type PkgRef struct {
8080

8181
type refsSaver struct {
8282
pkgPrefix string
83-
References
84-
refMap map[PkgRef]struct{}
83+
*References
84+
refMap map[PkgRef]struct{}
85+
insideStruct bool
8586
}
8687

8788
// AnalyzeFile scans the provided file for references to packages with the given
@@ -94,7 +95,7 @@ func AnalyzeFile(file *ast.File, pkgPrefix string) (*References, error) {
9495
pkg, _ := ast.NewPackage(fset, files, visitor.importer(), nil)
9596
ast.Walk(visitor, pkg)
9697
visitor.findEmbeddingStructs(pkg)
97-
return &visitor.References, nil
98+
return visitor.References, nil
9899
}
99100

100101
// AnalyzePackages scans the provided packages for references to packages with the given
@@ -118,7 +119,7 @@ func AnalyzePackages(pkgs []*build.Package, pkgPrefix string) (*References, erro
118119
ast.Walk(visitor, astpkg)
119120
visitor.findEmbeddingStructs(astpkg)
120121
}
121-
return &visitor.References, nil
122+
return visitor.References, nil
122123
}
123124

124125
// findEmbeddingStructs finds all top level declarations embedding a prefixed type.
@@ -148,6 +149,9 @@ func (v *refsSaver) findEmbeddingStructs(pkg *ast.Package) {
148149
}
149150
var refs []PkgRef
150151
for _, f := range t.Fields.List {
152+
if len(f.Names) > 0 && !f.Names[0].IsExported() {
153+
continue
154+
}
151155
sel, ok := f.Type.(*ast.SelectorExpr)
152156
if !ok {
153157
continue
@@ -169,8 +173,9 @@ func (v *refsSaver) findEmbeddingStructs(pkg *ast.Package) {
169173

170174
func newRefsSaver(pkgPrefix string) *refsSaver {
171175
s := &refsSaver{
172-
pkgPrefix: pkgPrefix,
173-
refMap: make(map[PkgRef]struct{}),
176+
pkgPrefix: pkgPrefix,
177+
refMap: make(map[PkgRef]struct{}),
178+
References: &References{},
174179
}
175180
s.Names = make(map[string]struct{})
176181
return s
@@ -212,6 +217,17 @@ func (v *refsSaver) parseRef(sel *ast.SelectorExpr) (PkgRef, bool) {
212217

213218
func (v *refsSaver) Visit(n ast.Node) ast.Visitor {
214219
switch n := n.(type) {
220+
case *ast.StructType:
221+
// Use a copy of refsSaver that only accepts exported fields. It refers
222+
// to the original refsSaver for collecting references.
223+
v2 := *v
224+
v2.insideStruct = true
225+
return &v2
226+
case *ast.Field:
227+
if v.insideStruct && len(n.Names) == 1 && !n.Names[0].IsExported() {
228+
return nil
229+
}
230+
return v
215231
case *ast.SelectorExpr:
216232
v.Names[n.Sel.Name] = struct{}{}
217233
if ref, ok := v.parseRef(n); ok {

internal/importers/ast_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const c = Name.Constant
1616
1717
type T struct {
1818
Name.Type
19+
hidden Name.Type2
1920
}
2021
`
2122
fset := token.NewFileSet()

internal/importers/java/java.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ func (j *Importer) Import(refs *importers.References) ([]*Class, error) {
243243
jpkg := strings.Replace(ref.Pkg, "/", ".", -1)
244244
super := jpkg + "." + ref.Name
245245
if _, exists := j.clsMap[super]; !exists {
246-
return nil, fmt.Errorf("class %q not found", super)
246+
return nil, fmt.Errorf("failed to find Java class %s, embedded by %s", super, n)
247247
}
248248
cls.Supers = append(cls.Supers, super)
249249
}

0 commit comments

Comments
 (0)