Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(jsii-go): use reflect to resolve overriden methods #2780

Merged
merged 9 commits into from
Apr 9, 2021
10 changes: 10 additions & 0 deletions .all-contributorsrc
Original file line number Diff line number Diff line change
Expand Up @@ -1093,6 +1093,16 @@
"contributions": [
"bug"
]
},
{
"login": "yglcode",
"name": "Yigong Liu",
"avatar_url": "https://avatars.githubusercontent.com/u/11893614?v=4",
"profile": "https://github.com/yglcode",
"contributions": [
"bug",
"ideas"
]
}
],
"repoType": "github",
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,18 +178,19 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
<td align="center"><a href="http://ultidev.com/Products/"><img src="https://avatars1.githubusercontent.com/u/757185?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Vlad Hrybok</b></sub></a><br /><a href="https://github.com/aws/jsii/issues?q=author%3Avgribok+label%3Abug" title="Bug reports">🐛</a></td>
<td align="center"><a href="https://github.com/Lanayx"><img src="https://avatars2.githubusercontent.com/u/3329606?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Vladimir Shchur</b></sub></a><br /><a href="https://github.com/aws/jsii/issues?q=author%3ALanayx+label%3Abug" title="Bug reports">🐛</a></td>
<td align="center"><a href="http://yanex.org/"><img src="https://avatars2.githubusercontent.com/u/95996?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Yan Zhulanow</b></sub></a><br /><a href="https://github.com/aws/jsii/commits?author=yanex" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/ajnarang"><img src="https://avatars3.githubusercontent.com/u/52025281?v=4?s=100" width="100px;" alt=""/><br /><sub><b>ajnarang</b></sub></a><br /><a href="https://github.com/aws/jsii/issues?q=author%3Aajnarang+label%3Afeature-request" title="Feature requests">🤔</a></td>
<td align="center"><a href="https://github.com/yglcode"><img src="https://avatars.githubusercontent.com/u/11893614?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Yigong Liu</b></sub></a><br /><a href="https://github.com/aws/jsii/issues?q=author%3Ayglcode+label%3Abug" title="Bug reports">🐛</a> <a href="https://github.com/aws/jsii/issues?q=author%3Ayglcode+label%3Afeature-request" title="Feature requests">🤔</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/ajnarang"><img src="https://avatars3.githubusercontent.com/u/52025281?v=4?s=100" width="100px;" alt=""/><br /><sub><b>ajnarang</b></sub></a><br /><a href="https://github.com/aws/jsii/issues?q=author%3Aajnarang+label%3Afeature-request" title="Feature requests">🤔</a></td>
<td align="center"><a href="https://github.com/aniljava"><img src="https://avatars.githubusercontent.com/u/412569?v=4?s=100" width="100px;" alt=""/><br /><sub><b>aniljava</b></sub></a><br /><a href="https://github.com/aws/jsii/commits?author=aniljava" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/deccy-mcc"><img src="https://avatars0.githubusercontent.com/u/45844893?v=4?s=100" width="100px;" alt=""/><br /><sub><b>deccy-mcc</b></sub></a><br /><a href="https://github.com/aws/jsii/issues?q=author%3Adeccy-mcc+label%3Abug" title="Bug reports">🐛</a></td>
<td align="center"><a href="https://github.com/apps/dependabot-preview"><img src="https://avatars3.githubusercontent.com/in/2141?v=4?s=100" width="100px;" alt=""/><br /><sub><b>dependabot-preview[bot]</b></sub></a><br /><a href="https://github.com/aws/jsii/issues?q=author%3Adependabot-preview[bot]+label%3Abug" title="Bug reports">🐛</a> <a href="https://github.com/aws/jsii/pulls?q=is%3Apr+author%3Adependabot-preview[bot]" title="Maintenance">🚧</a></td>
<td align="center"><a href="https://github.com/apps/dependabot"><img src="https://avatars0.githubusercontent.com/in/29110?v=4?s=100" width="100px;" alt=""/><br /><sub><b>dependabot[bot]</b></sub></a><br /><a href="https://github.com/aws/jsii/pulls?q=is%3Apr+author%3Adependabot[bot]" title="Maintenance">🚧</a></td>
<td align="center"><a href="https://github.com/dheffx"><img src="https://avatars0.githubusercontent.com/u/22029918?v=4?s=100" width="100px;" alt=""/><br /><sub><b>dheffx</b></sub></a><br /><a href="https://github.com/aws/jsii/issues?q=author%3Adheffx+label%3Abug" title="Bug reports">🐛</a></td>
<td align="center"><a href="https://github.com/gregswdl"><img src="https://avatars0.githubusercontent.com/u/47365273?v=4?s=100" width="100px;" alt=""/><br /><sub><b>gregswdl</b></sub></a><br /><a href="https://github.com/aws/jsii/issues?q=author%3Agregswdl+label%3Abug" title="Bug reports">🐛</a></td>
<td align="center"><a href="https://github.com/mattBrzezinski"><img src="https://avatars.githubusercontent.com/u/4356074?v=4?s=100" width="100px;" alt=""/><br /><sub><b>mattBrzezinski</b></sub></a><br /><a href="https://github.com/aws/jsii/commits?author=mattBrzezinski" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/mattBrzezinski"><img src="https://avatars.githubusercontent.com/u/4356074?v=4?s=100" width="100px;" alt=""/><br /><sub><b>mattBrzezinski</b></sub></a><br /><a href="https://github.com/aws/jsii/commits?author=mattBrzezinski" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/apps/mergify"><img src="https://avatars1.githubusercontent.com/in/10562?v=4?s=100" width="100px;" alt=""/><br /><sub><b>mergify[bot]</b></sub></a><br /><a href="https://github.com/aws/jsii/pulls?q=is%3Apr+author%3Amergify[bot]" title="Maintenance">🚧</a></td>
<td align="center"><a href="https://github.com/seiyashima"><img src="https://avatars2.githubusercontent.com/u/4947101?v=4?s=100" width="100px;" alt=""/><br /><sub><b>seiyashima42</b></sub></a><br /><a href="https://github.com/aws/jsii/issues?q=author%3Aseiyashima+label%3Abug" title="Bug reports">🐛</a> <a href="https://github.com/aws/jsii/commits?author=seiyashima" title="Code">💻</a> <a href="https://github.com/aws/jsii/commits?author=seiyashima" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/sullis"><img src="https://avatars3.githubusercontent.com/u/30938?v=4?s=100" width="100px;" alt=""/><br /><sub><b>sullis</b></sub></a><br /><a href="https://github.com/aws/jsii/commits?author=sullis" title="Code">💻</a></td>
Expand Down
10 changes: 4 additions & 6 deletions gh-pages/content/user-guides/lib-user/language-specific/go.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,8 @@ following convention: `New<ClassName>_Override`, and receives the *overriding*
struct instance as the first parameter.

