diff --git a/gh-pages/content/specification/6-compliance-report.md b/gh-pages/content/specification/6-compliance-report.md index ca798d0e96..080bfb9cf9 100644 --- a/gh-pages/content/specification/6-compliance-report.md +++ b/gh-pages/content/specification/6-compliance-report.md @@ -5,7 +5,7 @@ This section details the current state of each language binding with respect to our standard compliance suite. -| number | test | java (100.00%) | golang (70.09%) | Dotnet | Python | +| number | test | java (100.00%) | golang (73.50%) | Dotnet | Python | | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- | -------------------------------------------- | ------ | ------ | | 1 | asyncOverrides_overrideCallsSuper | 🟢 | [🔴](https://github.com/aws/jsii/issues/2670) | ⭕ | ⭕ | | 2 | [arrayReturnedByMethodCanBeRead]("Array created in the kernel can be queried for its elements") | 🟢 | 🟢 | ⭕ | ⭕ | @@ -28,7 +28,7 @@ This section details the current state of each language binding with respect to | 19 | [doNotOverridePrivates_method_private]("Non public methods on the guest class do not override methods in the host class") | 🟢 | 🟢 | ⭕ | ⭕ | | 20 | [pureInterfacesCanBeUsedTransparently]("Guest implementation of a pure host interface can be used by host consumers accepting that interface") | 🟢 | 🟢 | ⭕ | ⭕ | | 21 | [nullShouldBeTreatedAsUndefined]("Null value of target language is treated as undefined by the host") | 🟢 | 🟢 | ⭕ | ⭕ | -| 22 | [primitiveTypes]("All Primitive types are set and read with their respective types") | 🟢 | [🔴](https://github.com/aws/jsii/issues/2659) | ⭕ | ⭕ | +| 22 | [primitiveTypes]("All Primitive types are set and read with their respective types") | 🟢 | 🟢 | ⭕ | ⭕ | | 23 | [reservedKeywordsAreSlugifiedInClassProperties]("TS code that uses reserved words as class property names get slugified so it is usable in the target language") | 🟢 | ⚪ | ⭕ | ⭕ | | 24 | [objectIdDoesNotGetReallocatedWhenTheConstructorPassesThisOut]("Ensure the JSII kernel can pass 'this' out to JSII remotes from within the constructor") | 🟢 | 🟢 | ⭕ | ⭕ | | 25 | [interfaceBuilder]("Seems to be a duplicate of 'propertyOverrides_interfaces'?") | 🟢 | 🟢 | ⭕ | ⭕ | @@ -52,7 +52,7 @@ This section details the current state of each language binding with respect to | 43 | doNotOverridePrivates_property_getter_public | 🟢 | 🟢 | ⭕ | ⭕ | | 44 | equalsIsResistantToPropertyShadowingResultVariable | 🟢 | 🟢 | ⭕ | ⭕ | | 45 | listInClassCanBeReadCorrectly | 🟢 | 🟢 | ⭕ | ⭕ | -| 46 | useNestedStruct | 🟢 | [🔴](https://github.com/aws/jsii/pull/2650) | ⭕ | ⭕ | +| 46 | useNestedStruct | 🟢 | 🟢 | ⭕ | ⭕ | | 47 | testFluentApiWithDerivedClasses | 🟢 | 🟢 | ⭕ | ⭕ | | 48 | interfacesCanBeUsedTransparently_WhenAddedToJsiiType | 🟢 | 🟢 | ⭕ | ⭕ | | 49 | canOverrideProtectedGetter | 🟢 | [🔴](https://github.com/aws/jsii/issues/2673) | ⭕ | ⭕ | @@ -69,7 +69,7 @@ This section details the current state of each language binding with respect to | 60 | canOverrideProtectedSetter | 🟢 | [🔴](https://github.com/aws/jsii/issues/2673) | ⭕ | ⭕ | | 61 | asyncOverrides_callAsyncMethod | 🟢 | [🔴](https://github.com/aws/jsii/issues/2670) | ⭕ | ⭕ | | 62 | nodeStandardLibrary | 🟢 | [🔴](https://github.com/aws/jsii/issues/2670) | ⭕ | ⭕ | -| 63 | dates | 🟢 | [🔴](https://github.com/aws/jsii/issues/2659) | ⭕ | ⭕ | +| 63 | dates | 🟢 | 🟢 | ⭕ | ⭕ | | 64 | collectionOfInterfaces_ListOfStructs | 🟢 | 🟢 | ⭕ | ⭕ | | 65 | objRefsAreLabelledUsingWithTheMostCorrectType | 🟢 | 🔴 | ⭕ | ⭕ | | 66 | unionPropertiesWithBuilder | 🟢 | 🟢 | ⭕ | ⭕ | @@ -86,7 +86,7 @@ This section details the current state of each language binding with respect to | 77 | asyncOverrides_overrideThrows | 🟢 | [🔴](https://github.com/aws/jsii/issues/2670) | ⭕ | ⭕ | | 78 | callMethods | 🟢 | 🟢 | ⭕ | ⭕ | | 79 | returnAbstract | 🟢 | 🟢 | ⭕ | ⭕ | -| 80 | dynamicTypes | 🟢 | [🔴](https://github.com/aws/jsii/issues/2659) | ⭕ | ⭕ | +| 80 | dynamicTypes | 🟢 | 🟢 | ⭕ | ⭕ | | 81 | hashCodeIsResistantToPropertyShadowingResultVariable | 🟢 | ⚪ | ⭕ | ⭕ | | 82 | returnSubclassThatImplementsInterface976 | 🟢 | 🟢 | ⭕ | ⭕ | | 83 | structs_optionalEquals | 🟢 | ⚪ | ⭕ | ⭕ | diff --git a/packages/@jsii/go-runtime-test/project/compliance_test.go b/packages/@jsii/go-runtime-test/project/compliance_test.go index 1170864106..7c0c368e84 100644 --- a/packages/@jsii/go-runtime-test/project/compliance_test.go +++ b/packages/@jsii/go-runtime-test/project/compliance_test.go @@ -62,21 +62,16 @@ func (suite *ComplianceSuite) TestPrimitiveTypes() { types.SetNumberProperty(jsii.Number(1234)) assert.Equal(float64(1234), *types.NumberProperty()) - // // json + // json mapProp := map[string]interface{}{"Foo": map[string]interface{}{"Bar": 123}} types.SetJsonProperty(&mapProp) assert.Equal(float64(123), (*types.JsonProperty())["Foo"].(map[string]interface{})["Bar"]) - suite.FailTest("Dates are currently treated as strings and fail going through the wire", "https://github.com/aws/jsii/issues/2659") - - // whoops - should accept time.Time, not string. - // date - types.SetDateProperty(jsii.String("12345")) - assert.Equal("12345", types.DateProperty()) + types.SetDateProperty(jsii.Time(time.Unix(0, 123000000))) + assert.WithinDuration(time.Unix(0, 123000000), *types.DateProperty(), 0) } func (suite *ComplianceSuite) TestUseNestedStruct() { - suite.FailTest("Nested types are not namespaced", "https://github.com/aws/jsii/pull/2650") jcb.StaticConsumer_Consume(customsubmodulename.NestingClass_NestedStruct{ Name: jsii.String("Bond, James Bond"), }) @@ -128,15 +123,14 @@ func (suite *ComplianceSuite) TestMaps() { func (suite *ComplianceSuite) TestDates() { assert := suite.Assert() - suite.FailTest("Dates are represented as strings instead of date objects", "https://github.com/aws/jsii/issues/2659") types := calc.NewAllTypes() - //types.SetDateProperty(time.Unix(128, 0)) - assert.Equal(time.Unix(128, 0), types.DateProperty()) + types.SetDateProperty(jsii.Time(time.Unix(128, 0))) + assert.WithinDuration(time.Unix(128, 0), *types.DateProperty(), 0) // weak type types.SetAnyProperty(time.Unix(999, 0)) - assert.Equal(time.Unix(999, 0), types.AnyProperty()) + assert.WithinDuration(time.Unix(999, 0), types.AnyProperty().(time.Time), 0) } func (suite *ComplianceSuite) TestCallMethods() { @@ -226,9 +220,7 @@ func (suite *ComplianceSuite) TestDynamicTypes() { // date types.SetAnyProperty(time.Unix(1234, 0)) - if types.AnyProperty() != time.Unix(1234, 0) { - suite.FailTest("Dates not supported", "https://github.com/aws/jsii/issues/2659") - } + assert.WithinDuration(time.Unix(1234, 0), types.AnyProperty().(time.Time), 0) } func (suite *ComplianceSuite) TestArrayReturnedByMethodCanBeRead() { @@ -1175,7 +1167,6 @@ func (suite *ComplianceSuite) TestUndefinedAndNull() { func (suite *ComplianceSuite) TestStructs_SerializeToJsii() { t := suite.T() - t.Skip("DateTime fields are not implemented yet") firstStruct := calclib.MyFirstStruct{ Astring: jsii.String("FirstString"), @@ -1186,12 +1177,12 @@ func (suite *ComplianceSuite) TestStructs_SerializeToJsii() { doubleTrouble := calc.NewDoubleTrouble() derivedStruct := calc.DerivedStruct{ - NonPrimitive: doubleTrouble, - Bool: jsii.Bool(false), - // TODO: AnotherRequired: time.Now(), - Astring: jsii.String("String"), - Anumber: jsii.Number(1234), - FirstOptional: &[]*string{jsii.String("one"), jsii.String("two")}, + NonPrimitive: doubleTrouble, + Bool: jsii.Bool(false), + AnotherRequired: jsii.Time(time.Now()), + Astring: jsii.String("String"), + Anumber: jsii.Number(1234), + FirstOptional: &[]*string{jsii.String("one"), jsii.String("two")}, } gms := calc.NewGiveMeStructs() @@ -1334,8 +1325,8 @@ func NewPartiallyInitializedThisConsumerImpl(assert *assert.Assertions) *partial return &p } -func (p *partiallyInitializedThisConsumerImpl) ConsumePartiallyInitializedThis(obj calc.ConstructorPassesThisOut, dt *string, ev calc.AllTypesEnum) *string { - epoch := time.Date(1970, time.January, 1, 0, 0, 0, 0, time.UTC).Format("2006-01-02T15:04:05.000Z07:00") +func (p *partiallyInitializedThisConsumerImpl) ConsumePartiallyInitializedThis(obj calc.ConstructorPassesThisOut, dt *time.Time, ev calc.AllTypesEnum) *string { + epoch := time.Date(1970, time.January, 1, 0, 0, 0, 0, time.UTC) p.assert.NotNil(obj) p.assert.Equal(epoch, *dt) diff --git a/packages/@jsii/go-runtime/jsii-runtime-go/internal/api/api.go b/packages/@jsii/go-runtime/jsii-runtime-go/internal/api/api.go index 83d354b8b1..259a133d4a 100644 --- a/packages/@jsii/go-runtime/jsii-runtime-go/internal/api/api.go +++ b/packages/@jsii/go-runtime/jsii-runtime-go/internal/api/api.go @@ -83,6 +83,10 @@ type EnumRef struct { MemberFQN string `json:"$jsii.enum"` } +type WireDate struct { + Timestamp string `json:"$jsii.date"` +} + type WireMap struct { MapData map[string]interface{} `json:"$jsii.map"` } diff --git a/packages/@jsii/go-runtime/jsii-runtime-go/internal/kernel/conversions.go b/packages/@jsii/go-runtime/jsii-runtime-go/internal/kernel/conversions.go index 1332aea503..8f718165e0 100644 --- a/packages/@jsii/go-runtime/jsii-runtime-go/internal/kernel/conversions.go +++ b/packages/@jsii/go-runtime/jsii-runtime-go/internal/kernel/conversions.go @@ -2,6 +2,7 @@ package kernel import ( "reflect" + "time" "github.com/aws/jsii-runtime-go/internal/api" ) @@ -126,6 +127,11 @@ func (c *Client) CastPtrToRef(dataVal reflect.Value) interface{} { return nil } + // In case we got a time.Time value (or pointer to one). + if wireDate, isDate := castPtrToDate(dataVal); isDate { + return wireDate + } + switch dataVal.Kind() { case reflect.Map: result := api.WireMap{MapData: make(map[string]interface{})} @@ -192,6 +198,24 @@ func (c *Client) CastPtrToRef(dataVal reflect.Value) interface{} { return dataVal.Interface() } +// castPtrToDate obtains an api.WireDate from the provided reflect.Value if it +// represents a time.Time or *time.Time value. It accepts both a pointer and +// direct value as a convenience (when passing time.Time through an interface{} +// parameter, having to unwrap it as a pointer is annoying and unneeded). +func castPtrToDate(data reflect.Value) (wireDate api.WireDate, ok bool) { + var timestamp *time.Time + if timestamp, ok = data.Interface().(*time.Time); !ok { + var val time.Time + if val, ok = data.Interface().(time.Time); ok { + timestamp = &val + } + } + if ok { + wireDate.Timestamp = timestamp.Format(time.RFC3339Nano) + } + return +} + func castValToRef(data reflect.Value) (ref api.ObjectRef, ok bool) { if data.Kind() == reflect.Map { for _, k := range data.MapKeys() { @@ -234,13 +258,14 @@ func castValToRef(data reflect.Value) (ref api.ObjectRef, ok bool) { } // TODO: This should return a time.Time instead -func castValToDate(data reflect.Value) (date string, ok bool) { +func castValToDate(data reflect.Value) (date time.Time, ok bool) { if data.Kind() == reflect.Map { for _, k := range data.MapKeys() { v := reflect.ValueOf(data.MapIndex(k).Interface()) if k.Kind() == reflect.String && k.String() == "$jsii.date" && v.Kind() == reflect.String { - date = v.String() - ok = true + var err error + date, err = time.Parse(time.RFC3339Nano, v.String()) + ok = (err == nil) break } } diff --git a/packages/@jsii/go-runtime/jsii-runtime-go/runtime.go b/packages/@jsii/go-runtime/jsii-runtime-go/runtime.go index 19ed07277a..8810d8b552 100644 --- a/packages/@jsii/go-runtime/jsii-runtime-go/runtime.go +++ b/packages/@jsii/go-runtime/jsii-runtime-go/runtime.go @@ -4,6 +4,7 @@ import ( "fmt" "reflect" "strings" + "time" "github.com/aws/jsii-runtime-go/internal/api" "github.com/aws/jsii-runtime-go/internal/kernel" @@ -371,7 +372,14 @@ func Close() { kernel.CloseClient() } -// Helpers to store primitives and return pointers to them -func Bool(v bool) *bool { return &v } -func Number(v float64) *float64 { return &v } -func String(v string) *string { return &v } +// Bool obtains a pointer to the provided bool. +func Bool(v bool) *bool { return &v } + +// Number obtains a pointer to the provided float64. +func Number(v float64) *float64 { return &v } + +// String obtains a pointer to the provided string. +func String(v string) *string { return &v } + +// Time obtains a pointer to the provided time.Time. +func Time(v time.Time) *time.Time { return &v } diff --git a/packages/jsii-pacmak/lib/targets/go/dependencies.ts b/packages/jsii-pacmak/lib/targets/go/dependencies.ts new file mode 100644 index 0000000000..a0996b43a9 --- /dev/null +++ b/packages/jsii-pacmak/lib/targets/go/dependencies.ts @@ -0,0 +1,17 @@ +/** + * Information about a module's dependency on "special" packages (either part of + * the go standard library, or generated as part of the current module). + */ +export interface SpecialDependencies { + /** Whether the jsii runtime library for go is needed */ + readonly runtime: boolean; + + /** Whether the package's initialization hook is needed */ + readonly init: boolean; + + /** Whether the internal type aliases package is needed */ + readonly internal: boolean; + + /** Whether go's standard library "time" module is needed */ + readonly time: boolean; +} diff --git a/packages/jsii-pacmak/lib/targets/go/package.ts b/packages/jsii-pacmak/lib/targets/go/package.ts index a0fab51c38..7aad56afc8 100644 --- a/packages/jsii-pacmak/lib/targets/go/package.ts +++ b/packages/jsii-pacmak/lib/targets/go/package.ts @@ -4,6 +4,7 @@ import { basename, dirname, join } from 'path'; import * as semver from 'semver'; import { VERSION } from '../../version'; +import { SpecialDependencies } from './dependencies'; import { EmitContext } from './emit-context'; import { ReadmeFile } from './readme-file'; import { @@ -184,16 +185,18 @@ export abstract class Package { code.line(); } - protected get usesRuntimePackage(): boolean { - return this.types.some((type) => type.usesRuntimePackage); - } - - protected get usesInitPackage(): boolean { - return this.types.some((type) => type.usesInitPackage); - } - - protected get usesInternalPackage(): boolean { - return this.types.some((type) => type.usesInternalPackage); + protected get specialDependencies(): SpecialDependencies { + return this.types + .map((t) => t.specialDependencies) + .reduce( + (acc, elt) => ({ + runtime: acc.runtime || elt.runtime, + init: acc.init || elt.init, + internal: acc.internal || elt.internal, + time: acc.time || elt.time, + }), + { runtime: false, init: false, internal: false, time: false }, + ); } /** @@ -229,18 +232,24 @@ export abstract class Package { private emitImports(code: CodeMaker) { const toImport = new Array(); - if (this.usesRuntimePackage) { + const specialDeps = this.specialDependencies; + + if (specialDeps.time) { + toImport.push({ module: 'time' }); + } + + if (specialDeps.runtime) { toImport.push(JSII_RT_MODULE); } - if (this.usesInitPackage) { + if (specialDeps.init) { toImport.push({ alias: JSII_INIT_ALIAS, module: `${this.root.goModuleName}/${JSII_INIT_PACKAGE}`, }); } - if (this.usesInternalPackage) { + if (specialDeps.internal) { toImport.push({ module: `${this.goModuleName}/${INTERNAL_PACKAGE_NAME}`, }); @@ -611,7 +620,9 @@ function importGoModules(code: CodeMaker, modules: readonly ImportedModule[]) { } function isBuiltIn(mod: ImportedModule): boolean { - return !mod.module.includes('/'); + // Standard library modules don't have any "." in their path, whereas any + // other module has a DNS portion in them, which must include a ".". + return !mod.module.includes('.'); } function isSpecial(mod: ImportedModule): boolean { diff --git a/packages/jsii-pacmak/lib/targets/go/types/class.ts b/packages/jsii-pacmak/lib/targets/go/types/class.ts index 6566dbdd27..142bd1edd4 100644 --- a/packages/jsii-pacmak/lib/targets/go/types/class.ts +++ b/packages/jsii-pacmak/lib/targets/go/types/class.ts @@ -3,6 +3,7 @@ import { Method, ClassType, Initializer } from 'jsii-reflect'; import { jsiiToPascalCase } from '../../../naming-util'; import * as comparators from '../comparators'; +import { SpecialDependencies } from '../dependencies'; import { EmitContext } from '../emit-context'; import { Package } from '../package'; import { @@ -155,18 +156,17 @@ export class GoClass extends GoType { ]; } - public get usesInitPackage() { - return ( - this.initializer != null || this.members.some((m) => m.usesInitPackage) - ); - } - - public get usesRuntimePackage() { - return this.initializer != null || this.members.length > 0; - } - - public get usesInternalPackage() { - return this.baseTypes.some((base) => this.pkg.isExternalType(base)); + public get specialDependencies(): SpecialDependencies { + return { + runtime: this.initializer != null || this.members.length > 0, + init: + this.initializer != null || + this.members.some((m) => m.specialDependencies.init), + internal: this.baseTypes.some((base) => this.pkg.isExternalType(base)), + time: + !!this.initializer?.specialDependencies.time || + this.members.some((m) => m.specialDependencies.time), + }; } protected emitInterface(context: EmitContext): void { @@ -276,9 +276,6 @@ export class GoClass extends GoType { } export class GoClassConstructor extends GoMethod { - public readonly usesInitPackage = true; - public readonly usesRuntimePackage = true; - private readonly constructorRuntimeCall: ClassConstructor; public constructor( @@ -289,6 +286,15 @@ export class GoClassConstructor extends GoMethod { this.constructorRuntimeCall = new ClassConstructor(this); } + public get specialDependencies(): SpecialDependencies { + return { + runtime: true, + init: true, + internal: false, + time: this.parameters.some((p) => p.reference.specialDependencies.time), + }; + } + public emit(context: EmitContext) { // Abstract classes cannot be directly created if (!this.parent.type.abstract) { @@ -332,8 +338,6 @@ export class GoClassConstructor extends GoMethod { export class ClassMethod extends GoMethod { public readonly runtimeCall: MethodCall; - public readonly usesInitPackage: boolean = false; - public readonly usesRuntimePackage = true; public constructor( public readonly parent: GoClass, @@ -371,11 +375,20 @@ export class ClassMethod extends GoMethod { public get instanceArg(): string { return this.parent.name.substring(0, 1).toLowerCase(); } + + public get specialDependencies(): SpecialDependencies { + return { + runtime: true, + init: this.method.static, + internal: false, + time: + !!this.parameters.some((p) => p.reference.specialDependencies.time) || + !!this.reference?.specialDependencies.time, + }; + } } export class StaticMethod extends ClassMethod { - public readonly usesInitPackage = true; - public constructor( public readonly parent: GoClass, public readonly method: Method, diff --git a/packages/jsii-pacmak/lib/targets/go/types/enum.ts b/packages/jsii-pacmak/lib/targets/go/types/enum.ts index 8e869b08b5..ea5ff70c5a 100644 --- a/packages/jsii-pacmak/lib/targets/go/types/enum.ts +++ b/packages/jsii-pacmak/lib/targets/go/types/enum.ts @@ -1,16 +1,13 @@ import { CodeMaker } from 'codemaker'; import { EnumType, EnumMember } from 'jsii-reflect'; +import { SpecialDependencies } from '../dependencies'; import { EmitContext } from '../emit-context'; import { Package } from '../package'; import { JSII_RT_ALIAS } from '../runtime'; import { GoType } from './go-type'; export class Enum extends GoType { - public readonly usesInitPackage = false; - public readonly usesRuntimePackage = false; - public readonly usesInternalPackage = false; - private readonly members: readonly GoEnumMember[]; public constructor(pkg: Package, public type: EnumType) { @@ -53,6 +50,15 @@ export class Enum extends GoType { public get dependencies(): Package[] { return []; } + + public get specialDependencies(): SpecialDependencies { + return { + runtime: false, + init: false, + internal: false, + time: false, + }; + } } class GoEnumMember { diff --git a/packages/jsii-pacmak/lib/targets/go/types/go-type-reference.ts b/packages/jsii-pacmak/lib/targets/go/types/go-type-reference.ts index 4383ec2f49..6f3d0c9dda 100644 --- a/packages/jsii-pacmak/lib/targets/go/types/go-type-reference.ts +++ b/packages/jsii-pacmak/lib/targets/go/types/go-type-reference.ts @@ -1,6 +1,7 @@ import { TypeReference } from 'jsii-reflect'; import * as log from '../../../logging'; +import { SpecialDependencies } from '../dependencies'; import { Package } from '../package'; import { GoType } from './go-type'; @@ -12,8 +13,7 @@ class PrimitiveMapper { number: 'float64', boolean: 'bool', any: 'interface{}', - // TODO: Resolve "time" package dependency where needed and change to "time.Time" - date: 'string', + date: 'time.Time', string: 'string', json: `map[string]interface{}`, }; @@ -60,6 +60,31 @@ export class GoTypeRef { return undefined; } + public get specialDependencies(): SpecialDependencies { + return { + runtime: false, + init: false, + internal: false, + time: containsDate(this.reference), + }; + + function containsDate(ref: TypeReference): boolean { + if (ref.primitive === 'date') { + return true; + } + if (ref.arrayOfType) { + return containsDate(ref.arrayOfType); + } + if (ref.mapOfType) { + return containsDate(ref.mapOfType); + } + if (ref.unionOfTypes) { + return ref.unionOfTypes.some(containsDate); + } + return false; + } + } + public get primitiveType() { if (this.reference.primitive) { return new PrimitiveMapper(this.reference.primitive).goPrimitive; diff --git a/packages/jsii-pacmak/lib/targets/go/types/go-type.ts b/packages/jsii-pacmak/lib/targets/go/types/go-type.ts index dd3839c4c3..7ccbe2f9c8 100644 --- a/packages/jsii-pacmak/lib/targets/go/types/go-type.ts +++ b/packages/jsii-pacmak/lib/targets/go/types/go-type.ts @@ -1,6 +1,7 @@ import { CodeMaker } from 'codemaker'; import { Type } from 'jsii-reflect'; +import { SpecialDependencies } from '../dependencies'; import { EmitContext } from '../emit-context'; import { Package } from '../package'; import { JSII_RT_ALIAS } from '../runtime'; @@ -36,9 +37,7 @@ export abstract class GoType { public abstract emitRegistration(code: CodeMaker): void; public abstract get dependencies(): Package[]; - public abstract get usesInitPackage(): boolean; - public abstract get usesRuntimePackage(): boolean; - public abstract get usesInternalPackage(): boolean; + public abstract get specialDependencies(): SpecialDependencies; public get namespace() { return this.pkg.packageName; diff --git a/packages/jsii-pacmak/lib/targets/go/types/interface.ts b/packages/jsii-pacmak/lib/targets/go/types/interface.ts index 69c527400c..bd24c151d0 100644 --- a/packages/jsii-pacmak/lib/targets/go/types/interface.ts +++ b/packages/jsii-pacmak/lib/targets/go/types/interface.ts @@ -2,6 +2,7 @@ import { CodeMaker } from 'codemaker'; import { InterfaceType, Method, Property } from 'jsii-reflect'; import * as comparators from '../comparators'; +import { SpecialDependencies } from '../dependencies'; import { EmitContext } from '../emit-context'; import { Package } from '../package'; import { JSII_RT_ALIAS, MethodCall } from '../runtime'; @@ -141,24 +142,26 @@ export class GoInterface extends GoType { code.close(')'); } - public get usesInitPackage() { - return ( - this.properties.some((p) => p.usesInitPackage) || - this.methods.some((m) => m.usesInitPackage) - ); - } - - public get usesRuntimePackage() { - return ( - this.properties.some((p) => p.usesRuntimePackage) || - this.methods.some((m) => m.usesRuntimePackage) + public get specialDependencies(): SpecialDependencies { + return [ + ...this.properties.map((p) => p.specialDependencies), + ...this.methods.map((m) => m.specialDependencies), + ].reduce( + (acc, elt) => ({ + runtime: acc.runtime || elt.runtime, + init: acc.init || elt.init, + internal: acc.internal, + time: acc.time || elt.time, + }), + { + runtime: false, + init: false, + internal: this.extends.some((base) => this.pkg.isExternalType(base)), + time: false, + }, ); } - public get usesInternalPackage() { - return this.extends.some((base) => this.pkg.isExternalType(base)); - } - public get extends(): GoInterface[] { return this.type.interfaces .map((iface) => this.pkg.root.findType(iface.fqn) as GoInterface) @@ -219,8 +222,6 @@ class InterfaceProperty extends GoProperty { class InterfaceMethod extends GoMethod { public readonly runtimeCall: MethodCall; - public readonly usesInitPackage = false; - public readonly usesRuntimePackage = true; public constructor( public readonly parent: GoInterface, @@ -253,6 +254,17 @@ class InterfaceMethod extends GoMethod { code.line(); } + public get specialDependencies(): SpecialDependencies { + return { + runtime: true, + init: false, + internal: false, + time: + this.parameters.some((p) => p.reference.specialDependencies.time) || + !!this.reference?.specialDependencies.time, + }; + } + private get returnTypeString(): string { return this.reference?.void ? '' : ` ${this.returnType}`; } diff --git a/packages/jsii-pacmak/lib/targets/go/types/struct.ts b/packages/jsii-pacmak/lib/targets/go/types/struct.ts index cafbaad0d7..a1424b9497 100644 --- a/packages/jsii-pacmak/lib/targets/go/types/struct.ts +++ b/packages/jsii-pacmak/lib/targets/go/types/struct.ts @@ -2,6 +2,7 @@ import * as assert from 'assert'; import { CodeMaker } from 'codemaker'; import { InterfaceType } from 'jsii-reflect'; +import { SpecialDependencies } from '../dependencies'; import { EmitContext } from '../emit-context'; import { Package } from '../package'; import { JSII_RT_ALIAS } from '../runtime'; @@ -13,10 +14,6 @@ import { GoProperty } from './type-member'; * Struct wraps a JSII datatype interface aka, structs */ export class Struct extends GoType { - public readonly usesRuntimePackage = false; - public readonly usesInitPackage = false; - public readonly usesInternalPackage = false; - private readonly properties: readonly GoProperty[]; public constructor(parent: Package, public readonly type: InterfaceType) { @@ -36,6 +33,15 @@ export class Struct extends GoType { return getMemberDependencies(this.properties); } + public get specialDependencies(): SpecialDependencies { + return { + runtime: false, + init: false, + internal: false, + time: this.properties.some((prop) => prop.specialDependencies.time), + }; + } + public emit(context: EmitContext): void { const { code, documenter } = context; documenter.emit(this.type.docs); diff --git a/packages/jsii-pacmak/lib/targets/go/types/type-member.ts b/packages/jsii-pacmak/lib/targets/go/types/type-member.ts index 5d27b7c696..2e75c089ad 100644 --- a/packages/jsii-pacmak/lib/targets/go/types/type-member.ts +++ b/packages/jsii-pacmak/lib/targets/go/types/type-member.ts @@ -1,6 +1,7 @@ import { Callable, Method, Parameter, Property } from 'jsii-reflect'; import { jsiiToPascalCase } from '../../../naming-util'; +import { SpecialDependencies } from '../dependencies'; import { EmitContext } from '../emit-context'; import { GetProperty, JSII_RT_ALIAS, SetProperty } from '../runtime'; import { substituteReservedWords } from '../util'; @@ -16,8 +17,7 @@ export interface GoTypeMember { reference?: GoTypeRef; returnType: string; - usesInitPackage: boolean; - usesRuntimePackage: boolean; + specialDependencies: SpecialDependencies; } /* @@ -41,12 +41,13 @@ export class GoProperty implements GoTypeMember { } } - public get usesInitPackage() { - return this.static; - } - - public get usesRuntimePackage() { - return true; + public get specialDependencies(): SpecialDependencies { + return { + runtime: true, + init: this.static, + internal: false, + time: !!this.reference?.specialDependencies.time, + }; } public get static(): boolean { @@ -157,8 +158,8 @@ export abstract class GoMethod implements GoTypeMember { } public abstract emit(context: EmitContext): void; - public abstract get usesInitPackage(): boolean; - public abstract get usesRuntimePackage(): boolean; + + public abstract get specialDependencies(): SpecialDependencies; public get returnsRef(): boolean { if ( diff --git a/packages/jsii-pacmak/test/generated-code/__snapshots__/prerelease-identifiers.test.ts.snap b/packages/jsii-pacmak/test/generated-code/__snapshots__/prerelease-identifiers.test.ts.snap index 6c73a2332c..d949ab5da1 100644 --- a/packages/jsii-pacmak/test/generated-code/__snapshots__/prerelease-identifiers.test.ts.snap +++ b/packages/jsii-pacmak/test/generated-code/__snapshots__/prerelease-identifiers.test.ts.snap @@ -146,11 +146,10 @@ exports[`foo@1.2.3 depends on bar@^2.0.0-rc.42: /go/foo/jsii/jsii.go 1`] package jsii import ( + bar "bar/v2/jsii" _ "embed" _jsii_ "github.com/aws/jsii-runtime-go" - - bar "bar/v2/jsii" ) //go:embed foo-1.2.3.tgz @@ -656,11 +655,10 @@ exports[`foo@1.2.3 depends on bar@^4.5.6-pre.1337: /go/foo/jsii/jsii.go package jsii import ( + bar "bar/v4/jsii" _ "embed" _jsii_ "github.com/aws/jsii-runtime-go" - - bar "bar/v4/jsii" ) //go:embed foo-1.2.3.tgz diff --git a/packages/jsii-pacmak/test/generated-code/__snapshots__/target-go.test.ts.snap b/packages/jsii-pacmak/test/generated-code/__snapshots__/target-go.test.ts.snap index da8c244e0a..6cd08127ed 100644 --- a/packages/jsii-pacmak/test/generated-code/__snapshots__/target-go.test.ts.snap +++ b/packages/jsii-pacmak/test/generated-code/__snapshots__/target-go.test.ts.snap @@ -2842,6 +2842,8 @@ exports[`Generated code for "jsii-calc": /go/jsiicalc/jsiicalc.go 1`] = package jsiicalc import ( + "time" + _jsii_ "github.com/aws/jsii-runtime-go" _init_ "github.com/aws/jsii/jsii-calc/go/jsiicalc/v3/jsii" @@ -3225,8 +3227,8 @@ type AllTypes interface { SetArrayProperty(val *[]*string) BooleanProperty() *bool SetBooleanProperty(val *bool) - DateProperty() *string - SetDateProperty(val *string) + DateProperty() *time.Time + SetDateProperty(val *time.Time) EnumProperty() AllTypesEnum SetEnumProperty(val AllTypesEnum) EnumPropertyValue() *float64 @@ -3312,8 +3314,8 @@ func (j *jsiiProxy_AllTypes) BooleanProperty() *bool { return returns } -func (j *jsiiProxy_AllTypes) DateProperty() *string { - var returns *string +func (j *jsiiProxy_AllTypes) DateProperty() *time.Time { + var returns *time.Time _jsii_.Get( j, "dateProperty", @@ -3517,7 +3519,7 @@ func (j *jsiiProxy_AllTypes) SetBooleanProperty(val *bool) { ) } -func (j *jsiiProxy_AllTypes) SetDateProperty(val *string) { +func (j *jsiiProxy_AllTypes) SetDateProperty(val *time.Time) { _jsii_.Set( j, "dateProperty", @@ -5807,7 +5809,7 @@ func (d *jsiiProxy_Default) PleaseCompile() { type DefaultedConstructorArgument interface { Arg1() *float64 Arg2() *string - Arg3() *string + Arg3() *time.Time } // The jsii proxy struct for DefaultedConstructorArgument @@ -5835,8 +5837,8 @@ func (j *jsiiProxy_DefaultedConstructorArgument) Arg2() *string { return returns } -func (j *jsiiProxy_DefaultedConstructorArgument) Arg3() *string { - var returns *string +func (j *jsiiProxy_DefaultedConstructorArgument) Arg3() *time.Time { + var returns *time.Time _jsii_.Get( j, "arg3", @@ -5846,7 +5848,7 @@ func (j *jsiiProxy_DefaultedConstructorArgument) Arg3() *string { } -func NewDefaultedConstructorArgument(arg1 *float64, arg2 *string, arg3 *string) DefaultedConstructorArgument { +func NewDefaultedConstructorArgument(arg1 *float64, arg2 *string, arg3 *time.Time) DefaultedConstructorArgument { _init_.Initialize() j := jsiiProxy_DefaultedConstructorArgument{} @@ -5860,7 +5862,7 @@ func NewDefaultedConstructorArgument(arg1 *float64, arg2 *string, arg3 *string) return &j } -func NewDefaultedConstructorArgument_Override(d DefaultedConstructorArgument, arg1 *float64, arg2 *string, arg3 *string) { +func NewDefaultedConstructorArgument_Override(d DefaultedConstructorArgument, arg1 *float64, arg2 *string, arg3 *time.Time) { _init_.Initialize() _jsii_.Create( @@ -6039,7 +6041,7 @@ type DerivedStruct struct { Astring *string \`json:"astring"\` // Deprecated. FirstOptional *[]*string \`json:"firstOptional"\` - AnotherRequired *string \`json:"anotherRequired"\` + AnotherRequired *time.Time \`json:"anotherRequired"\` Bool *bool \`json:"bool"\` // An example of a non primitive property. NonPrimitive DoubleTrouble \`json:"nonPrimitive"\` @@ -6056,7 +6058,7 @@ type DiamondBottom struct { Left *float64 \`json:"left"\` // Deprecated. Right *bool \`json:"right"\` - Bottom *string \`json:"bottom"\` + Bottom *time.Time \`json:"bottom"\` } type DiamondInheritanceBaseLevelStruct struct { @@ -8387,7 +8389,7 @@ func (j *jsiiProxy_ImplementsPrivateInterface) SetPrivate(val *string) { type ImplictBaseOfBase struct { Foo scopejsiicalcbaseofbase.Very \`json:"foo"\` Bar *string \`json:"bar"\` - Goo *string \`json:"goo"\` + Goo *time.Time \`json:"goo"\` } type InbetweenClass interface { @@ -10786,7 +10788,7 @@ func (o *jsiiProxy_OptionalArgumentInvoker) InvokeWithoutOptional() { type OptionalConstructorArgument interface { Arg1() *float64 Arg2() *string - Arg3() *string + Arg3() *time.Time } // The jsii proxy struct for OptionalConstructorArgument @@ -10814,8 +10816,8 @@ func (j *jsiiProxy_OptionalConstructorArgument) Arg2() *string { return returns } -func (j *jsiiProxy_OptionalConstructorArgument) Arg3() *string { - var returns *string +func (j *jsiiProxy_OptionalConstructorArgument) Arg3() *time.Time { + var returns *time.Time _jsii_.Get( j, "arg3", @@ -10825,7 +10827,7 @@ func (j *jsiiProxy_OptionalConstructorArgument) Arg3() *string { } -func NewOptionalConstructorArgument(arg1 *float64, arg2 *string, arg3 *string) OptionalConstructorArgument { +func NewOptionalConstructorArgument(arg1 *float64, arg2 *string, arg3 *time.Time) OptionalConstructorArgument { _init_.Initialize() j := jsiiProxy_OptionalConstructorArgument{} @@ -10839,7 +10841,7 @@ func NewOptionalConstructorArgument(arg1 *float64, arg2 *string, arg3 *string) O return &j } -func NewOptionalConstructorArgument_Override(o OptionalConstructorArgument, arg1 *float64, arg2 *string, arg3 *string) { +func NewOptionalConstructorArgument_Override(o OptionalConstructorArgument, arg1 *float64, arg2 *string, arg3 *time.Time) { _init_.Initialize() _jsii_.Create( @@ -11062,7 +11064,7 @@ type ParentStruct982 struct { } type PartiallyInitializedThisConsumer interface { - ConsumePartiallyInitializedThis(obj ConstructorPassesThisOut, dt *string, ev AllTypesEnum) *string + ConsumePartiallyInitializedThis(obj ConstructorPassesThisOut, dt *time.Time, ev AllTypesEnum) *string } // The jsii proxy struct for PartiallyInitializedThisConsumer @@ -11080,7 +11082,7 @@ func NewPartiallyInitializedThisConsumer_Override(p PartiallyInitializedThisCons ) } -func (p *jsiiProxy_PartiallyInitializedThisConsumer) ConsumePartiallyInitializedThis(obj ConstructorPassesThisOut, dt *string, ev AllTypesEnum) *string { +func (p *jsiiProxy_PartiallyInitializedThisConsumer) ConsumePartiallyInitializedThis(obj ConstructorPassesThisOut, dt *time.Time, ev AllTypesEnum) *string { var returns *string _jsii_.Invoke( @@ -11882,9 +11884,9 @@ func RootStructValidator_Validate(struct_ *RootStruct) { } type RuntimeTypeChecking interface { - MethodWithDefaultedArguments(arg1 *float64, arg2 *string, arg3 *string) + MethodWithDefaultedArguments(arg1 *float64, arg2 *string, arg3 *time.Time) MethodWithOptionalAnyArgument(arg interface{}) - MethodWithOptionalArguments(arg1 *float64, arg2 *string, arg3 *string) + MethodWithOptionalArguments(arg1 *float64, arg2 *string, arg3 *time.Time) } // The jsii proxy struct for RuntimeTypeChecking @@ -11916,7 +11918,7 @@ func NewRuntimeTypeChecking_Override(r RuntimeTypeChecking) { ) } -func (r *jsiiProxy_RuntimeTypeChecking) MethodWithDefaultedArguments(arg1 *float64, arg2 *string, arg3 *string) { +func (r *jsiiProxy_RuntimeTypeChecking) MethodWithDefaultedArguments(arg1 *float64, arg2 *string, arg3 *time.Time) { _jsii_.InvokeVoid( r, "methodWithDefaultedArguments", @@ -11933,7 +11935,7 @@ func (r *jsiiProxy_RuntimeTypeChecking) MethodWithOptionalAnyArgument(arg interf } // Used to verify verification of number of method arguments. -func (r *jsiiProxy_RuntimeTypeChecking) MethodWithOptionalArguments(arg1 *float64, arg2 *string, arg3 *string) { +func (r *jsiiProxy_RuntimeTypeChecking) MethodWithOptionalArguments(arg1 *float64, arg2 *string, arg3 *time.Time) { _jsii_.InvokeVoid( r, "methodWithOptionalArguments",