The **go** `struct` that *extends* the base *jsii class* must anonymously embed
the *jsii class*' **go** interface, while specifying the `overrides:"..."` field
tag. The value of the tag is a comma-separated list of **go** methods that are
locally overridden (note: in the case of *property accessors*, the *getter* name
is to be used, even if only the *setter* is overridden).
the *jsii class*' **go** interface. All overridden method *must* be defined
using a pointer receiver.

Assuming the following abstract base class:

Expand Down Expand Up @@ -165,8 +163,8 @@ import (
)

type childClass struct {
// We implement AbstractMethod, AbstractReadonlyProperty, and override the setter for ConcreteProperty
jsiimodule.AbstractBaseClass `overrides:"AbstractMethod,AbstractReadonlyProperty,ConcreteProperty"`
// Anonymous embed of the "base class".
jsiimodule.AbstractBaseClass

// Our own storage
stringValue string
Expand Down
31 changes: 15 additions & 16 deletions packages/@jsii/go-runtime-test/project/compliance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ func (suite *ComplianceSuite) TestEqualsIsResistantToPropertyShadowingResultVari
}

type overridableProtectedMemberDerived struct {
calc.OverridableProtectedMember `overrides:"OverrideReadOnly,OverrideReadWrite"`
calc.OverridableProtectedMember
}

func newOverridableProtectedMemberDerived() *overridableProtectedMemberDerived {
Expand Down Expand Up @@ -381,7 +381,7 @@ func newImplementsAdditionalInterface(s calc.StructB) *implementsAdditionalInter
return &n
}

func (x implementsAdditionalInterface) ReturnStruct() *calc.StructB {
func (x *implementsAdditionalInterface) ReturnStruct() *calc.StructB {
return &x._struct
}

Expand Down Expand Up @@ -500,7 +500,7 @@ func (suite *ComplianceSuite) TestCallbacksCorrectlyDeserializeArguments() {
}

type testCallbacksCorrectlyDeserializeArgumentsDataRenderer struct {
calc.DataRenderer `overrides:"RenderMap"`
calc.DataRenderer
}

func NewTestCallbacksCorrectlyDeserializeArgumentsDataRenderer() *testCallbacksCorrectlyDeserializeArgumentsDataRenderer {
Expand Down Expand Up @@ -610,7 +610,7 @@ func (suite *ComplianceSuite) TestNullShouldBeTreatedAsUndefined() {
}

type myOverridableProtectedMember struct {
calc.OverridableProtectedMember `overrides:"OverrideMe"`
calc.OverridableProtectedMember
}

func newMyOverridableProtectedMember() *myOverridableProtectedMember {
Expand All @@ -619,7 +619,7 @@ func newMyOverridableProtectedMember() *myOverridableProtectedMember {
return &m
}

func (x myOverridableProtectedMember) OverrideMe() *string {
func (x *myOverridableProtectedMember) OverrideMe() *string {
return jsii.String("Cthulhu Fhtagn!")
}

Expand Down Expand Up @@ -685,7 +685,7 @@ func (suite *ComplianceSuite) TestMapReturnedByMethodCanBeRead() {
}

type myAbstractSuite struct {
calc.AbstractSuite `overrides:"SomeMethod,Property"`
calc.AbstractSuite

_property *string
}
Expand Down Expand Up @@ -724,10 +724,10 @@ func (suite *ComplianceSuite) TestCanOverrideProtectedSetter() {
}

type TestCanOverrideProtectedSetterOverridableProtectedMember struct {
calc.OverridableProtectedMember `overrides:"OverrideReadWrite"`
calc.OverridableProtectedMember
}

func (x TestCanOverrideProtectedSetterOverridableProtectedMember) SetOverrideReadWrite(val *string) {
func (x *TestCanOverrideProtectedSetterOverridableProtectedMember) SetOverrideReadWrite(val *string) {
x.OverridableProtectedMember.SetOverrideReadWrite(jsii.String(fmt.Sprintf("zzzzzzzzz%s", *val)))
}

Expand All @@ -737,7 +737,6 @@ func newTestCanOverrideProtectedSetterOverridableProtectedMember() *TestCanOverr
return &m
}


func (suite *ComplianceSuite) TestObjRefsAreLabelledUsingWithTheMostCorrectType() {
require := suite.Require()

Expand Down Expand Up @@ -952,7 +951,7 @@ func (suite *ComplianceSuite) TestPropertyOverrides_Get_Calls_Super() {
}

type testPropertyOverridesGetCallsSuper struct {
calc.SyncVirtualMethods `overrides:"TheProperty"`
calc.SyncVirtualMethods
}

func (t *testPropertyOverridesGetCallsSuper) TheProperty() *string {
Expand Down Expand Up @@ -1063,7 +1062,7 @@ func (suite *ComplianceSuite) TestPropertyOverrides_Get_Throws() {
}

type testPropertyOverridesGetThrows struct {
calc.SyncVirtualMethods `overrides:"TheProperty"`
calc.SyncVirtualMethods
}

func (t *testPropertyOverridesGetThrows) TheProperty() *string {
Expand Down Expand Up @@ -1143,7 +1142,7 @@ func (suite *ComplianceSuite) TestPropertyOverrides_Set_Calls_Super() {
}

type testPropertyOverridesSetCallsSuper struct {
calc.SyncVirtualMethods `overrides:"TheProperty"`
calc.SyncVirtualMethods
}

func (t *testPropertyOverridesSetCallsSuper) SetTheProperty(value *string) {
Expand Down Expand Up @@ -1327,8 +1326,8 @@ func (suite *ComplianceSuite) TestObjectIdDoesNotGetReallocatedWhenTheConstructo
}

type partiallyInitializedThisConsumerImpl struct {
calc.PartiallyInitializedThisConsumer `overrides:"ConsumePartiallyInitializedThis"`
require *require.Assertions
calc.PartiallyInitializedThisConsumer
require *require.Assertions
}

func NewPartiallyInitializedThisConsumerImpl(assert *require.Assertions) *partiallyInitializedThisConsumerImpl {
Expand Down Expand Up @@ -1478,7 +1477,7 @@ func (suite *ComplianceSuite) TestPropertyOverrides_Set_Throws() {
}

type testPropertyOverrides_Set_ThrowsSyncVirtualMethods struct {
calc.SyncVirtualMethods `overrides:"TheProperty"`
calc.SyncVirtualMethods
}

func NewTestPropertyOverrides_Set_ThrowsSyncVirtualMethods() *testPropertyOverrides_Set_ThrowsSyncVirtualMethods {
Expand Down Expand Up @@ -1582,7 +1581,7 @@ func (suite *ComplianceSuite) TestAsyncOverrides_OverrideCallsSuper() {
}

type OverrideCallsSuper struct {
calc.AsyncVirtualMethods `overrides:"OverrideMe"`
calc.AsyncVirtualMethods
}

func (o *OverrideCallsSuper) OverrideMe(mult *float64) *float64 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
)

type OverrideAsyncMethods struct {
jsiicalc.AsyncVirtualMethods `overrides:"OverrideMe"`
jsiicalc.AsyncVirtualMethods
}

func New() *OverrideAsyncMethods {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import (
)

type SyncOverrides struct {
jsiicalc.SyncVirtualMethods `overrides:"VirtualMethod,TheProperty"`
AnotherTheProperty *string
Multiplier int
ReturnSuper bool
CallAsync bool
jsiicalc.SyncVirtualMethods
AnotherTheProperty *string
Multiplier int
ReturnSuper bool
CallAsync bool
}

func New() *SyncOverrides {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
)

type TwoOverrides struct {
jsiicalc.AsyncVirtualMethods `overrides:"OverrideMe,OverrideMeToo"`
jsiicalc.AsyncVirtualMethods
}

func New() *TwoOverrides {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func (w *WallClock) Iso8601Now() *string {
}

type Entropy struct {
jsiicalc.Entropy `overrides:"Repeat"`
jsiicalc.Entropy
}

func NewEntropy(clock jsiicalc.IWallClock) *Entropy {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package jsii

import (
"reflect"
"sort"
"testing"
)

type IFace interface {
M1()
M2()
M3()
}

type Base struct {
X, Y int
}

func (b *Base) M1() {}
func (b *Base) M2() {}
func (b *Base) M3() {}

type D1 struct {
*Base
}

func (d *D1) M1() {}

func (d *D1) X1() {}

type D2 struct {
Name string
IFace
}

func (d *D2) M2() {}

func (d *D2) X2() {}

func TestOverrideReflection(t *testing.T) {
testCases := [...]struct {
//overriding instance
val interface{}
//instance overriding methods
methods []string
}{
{&Base{}, []string(nil)},
{&D1{&Base{}}, []string{"M1", "X1"}},
{&D2{Name: "abc", IFace: &D1{&Base{}}}, []string{"M1", "X1", "M2", "X2"}},
}
for _, tc := range testCases {
sort.Slice(tc.methods, func(i, j int) bool {
return tc.methods[i] < tc.methods[j]
})
}
for _, tc := range testCases {
methods := getMethodOverrides(tc.val, "Base")
sort.Slice(methods, func(i, j int) bool {
return methods[i] < methods[j]
})
if !reflect.DeepEqual(methods, tc.methods) {
t.Errorf("expect: %v, got: %v", tc.methods, methods)
}
}
}
Loading