diff --git a/.gitignore b/.gitignore
index b7615a96eb..3afdbc282d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -368,3 +368,6 @@ jspm_packages/
# that NuGet uses for external packages. We don't want to ignore the
# lerna packages.
!/packages/*
+
+#MacOS metadata
+.DS_Store
\ No newline at end of file
diff --git a/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator.UnitTests/Class/AbstractClassProxyGeneratorTests.cs b/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator.UnitTests/Class/AbstractClassProxyGeneratorTests.cs
new file mode 100644
index 0000000000..bedc10ab15
--- /dev/null
+++ b/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator.UnitTests/Class/AbstractClassProxyGeneratorTests.cs
@@ -0,0 +1,188 @@
+using Amazon.JSII.Generator.Class;
+using Amazon.JSII.JsonModel.Spec;
+using Xunit;
+
+namespace Amazon.JSII.Generator.UnitTests.Class
+{
+ public class AbstractClassProxyGeneratorTests : GeneratorTestBase
+ {
+ private const string Prefix = nameof(Generator) + "." + nameof(AbstractClassProxyGenerator) + ".";
+
+ private string Render(ClassType classType)
+ {
+ Symbols.MapTypeToPackage("myFqn", classType.Assembly);
+ Symbols.MapNamespace(classType.QualifiedNamespace, "MyNamespace");
+ Symbols.MapTypeName("myFqn", "MyClass", TypeKind.Class);
+
+ var generator = new AbstractClassProxyGenerator(classType.Assembly, classType, Symbols, Namespaces);
+
+ var syntaxTree = generator.CreateSyntaxTree();
+ return syntaxTree.ToString();
+ }
+
+ [Fact(DisplayName = Prefix + nameof(IncludesAttribute))]
+ public void IncludesAttribute()
+ {
+ var classType = new ClassType
+ (
+ "myFqn",
+ "myPackage",
+ "myClass",
+ true,
+ initializer: new Method(true, false, false)
+ );
+
+ var actual = Render(classType);
+ var expected =
+ @"namespace MyNamespace
+{
+ [JsiiTypeProxy(typeof(MyClass), ""myFqn"")]
+ internal sealed class MyClassProxy : MyClass
+ {
+ private MyClassProxy(ByRefValue reference): base(reference)
+ {
+ }
+ }
+}";
+ Assert.Equal(expected, actual, ignoreLineEndingDifferences: true);
+ }
+
+ [Fact(DisplayName = Prefix + nameof(IncludesDocs))]
+ public void IncludesDocs()
+ {
+ // Docs are not currently generated as part of the C# code.
+ ClassType classType = new ClassType
+ (
+ fullyQualifiedName: "myFqn",
+ assembly: "myPackage",
+ name: "myClass",
+ isAbstract: true,
+ initializer: new Method(true, false, false),
+ docs: new Docs {{"foo", "bar"}}
+ );
+
+ string actual = Render(classType);
+ string expected =
+ @"namespace MyNamespace
+{
+ /// foo: bar
+ [JsiiTypeProxy(typeof(MyClass), ""myFqn"")]
+ internal sealed class MyClassProxy : MyClass
+ {
+ private MyClassProxy(ByRefValue reference): base(reference)
+ {
+ }
+ }
+}";
+ Assert.Equal(expected, actual, ignoreLineEndingDifferences: true);
+ }
+
+ [Fact(DisplayName = Prefix + nameof(IncludesProperties))]
+ public void IncludesProperties()
+ {
+ ClassType classType = new ClassType
+ (
+ fullyQualifiedName: "myFqn",
+ assembly: "myPackage",
+ name: "myClass",
+ isAbstract: true,
+ initializer: new Method(true, false, false),
+ properties: new[]
+ {
+ new Property
+ (
+ name: "myProp",
+ type: new TypeReference("myPropTypeFqn"),
+ isImmutable: false,
+ isAbstract: true,
+ isProtected: false
+ ),
+ new Property
+ (
+ name: "notMyProp",
+ type: new TypeReference("myPropTypeFqn"),
+ isImmutable: false,
+ isAbstract: false,
+ isProtected: false
+ )
+ }
+ );
+
+ Symbols.MapTypeName("myPropTypeFqn", "MyPropType", TypeKind.Class);
+ Symbols.MapPropertyName("myFqn", "myProp", "MyProp");
+
+ string actual = Render(classType);
+ string expected =
+ @"namespace MyNamespace
+{
+ [JsiiTypeProxy(typeof(MyClass), ""myFqn"")]
+ internal sealed class MyClassProxy : MyClass
+ {
+ private MyClassProxy(ByRefValue reference): base(reference)
+ {
+ }
+
+ [JsiiProperty(""myProp"", ""{\""fqn\"":\""myPropTypeFqn\""}"")]
+ public override MyPropType MyProp
+ {
+ get => GetInstanceProperty();
+ set => SetInstanceProperty(value);
+ }
+ }
+}";
+ Assert.Equal(expected, actual, ignoreLineEndingDifferences: true);
+ }
+
+ [Fact(DisplayName = Prefix + nameof(IncludesMethods))]
+ public void IncludesMethods()
+ {
+ ClassType classType = new ClassType
+ (
+ fullyQualifiedName: "myFqn",
+ assembly: "myPackage",
+ name: "myClass",
+ isAbstract: true,
+ initializer: new Method(true, false, false),
+ methods: new[]
+ {
+ new Method
+ (
+ false,
+ false,
+ true,
+ name: "myMethod"
+ ),
+ new Method
+ (
+ false,
+ false,
+ false,
+ name: "notMyMethod"
+ )
+ }
+ );
+
+ Symbols.MapMethodName("myFqn", "myMethod", "MyMethod");
+
+ string actual = Render(classType);
+ string expected =
+ @"namespace MyNamespace
+{
+ [JsiiTypeProxy(typeof(MyClass), ""myFqn"")]
+ internal sealed class MyClassProxy : MyClass
+ {
+ private MyClassProxy(ByRefValue reference): base(reference)
+ {
+ }
+
+ [JsiiMethod(""myMethod"", null, ""[]"")]
+ public override void MyMethod()
+ {
+ InvokeInstanceVoidMethod(new object[]{});
+ }
+ }
+}";
+ Assert.Equal(expected, actual, ignoreLineEndingDifferences: true);
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator.UnitTests/Class/ClassGeneratorTests.cs b/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator.UnitTests/Class/ClassGeneratorTests.cs
index 7c463047aa..f430a9b358 100644
--- a/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator.UnitTests/Class/ClassGeneratorTests.cs
+++ b/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator.UnitTests/Class/ClassGeneratorTests.cs
@@ -1,20 +1,20 @@
using Amazon.JSII.Generator.Class;
-using Amazon.JSII.Generator.Interface;
using Amazon.JSII.JsonModel.Spec;
using Microsoft.CodeAnalysis;
using Xunit;
+using TypeKind = Amazon.JSII.JsonModel.Spec.TypeKind;
namespace Amazon.JSII.Generator.UnitTests.Class
{
public class ClassGeneratorTests : GeneratorTestBase
{
- const string Prefix = nameof(Generator) + "." + nameof(InterfaceGenerator) + ".";
+ const string Prefix = nameof(Generator) + "." + nameof(ClassGenerator) + ".";
- string Render(ClassType classType)
+ private string Render(ClassType classType)
{
Symbols.MapTypeToPackage("myFqn", classType.Assembly);
Symbols.MapNamespace(classType.QualifiedNamespace, "MyNamespace");
- Symbols.MapTypeName("myFqn", "MyClass", JsonModel.Spec.TypeKind.Class);
+ Symbols.MapTypeName("myFqn", "MyClass", TypeKind.Class);
ClassGenerator generator = new ClassGenerator(classType.Assembly, classType, Symbols, Namespaces);
@@ -36,7 +36,7 @@ public void IncludesAttribute()
string actual = Render(classType);
string expected =
-@"namespace MyNamespace
+ @"namespace MyNamespace
{
[JsiiClass(typeof(MyClass), ""myFqn"", ""[]"")]
public class MyClass : DeputyBase
@@ -71,7 +71,7 @@ public void IncludesAbstractKeyword()
string actual = Render(classType);
string expected =
-@"namespace MyNamespace
+ @"namespace MyNamespace
{
[JsiiClass(typeof(MyClass), ""myFqn"", ""[]"")]
public abstract class MyClass : DeputyBase
@@ -103,12 +103,12 @@ public void IncludesDocs()
name: "myClass",
isAbstract: false,
initializer: new Method(true, false, false),
- docs: new Docs { { "foo", "bar" } }
+ docs: new Docs {{"foo", "bar"}}
);
string actual = Render(classType);
string expected =
-@"namespace MyNamespace
+ @"namespace MyNamespace
{
/// foo: bar
[JsiiClass(typeof(MyClass), ""myFqn"", ""[]"")]
@@ -144,7 +144,7 @@ public void IncludesProperties()
{
new Property
(
- name: "myProp",
+ name: "myProp",
type: new TypeReference("myPropTypeFqn"),
isImmutable: false,
isAbstract: false,
@@ -153,12 +153,12 @@ public void IncludesProperties()
}
);
- Symbols.MapTypeName("myPropTypeFqn", "MyPropType", JsonModel.Spec.TypeKind.Class);
+ Symbols.MapTypeName("myPropTypeFqn", "MyPropType", TypeKind.Class);
Symbols.MapPropertyName("myFqn", "myProp", "MyProp");
string actual = Render(classType);
string expected =
-@"namespace MyNamespace
+ @"namespace MyNamespace
{
[JsiiClass(typeof(MyClass), ""myFqn"", ""[]"")]
public class MyClass : DeputyBase
@@ -212,7 +212,7 @@ public void IncludesMethods()
string actual = Render(classType);
string expected =
-@"namespace MyNamespace
+ @"namespace MyNamespace
{
[JsiiClass(typeof(MyClass), ""myFqn"", ""[]"")]
public class MyClass : DeputyBase
@@ -252,11 +252,11 @@ public void IncludesBase()
@base: new TypeReference("myBaseTypeFqn")
);
- Symbols.MapTypeName("myBaseTypeFqn", "MyBaseType", JsonModel.Spec.TypeKind.Class);
+ Symbols.MapTypeName("myBaseTypeFqn", "MyBaseType", TypeKind.Class);
string actual = Render(classType);
string expected =
-@"namespace MyNamespace
+ @"namespace MyNamespace
{
[JsiiClass(typeof(MyClass), ""myFqn"", ""[]"")]
public class MyClass : MyBaseType
@@ -294,12 +294,12 @@ public void IncludesInterfaces()
}
);
- Symbols.MapTypeName("myInterfaceFqn1", "MyInterface1", JsonModel.Spec.TypeKind.Interface);
- Symbols.MapTypeName("myInterfaceFqn2", "MyInterface2", JsonModel.Spec.TypeKind.Interface);
+ Symbols.MapTypeName("myInterfaceFqn1", "MyInterface1", TypeKind.Interface);
+ Symbols.MapTypeName("myInterfaceFqn2", "MyInterface2", TypeKind.Interface);
string actual = Render(classType);
string expected =
-@"namespace MyNamespace
+ @"namespace MyNamespace
{
[JsiiClass(typeof(MyClass), ""myFqn"", ""[]"")]
public class MyClass : DeputyBase, IMyInterface1, IMyInterface2
@@ -320,4 +320,4 @@ protected MyClass(DeputyProps props): base(props)
Assert.Equal(expected, actual, ignoreLineEndingDifferences: true);
}
}
-}
+}
\ No newline at end of file
diff --git a/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator.UnitTests/Interface/InterfaceProxyGeneratorTests.cs b/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator.UnitTests/Interface/InterfaceProxyGeneratorTests.cs
index 37f0b11dc6..b0555c034b 100644
--- a/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator.UnitTests/Interface/InterfaceProxyGeneratorTests.cs
+++ b/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator.UnitTests/Interface/InterfaceProxyGeneratorTests.cs
@@ -3,6 +3,7 @@
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Xunit;
+using TypeKind = Amazon.JSII.JsonModel.Spec.TypeKind;
namespace Amazon.JSII.Generator.UnitTests.Interface
{
@@ -10,12 +11,13 @@ public class InterfaceProxyGeneratorTests : GeneratorTestBase
{
const string Prefix = nameof(Generator) + "." + nameof(InterfaceProxyGenerator) + ".";
- string Render(InterfaceType interfaceType, string package = "myPackage", string @namespace = "MyNamespace", string typeName = "MyInterface")
+ string Render(InterfaceType interfaceType, string package = "myPackage", string @namespace = "MyNamespace",
+ string typeName = "MyInterface")
{
Symbols.MapTypeToPackage(interfaceType.FullyQualifiedName, package);
string suffix = interfaceType.Namespace != null ? "." + interfaceType.Namespace : "";
Symbols.MapNamespace(interfaceType.Assembly + suffix, @namespace);
- Symbols.MapTypeName(interfaceType.FullyQualifiedName, typeName, JsonModel.Spec.TypeKind.Interface);
+ Symbols.MapTypeName(interfaceType.FullyQualifiedName, typeName, TypeKind.Interface);
var generator = new InterfaceProxyGenerator(package, interfaceType, Symbols, Namespaces);
@@ -37,10 +39,10 @@ public void IncludesAttribute()
string actual = Render(interfaceType);
string expected =
-@"namespace MyNamespace
+ @"namespace MyNamespace
{
- [JsiiInterfaceProxy(typeof(IMyInterface), ""myInterfaceFqn"")]
- internal class MyInterfaceProxy : DeputyBase, IMyInterface
+ [JsiiTypeProxy(typeof(IMyInterface), ""myInterfaceFqn"")]
+ internal sealed class MyInterfaceProxy : DeputyBase, IMyInterface
{
private MyInterfaceProxy(ByRefValue reference): base(reference)
{
@@ -59,24 +61,24 @@ public void IncludesMethods()
"myPackage",
"myInterface",
"myNamespace",
- methods: new Method[] { new Method(false, false, true, name: "myMethod") }
+ methods: new Method[] {new Method(false, false, true, name: "myMethod")}
);
Symbols.MapMethodName("myInterfaceFqn", "myMethod", "MyMethod");
string actual = Render(interfaceType);
string expected =
-@"namespace MyNamespace
+ @"namespace MyNamespace
{
- [JsiiInterfaceProxy(typeof(IMyInterface), ""myInterfaceFqn"")]
- internal class MyInterfaceProxy : DeputyBase, IMyInterface
+ [JsiiTypeProxy(typeof(IMyInterface), ""myInterfaceFqn"")]
+ internal sealed class MyInterfaceProxy : DeputyBase, IMyInterface
{
private MyInterfaceProxy(ByRefValue reference): base(reference)
{
}
[JsiiMethod(""myMethod"", null, ""[]"")]
- public virtual void MyMethod()
+ public void MyMethod()
{
InvokeInstanceVoidMethod(new object[]{});
}
@@ -94,7 +96,7 @@ public void IncludesAncestorInterfaceMethods()
"myPackage",
"myAncestorInterface",
"myNamespace",
- methods: new [] { new Method(false, false, true, name: "myAncestorMethod") }
+ methods: new[] {new Method(false, false, true, name: "myAncestorMethod")}
);
InterfaceType baseInterface = new InterfaceType
(
@@ -102,8 +104,8 @@ public void IncludesAncestorInterfaceMethods()
"myPackage",
"myBaseInterface",
"myNamespace",
- methods: new[] { new Method(false, false, true, name: "myBaseMethod") },
- interfaces: new[] { new TypeReference("myAncestorInterfaceFqn") }
+ methods: new[] {new Method(false, false, true, name: "myBaseMethod")},
+ interfaces: new[] {new TypeReference("myAncestorInterfaceFqn")}
);
InterfaceType interfaceType = new InterfaceType
(
@@ -111,36 +113,36 @@ public void IncludesAncestorInterfaceMethods()
"myPackage",
"myInterface",
"myNamespace",
- interfaces: new[] { new TypeReference("myBaseInterfaceFqn") }
+ interfaces: new[] {new TypeReference("myBaseInterfaceFqn")}
);
- Symbols.MapTypeName("myAncestorInterfaceFqn", "MyAncestorInterface", JsonModel.Spec.TypeKind.Interface);
+ Symbols.MapTypeName("myAncestorInterfaceFqn", "MyAncestorInterface", TypeKind.Interface);
Symbols.MapFullyQualifiedNameToType("myAncestorInterfaceFqn", ancestorInterface);
Symbols.MapMethodName("myInterfaceFqn", "myAncestorMethod", "MyAncestorMethod");
- Symbols.MapTypeName("myBaseInterfaceFqn", "MyBaseInterface", JsonModel.Spec.TypeKind.Interface);
+ Symbols.MapTypeName("myBaseInterfaceFqn", "MyBaseInterface", TypeKind.Interface);
Symbols.MapFullyQualifiedNameToType("myBaseInterfaceFqn", baseInterface);
Symbols.MapMethodName("myInterfaceFqn", "myBaseMethod", "MyBaseMethod");
string actual = Render(interfaceType);
string expected =
-@"namespace MyNamespace
+ @"namespace MyNamespace
{
- [JsiiInterfaceProxy(typeof(IMyInterface), ""myInterfaceFqn"")]
- internal class MyInterfaceProxy : DeputyBase, IMyInterface
+ [JsiiTypeProxy(typeof(IMyInterface), ""myInterfaceFqn"")]
+ internal sealed class MyInterfaceProxy : DeputyBase, IMyInterface
{
private MyInterfaceProxy(ByRefValue reference): base(reference)
{
}
[JsiiMethod(""myBaseMethod"", null, ""[]"")]
- public virtual void MyBaseMethod()
+ public void MyBaseMethod()
{
InvokeInstanceVoidMethod(new object[]{});
}
[JsiiMethod(""myAncestorMethod"", null, ""[]"")]
- public virtual void MyAncestorMethod()
+ public void MyAncestorMethod()
{
InvokeInstanceVoidMethod(new object[]{});
}
@@ -158,16 +160,16 @@ public void IncludesDocs()
"myPackage",
"myInterface",
"myNamespace",
- docs: new Docs { { "foo", "bar" } }
+ docs: new Docs {{"foo", "bar"}}
);
string actual = Render(interfaceType);
string expected =
-@"namespace MyNamespace
+ @"namespace MyNamespace
{
/// foo: bar
- [JsiiInterfaceProxy(typeof(IMyInterface), ""myInterfaceFqn"")]
- internal class MyInterfaceProxy : DeputyBase, IMyInterface
+ [JsiiTypeProxy(typeof(IMyInterface), ""myInterfaceFqn"")]
+ internal sealed class MyInterfaceProxy : DeputyBase, IMyInterface
{
private MyInterfaceProxy(ByRefValue reference): base(reference)
{
@@ -181,7 +183,7 @@ private MyInterfaceProxy(ByRefValue reference): base(reference)
public void EnvironmentRegression()
{
const string json =
-@" {
+ @" {
""docs"": {
""comment"": ""Models an AWS execution environment, for use within the CDK toolkit.""
},
@@ -231,13 +233,14 @@ public void EnvironmentRegression()
Symbols.MapPropertyName("jsii$aws_cdk_cx_api$.Environment", "account", "Account");
Symbols.MapPropertyName("jsii$aws_cdk_cx_api$.Environment", "region", "Region");
- string actual = Render(interfaceType, package: "aws-cdk-cx-api", @namespace: "Aws.Cdk.CxApi", typeName: "Environment");
+ string actual = Render(interfaceType, package: "aws-cdk-cx-api", @namespace: "Aws.Cdk.CxApi",
+ typeName: "Environment");
string expected =
-@"namespace Aws.Cdk.CxApi
+ @"namespace Aws.Cdk.CxApi
{
/// Models an AWS execution environment, for use within the CDK toolkit.
- [JsiiInterfaceProxy(typeof(IEnvironment), ""jsii$aws_cdk_cx_api$.Environment"")]
- internal class EnvironmentProxy : DeputyBase, IEnvironment
+ [JsiiTypeProxy(typeof(IEnvironment), ""jsii$aws_cdk_cx_api$.Environment"")]
+ internal sealed class EnvironmentProxy : DeputyBase, IEnvironment
{
private EnvironmentProxy(ByRefValue reference): base(reference)
{
@@ -245,7 +248,7 @@ private EnvironmentProxy(ByRefValue reference): base(reference)
/// The arbitrary name of this environment (user-set, or at least user-meaningful)
[JsiiProperty(""name"", ""{\""primitive\"":\""string\""}"")]
- public virtual string Name
+ public string Name
{
get => GetInstanceProperty();
set => SetInstanceProperty(value);
@@ -253,7 +256,7 @@ public virtual string Name
/// The 12-digit AWS account ID for the account this environment deploys into
[JsiiProperty(""account"", ""{\""primitive\"":\""string\""}"")]
- public virtual string Account
+ public string Account
{
get => GetInstanceProperty();
set => SetInstanceProperty(value);
@@ -261,7 +264,7 @@ public virtual string Account
/// The AWS region name where this environment deploys into
[JsiiProperty(""region"", ""{\""primitive\"":\""string\""}"")]
- public virtual string Region
+ public string Region
{
get => GetInstanceProperty();
set => SetInstanceProperty(value);
@@ -271,4 +274,4 @@ public virtual string Region
Assert.Equal(expected, actual, ignoreLineEndingDifferences: true);
}
}
-}
+}
\ No newline at end of file
diff --git a/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator.UnitTests/Interface/InterfaceProxyMethodGeneratorTests.cs b/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator.UnitTests/Interface/InterfaceProxyMethodGeneratorTests.cs
index d33f6cc9c9..76851dd603 100644
--- a/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator.UnitTests/Interface/InterfaceProxyMethodGeneratorTests.cs
+++ b/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator.UnitTests/Interface/InterfaceProxyMethodGeneratorTests.cs
@@ -3,6 +3,7 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Xunit;
+using TypeKind = Amazon.JSII.JsonModel.Spec.TypeKind;
namespace Amazon.JSII.Generator.UnitTests.Interface
{
@@ -23,7 +24,7 @@ string Render(Method method)
Symbols.MapTypeToPackage("myInterfaceFqn", "myPackage");
Symbols.MapNamespace("", "MyNamespace");
- Symbols.MapTypeName("myInterfaceFqn", "MyInterface", JsonModel.Spec.TypeKind.Interface);
+ Symbols.MapTypeName("myInterfaceFqn", "MyInterface", TypeKind.Interface);
var generator = new InterfaceProxyMethodGenerator(interfaceType, method, Symbols, Namespaces);
@@ -41,7 +42,7 @@ public void IncludesAttribute()
string actual = Render(method);
string expected =
@"[JsiiMethod(""myMethod"", null, ""[]"")]
-public virtual void MyMethod()
+public void MyMethod()
{
InvokeInstanceVoidMethod(new object[]{});
}";
@@ -62,14 +63,14 @@ public void IncluesParameters()
);
Symbols.MapMethodName("myInterfaceFqn", "myMethod", "MyMethod");
- Symbols.MapTypeName("myParamTypeFqn", "MyParamType", JsonModel.Spec.TypeKind.Class);
+ Symbols.MapTypeName("myParamTypeFqn", "MyParamType", TypeKind.Class);
Symbols.MapParameterName("myParam", "myParam");
Symbols.MapParameterName("event", "@event");
string actual = Render(method);
string expected =
@"[JsiiMethod(""myMethod"", null, ""[{\""name\"":\""myParam\"",\""type\"":{\""fqn\"":\""myParamTypeFqn\""}},{\""name\"":\""event\"",\""type\"":{\""primitive\"":\""string\""}}]"")]
-public virtual void MyMethod(MyParamType myParam, string @event)
+public void MyMethod(MyParamType myParam, string @event)
{
InvokeInstanceVoidMethod(new object[]{myParam, @event});
}";
@@ -90,7 +91,7 @@ public void DoesNotIncludeDocs()
string actual = Render(method);
string expected =
@"[JsiiMethod(""myMethod"", null, ""[]"")]
-public virtual void MyMethod()
+public void MyMethod()
{
InvokeInstanceVoidMethod(new object[]{});
}";
@@ -107,12 +108,12 @@ public void IncludesReturnTypeForNonVoid()
);
Symbols.MapMethodName("myInterfaceFqn", "myMethod", "MyMethod");
- Symbols.MapTypeName("myReturnTypeFqn", "MyReturnType", JsonModel.Spec.TypeKind.Class);
+ Symbols.MapTypeName("myReturnTypeFqn", "MyReturnType", TypeKind.Class);
string actual = Render(method);
string expected =
@"[JsiiMethod(""myMethod"", ""{\""fqn\"":\""myReturnTypeFqn\""}"", ""[]"")]
-public virtual MyReturnType MyMethod()
+public MyReturnType MyMethod()
{
return InvokeInstanceMethod(new object[]{});
}";
diff --git a/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator.UnitTests/SymbolMapExtensions.cs b/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator.UnitTests/SymbolMapExtensions.cs
index 4d2bd4cb2d..ed6093e7fa 100644
--- a/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator.UnitTests/SymbolMapExtensions.cs
+++ b/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator.UnitTests/SymbolMapExtensions.cs
@@ -1,7 +1,6 @@
using Amazon.JSII.JsonModel.Spec;
using NSubstitute;
using SF = Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
-using Type = Amazon.JSII.JsonModel.Spec.Type;
namespace Amazon.JSII.Generator.UnitTests
{
@@ -91,6 +90,15 @@ public static void MapTypeName(this ISymbolMap symbols, string fullyQualifiedNam
frameworkName = $"I{frameworkName}";
}
+ if (kind == TypeKind.Class)
+ {
+ string proxyName = $"{frameworkName}Proxy";
+
+ symbols
+ .GetAbstractClassProxyName(Arg.Is(t => t.FullyQualifiedName == fullyQualifiedName), disambiguate: Arg.Any())
+ .Returns(proxyName);
+ }
+
symbols
.GetName(Arg.Is(t => t.FullyQualifiedName == fullyQualifiedName), disambiguate: Arg.Any())
.Returns(frameworkName);
diff --git a/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/AssemblyGenerator.cs b/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/AssemblyGenerator.cs
index d05786067c..6e087b8d45 100644
--- a/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/AssemblyGenerator.cs
+++ b/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/AssemblyGenerator.cs
@@ -281,25 +281,47 @@ void SaveType(Type type)
switch (type.Kind)
{
case TypeKind.Class:
- SaveTypeFile($"{symbols.GetName(type)}.cs", new ClassGenerator(assembly.Name, (ClassType)type, symbols).CreateSyntaxTree());
+ {
+ var classType = (ClassType) type;
+
+ if (classType.IsAbstract)
+ {
+ SaveTypeFile($"{symbols.GetAbstractClassProxyName(classType)}.cs",
+ new AbstractClassProxyGenerator(assembly.Name, classType, symbols).CreateSyntaxTree());
+ }
+
+ SaveTypeFile($"{symbols.GetName(type)}.cs",
+ new ClassGenerator(assembly.Name, classType, symbols).CreateSyntaxTree());
return;
+ }
case TypeKind.Enum:
- SaveTypeFile($"{symbols.GetName(type)}.cs", new EnumGenerator(assembly.Name, (EnumType)type, symbols).CreateSyntaxTree());
+ {
+ SaveTypeFile($"{symbols.GetName(type)}.cs",
+ new EnumGenerator(assembly.Name, (EnumType) type, symbols).CreateSyntaxTree());
return;
+ }
case TypeKind.Interface:
- InterfaceType interfaceType = (InterfaceType)type;
+ {
+ InterfaceType interfaceType = (InterfaceType) type;
- SaveTypeFile($"{symbols.GetName(interfaceType)}.cs", new InterfaceGenerator(assembly.Name, interfaceType, symbols).CreateSyntaxTree());
- SaveTypeFile($"{symbols.GetInterfaceProxyName(interfaceType)}.cs", new InterfaceProxyGenerator(assembly.Name, interfaceType, symbols).CreateSyntaxTree());
+ SaveTypeFile($"{symbols.GetName(interfaceType)}.cs",
+ new InterfaceGenerator(assembly.Name, interfaceType, symbols).CreateSyntaxTree());
+ SaveTypeFile($"{symbols.GetInterfaceProxyName(interfaceType)}.cs",
+ new InterfaceProxyGenerator(assembly.Name, interfaceType, symbols).CreateSyntaxTree());
if (interfaceType.IsDataType == true)
{
- SaveTypeFile($"{symbols.GetInterfaceDefaultName(interfaceType)}.cs", new InterfaceDefaultGenerator(assembly.Name, interfaceType, symbols).CreateSyntaxTree());
+ SaveTypeFile($"{symbols.GetInterfaceDefaultName(interfaceType)}.cs",
+ new InterfaceDefaultGenerator(assembly.Name, interfaceType, symbols)
+ .CreateSyntaxTree());
}
return;
+ }
default:
+ {
throw new ArgumentException($"Unkown type kind: {type.Kind}", nameof(type));
+ }
}
void SaveTypeFile(string filename, SyntaxTree syntaxTree)
diff --git a/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/Class/AbstractClassProxyGenerator.cs b/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/Class/AbstractClassProxyGenerator.cs
new file mode 100644
index 0000000000..3e12ed352f
--- /dev/null
+++ b/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/Class/AbstractClassProxyGenerator.cs
@@ -0,0 +1,174 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Amazon.JSII.JsonModel.Spec;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using SF = Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
+using Type = Amazon.JSII.JsonModel.Spec.Type;
+
+namespace Amazon.JSII.Generator.Class
+{
+ public class AbstractClassProxyGenerator : TypeProxyGeneratorBase
+ {
+ public AbstractClassProxyGenerator(string package, ClassType type, ISymbolMap symbols,
+ INamespaceSet namespaces = null)
+ : base(package, type, symbols, namespaces)
+ {
+ if (!type.IsAbstract)
+ {
+ throw new ArgumentException("Class type must be abstract.", nameof(type));
+ }
+ }
+
+ protected override SyntaxToken GetProxyTypeNameSyntax()
+ {
+ return SF.Identifier(Symbols.GetAbstractClassProxyName(Type));
+ }
+
+ protected override IEnumerable CreateProperties()
+ {
+ foreach (Property property in GetAllProperties(Type))
+ {
+ var generator = new AbstractClassProxyPropertyGenerator(Type, property, Symbols, Namespaces);
+ yield return generator.CreateProperty();
+ }
+ }
+
+ protected override IEnumerable CreateMethods()
+ {
+ foreach (Method method in GetAllMethods(Type))
+ {
+ var generator = new AbstractClassProxyMethodGenerator(Type, method, Symbols, Namespaces);
+ yield return generator.CreateMethod();
+ }
+ }
+
+ private IEnumerable GetAllMethods(Type type)
+ {
+ IEnumerable GetAllMethodsRecurse(Type currentType, IEnumerable methods)
+ {
+ if (currentType is InterfaceType interfaceType)
+ {
+ // Get all properties from the interface.
+ methods = methods.Concat(interfaceType.Methods ?? Enumerable.Empty());
+
+ // Interfaces can have superinterfaces. Run through them too.
+ if (interfaceType.Interfaces != null)
+ {
+ var superinterfaceMethods = interfaceType.Interfaces.Select(r =>
+ Symbols.GetTypeFromFullyQualifiedName(r.FullyQualifiedName) as
+ InterfaceType)
+ .SelectMany(i => GetAllMethodsRecurse(i, methods))
+ .ToList();
+
+ methods = methods.Concat(superinterfaceMethods);
+ }
+ }
+ else if (currentType is ClassType classType)
+ {
+ // Get all methods from the interface
+ methods = methods.Concat(classType.Methods ?? Enumerable.Empty());
+
+ if (classType.Interfaces != null)
+ {
+ // Run through all the interfaces.
+ var superinterfaceMethods = classType.Interfaces.Select(r =>
+ Symbols.GetTypeFromFullyQualifiedName(r.FullyQualifiedName) as
+ InterfaceType)
+ .SelectMany(i => GetAllMethodsRecurse(i, methods))
+ .ToList();
+
+ methods = methods.Concat(superinterfaceMethods);
+ }
+
+ // Run through the superclass.
+ if (classType.Base != null)
+ {
+ methods = methods.Concat(GetAllMethodsRecurse(
+ Symbols.GetTypeFromFullyQualifiedName(classType.Base.FullyQualifiedName) as ClassType,
+ methods));
+ }
+ }
+
+ return methods;
+ }
+
+ /*
+ Only get the first declaration encountered, and keep it if it is abstract. The list contains ALL
+ methods and properties encountered, in the order encountered. An abstract class can have concrete
+ implementations. Therefore, we only generate methods/properties if the first member encountered
+ is unimplemented.
+ */
+ return GetAllMethodsRecurse(type, Enumerable.Empty())
+ .GroupBy(m => (m.Name,
+ string.Join("",
+ m.Parameters?.Select(p => p.Name + p.Type.FullyQualifiedName) ?? Enumerable.Empty())))
+ .Select(g => g.First())
+ .Where(m => m.IsAbstract ?? false);
+ }
+
+ private IEnumerable GetAllProperties(Type type)
+ {
+ IEnumerable GetAllPropertiesRecurse(Type currentType, IEnumerable properties)
+ {
+ if (currentType is InterfaceType interfaceType)
+ {
+ // Get all properties from the interface.
+ properties = properties.Concat(interfaceType.Properties ?? Enumerable.Empty());
+
+ // Interfaces can have superinterfaces. Run through them too.
+ if (interfaceType.Interfaces != null)
+ {
+ var superinterfaceMethods = interfaceType.Interfaces.Select(r =>
+ Symbols.GetTypeFromFullyQualifiedName(r.FullyQualifiedName) as
+ InterfaceType)
+ .SelectMany(i => GetAllPropertiesRecurse(i, properties))
+ .ToList();
+
+ properties = properties.Concat(superinterfaceMethods);
+ }
+ }
+ else if (currentType is ClassType classType)
+ {
+ // Add the properties from the class.
+ properties =
+ properties.Concat(classType.Properties ?? Enumerable.Empty());
+
+ // Run through all the interfaces.
+ if (classType.Interfaces != null)
+ {
+ var superinterfaceMethods = classType.Interfaces.Select(r =>
+ Symbols.GetTypeFromFullyQualifiedName(r.FullyQualifiedName) as
+ InterfaceType)
+ .SelectMany(i => GetAllPropertiesRecurse(i, properties))
+ .ToList();
+
+ properties = properties.Concat(superinterfaceMethods);
+ }
+
+ // Run through the superclass.
+ if (classType.Base != null)
+ {
+ properties = properties.Concat(GetAllPropertiesRecurse(
+ Symbols.GetTypeFromFullyQualifiedName(classType.Base.FullyQualifiedName) as ClassType,
+ properties));
+ }
+ }
+
+ return properties;
+ }
+
+ /*
+ Only get the first declaration encountered, and keep it if it is abstract. The list contains ALL
+ methods and properties encountered, in the order encountered. An abstract class can have concrete
+ implementations. Therefore, we only generate methods/properties if the first member encountered
+ is unimplemented.
+ */
+ return GetAllPropertiesRecurse(type, Enumerable.Empty())
+ .GroupBy(p => p.Name)
+ .Select(g => g.First())
+ .Where(p => p.IsAbstract ?? false);
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/Class/AbstractClassProxyMethodGenerator.cs b/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/Class/AbstractClassProxyMethodGenerator.cs
new file mode 100644
index 0000000000..68c9e870c0
--- /dev/null
+++ b/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/Class/AbstractClassProxyMethodGenerator.cs
@@ -0,0 +1,40 @@
+using System.Collections.Generic;
+using System.Linq;
+using Amazon.JSII.JsonModel.Spec;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using SF = Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
+
+namespace Amazon.JSII.Generator.Class
+{
+ public class AbstractClassProxyMethodGenerator : ClassMethodGenerator
+ {
+ public AbstractClassProxyMethodGenerator(ClassType type, Method method, ISymbolMap symbols,
+ INamespaceSet namespaces) : base(type, method, symbols, namespaces)
+ {
+ }
+
+ protected override IEnumerable GetModifierKeywords()
+ {
+ yield return Method.IsProtected ? SyntaxKind.ProtectedKeyword : SyntaxKind.PublicKeyword;
+
+ // Type is the abstract class, so we need to check it as well as ancestors.
+ if (IsDefinedOnAncestor || Type.Methods.Any(m => m.Name == Method.Name))
+ {
+ yield return SyntaxKind.OverrideKeyword;
+ }
+ }
+
+ protected override BlockSyntax GetBody()
+ {
+ if (Method.Returns == null)
+ {
+ return SF.Block(SF.ExpressionStatement(CreateInvocationExpression()));
+ }
+
+ return SF.Block(SF.ReturnStatement(CreateInvocationExpression()));
+ }
+
+ protected override bool HasSemicolon => false;
+ }
+}
\ No newline at end of file
diff --git a/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/Class/AbstractClassProxyPropertyGenerator.cs b/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/Class/AbstractClassProxyPropertyGenerator.cs
new file mode 100644
index 0000000000..d3c8e97f0d
--- /dev/null
+++ b/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/Class/AbstractClassProxyPropertyGenerator.cs
@@ -0,0 +1,26 @@
+using System.Collections.Generic;
+using System.Linq;
+using Amazon.JSII.JsonModel.Spec;
+using Microsoft.CodeAnalysis.CSharp;
+
+namespace Amazon.JSII.Generator.Class
+{
+ public class AbstractClassProxyPropertyGenerator : ClassPropertyGenerator
+ {
+ public AbstractClassProxyPropertyGenerator(ClassType type, Property property, ISymbolMap symbols,
+ INamespaceSet namespaces) : base(type, property, symbols, namespaces)
+ {
+ }
+
+ protected override IEnumerable GetModifierKeywords()
+ {
+ yield return Property.IsProtected == true ? SyntaxKind.ProtectedKeyword : SyntaxKind.PublicKeyword;
+
+ // Type is the abstract class, so we need to check it as well as ancestors.
+ if (IsDefinedOnAncestor || Type.Properties.Any(p => p.Name == Property.Name))
+ {
+ yield return SyntaxKind.OverrideKeyword;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/Class/ClassMethodGenerator.cs b/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/Class/ClassMethodGenerator.cs
index 8108c3d091..8e8e80edf0 100644
--- a/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/Class/ClassMethodGenerator.cs
+++ b/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/Class/ClassMethodGenerator.cs
@@ -1,10 +1,8 @@
-using Amazon.JSII.JsonModel.Spec;
-using Microsoft.CodeAnalysis;
+using System.Collections.Generic;
+using System.Linq;
+using Amazon.JSII.JsonModel.Spec;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
-using System;
-using System.Collections.Generic;
-using System.Linq;
using SF = Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
namespace Amazon.JSII.Generator.Class
@@ -16,15 +14,15 @@ public ClassMethodGenerator(ClassType type, Method method, ISymbolMap symbols, I
{
}
- bool IsDefinedOnAncestor
+ protected bool IsDefinedOnAncestor
{
get
{
- string[] objectMethods = new[]
+ string[] objectMethods =
{
"ToString",
"GetHashCode",
- "Equals",
+ "Equals"
};
if (objectMethods.Contains(NameUtils.ConvertMethodName(Method.Name)))
@@ -79,4 +77,4 @@ protected override BlockSyntax GetBody()
protected override bool HasSemicolon => Method.IsAbstract == true;
}
-}
+}
\ No newline at end of file
diff --git a/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/Class/ClassPropertyGenerator.cs b/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/Class/ClassPropertyGenerator.cs
index 5558566fda..76bb7e79bc 100644
--- a/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/Class/ClassPropertyGenerator.cs
+++ b/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/Class/ClassPropertyGenerator.cs
@@ -1,10 +1,9 @@
-using Amazon.JSII.JsonModel.Spec;
+using System.Collections.Generic;
+using System.Linq;
+using Amazon.JSII.JsonModel.Spec;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
-using System;
-using System.Collections.Generic;
-using System.Linq;
using SF = Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
namespace Amazon.JSII.Generator.Class
@@ -16,7 +15,7 @@ public ClassPropertyGenerator(ClassType type, Property property, ISymbolMap symb
{
}
- bool IsDefinedOnAncestor => Type.AnyAncestor(Symbols, t => t.Properties?.Any(p => p.Name == Property.Name) == true);
+ protected bool IsDefinedOnAncestor => Type.AnyAncestor(Symbols, t => t.Properties?.Any(p => p.Name == Property.Name) == true);
protected override IEnumerable GetModifierKeywords()
{
diff --git a/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/ISymbolMap.cs b/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/ISymbolMap.cs
index d60230587f..030170385a 100644
--- a/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/ISymbolMap.cs
+++ b/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/ISymbolMap.cs
@@ -15,6 +15,8 @@ public interface ISymbolMap
string GetName(Type type, bool disambiguate = false);
string GetName(string fullyQualifiedName, bool disambiguate = false);
+
+ string GetAbstractClassProxyName(ClassType type, bool disambiguate = false);
string GetInterfaceProxyName(InterfaceType type, bool disambiguate = false);
diff --git a/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/Interface/InterfaceProxyGenerator.cs b/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/Interface/InterfaceProxyGenerator.cs
index 9935708ce0..d4b806f0cf 100644
--- a/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/Interface/InterfaceProxyGenerator.cs
+++ b/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/Interface/InterfaceProxyGenerator.cs
@@ -1,98 +1,24 @@
-using Amazon.JSII.JsonModel.Spec;
+using System.Collections.Generic;
+using Amazon.JSII.JsonModel.Spec;
using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
-using System;
-using System.Collections.Generic;
-using System.Linq;
using SF = Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
namespace Amazon.JSII.Generator.Interface
{
- public class InterfaceProxyGenerator : TypeGeneratorBase
+ public class InterfaceProxyGenerator : TypeProxyGeneratorBase
{
public InterfaceProxyGenerator(string package, InterfaceType type, ISymbolMap symbols, INamespaceSet namespaces = null)
: base(package, type, symbols, namespaces)
{
}
-
- protected override MemberDeclarationSyntax CreateType()
- {
- return SF.ClassDeclaration
- (
- CreateAttributes(),
- SF.TokenList(SF.Token(SyntaxKind.InternalKeyword)),
- GetProxyTypeNameSyntax(),
- null,
- CreateBaseList(),
- SF.List(),
- SF.List(CreateMembers())
- );
-
- SyntaxList CreateAttributes()
- {
- TypeOfExpressionSyntax typeOfExpression = SF.TypeOfExpression(Symbols.GetNameSyntax(Type));
- SyntaxToken fullyQualifiedNameLiteral = SF.Literal(Type.FullyQualifiedName);
-
- return SF.List(new[] {
- SF.AttributeList(SF.SeparatedList(new[] {
- SF.Attribute(
- SF.ParseName("JsiiInterfaceProxy"),
- SF.ParseAttributeArgumentList($"({typeOfExpression}, {fullyQualifiedNameLiteral})")
- )
- }))
- });
- }
-
- BaseListSyntax CreateBaseList()
- {
- return SF.BaseList(SF.SeparatedList(GetBaseTypes()));
-
- IEnumerable GetBaseTypes()
- {
- yield return SF.SimpleBaseType(SF.ParseTypeName("DeputyBase"));
-
- Namespaces.Add(Type);
- yield return SF.SimpleBaseType(Symbols.GetNameSyntax(Type, disambiguate: true));
- }
- }
-
- IEnumerable CreateMembers()
- {
- return CreateConstructors()
- .Concat(CreateProperties())
- .Concat(CreateMethods());
- }
- }
-
- SyntaxToken GetProxyTypeNameSyntax()
+
+ protected override SyntaxToken GetProxyTypeNameSyntax()
{
return SF.Identifier(Symbols.GetInterfaceProxyName(Type));
}
- IEnumerable CreateConstructors()
- {
- yield return SF.ConstructorDeclaration
- (
- SF.List(),
-
- // Only Amazon.JSII.Runtime should create interface proxies,
- // so we make the constructor private.
- SF.TokenList(SF.Token(SyntaxKind.PrivateKeyword)),
-
- GetProxyTypeNameSyntax(),
- SF.ParseParameterList("(ByRefValue reference)"),
- SF.ConstructorInitializer
- (
- SyntaxKind.BaseConstructorInitializer,
- SF.ParseArgumentList("(reference)")
- ),
- SF.Block(),
- null
- );
- }
-
- IEnumerable CreateProperties()
+ protected override IEnumerable CreateProperties()
{
foreach (Property property in Type.GetAllProperties(Symbols))
{
@@ -101,7 +27,7 @@ IEnumerable CreateProperties()
}
}
- IEnumerable CreateMethods()
+ protected override IEnumerable CreateMethods()
{
foreach (Method method in Type.GetAllMethods(Symbols))
{
diff --git a/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/Interface/InterfaceProxyMethodGenerator.cs b/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/Interface/InterfaceProxyMethodGenerator.cs
index 29c53e7db7..68c63f1768 100644
--- a/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/Interface/InterfaceProxyMethodGenerator.cs
+++ b/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/Interface/InterfaceProxyMethodGenerator.cs
@@ -1,8 +1,8 @@
-using Amazon.JSII.JsonModel.Spec;
+using System;
+using System.Collections.Generic;
+using Amazon.JSII.JsonModel.Spec;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
-using System;
-using System.Collections.Generic;
using SF = Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
namespace Amazon.JSII.Generator.Interface
@@ -34,7 +34,6 @@ public InterfaceProxyMethodGenerator(InterfaceType type, Method method, ISymbolM
protected override IEnumerable GetModifierKeywords()
{
yield return SyntaxKind.PublicKeyword;
- yield return SyntaxKind.VirtualKeyword;
}
protected override BlockSyntax GetBody()
diff --git a/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/Interface/InterfaceProxyPropertyGenerator.cs b/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/Interface/InterfaceProxyPropertyGenerator.cs
index ff6c8af620..bde2cdb839 100644
--- a/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/Interface/InterfaceProxyPropertyGenerator.cs
+++ b/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/Interface/InterfaceProxyPropertyGenerator.cs
@@ -1,9 +1,9 @@
-using Amazon.JSII.JsonModel.Spec;
+using System;
+using System.Collections.Generic;
+using Amazon.JSII.JsonModel.Spec;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
-using System;
-using System.Collections.Generic;
using SF = Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
namespace Amazon.JSII.Generator.Interface
@@ -35,8 +35,6 @@ public InterfaceProxyPropertyGenerator(InterfaceType type, Property property, IS
protected override IEnumerable GetModifierKeywords()
{
yield return SyntaxKind.PublicKeyword;
-
- yield return SyntaxKind.VirtualKeyword;
}
protected override SyntaxToken GetIdentifier()
diff --git a/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/SymbolMap.cs b/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/SymbolMap.cs
index f00914887b..eb5a9a3175 100644
--- a/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/SymbolMap.cs
+++ b/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/SymbolMap.cs
@@ -54,16 +54,26 @@ TypeMetadata GetMetadata(Type type)
switch (type.Kind)
{
case JsonModel.Spec.TypeKind.Class:
+ {
+ var classType = (ClassType) type;
+ if (classType.IsAbstract)
+ {
+ return new AbstractClassTypeMetadata(classType, assembly);
+ }
return new ClassTypeMetadata((ClassType)type, assembly);
-
+ }
case JsonModel.Spec.TypeKind.Enum:
- return new EnumTypeMetadata((EnumType)type, assembly);
-
+ {
+ return new EnumTypeMetadata((EnumType)type, assembly);
+ }
case JsonModel.Spec.TypeKind.Interface:
- return new InterfaceTypeMetadata((InterfaceType)type, assembly);
-
+ {
+ return new InterfaceTypeMetadata((InterfaceType)type, assembly);
+ }
default:
- throw new ArgumentException($"Type {type.Name} has unrecognized kind {type.Kind}", nameof(type));
+ {
+ throw new ArgumentException($"Type {type.Name} has unrecognized kind {type.Kind}", nameof(type));
+ }
}
}
}
@@ -101,6 +111,18 @@ public string GetName(string fullyQualifiedName, bool disambiguate = false)
return GetName(GetTypeFromFullyQualifiedName(fullyQualifiedName), disambiguate);
}
+ public string GetAbstractClassProxyName(ClassType type, bool disambiguate = false)
+ {
+ type = type ?? throw new ArgumentNullException(nameof(type));
+
+ if (_types[type.FullyQualifiedName] is AbstractClassTypeMetadata metadata)
+ {
+ return metadata.ProxyName;
+ }
+
+ throw new ArgumentException($"Cannot get proxy name for '{type.FullyQualifiedName}' because it is not an abstract class.");
+ }
+
public string GetInterfaceProxyName(InterfaceType type, bool disambiguate = false)
{
type = type ?? throw new ArgumentNullException(nameof(type));
@@ -110,7 +132,7 @@ public string GetInterfaceProxyName(InterfaceType type, bool disambiguate = fals
return metadata.ProxyName;
}
- throw new ArgumentException($"Cannot get proxy name for '{type.FullyQualifiedName}' because it is not an interface");
+ throw new ArgumentException($"Cannot get proxy name for '{type.FullyQualifiedName}' because it is not an interface.");
}
public string GetInterfaceDefaultName(InterfaceType type, bool disambiguate = false)
@@ -122,7 +144,7 @@ public string GetInterfaceDefaultName(InterfaceType type, bool disambiguate = fa
return metadata.DefaultName;
}
- throw new ArgumentException($"Cannot get default name for '{type.FullyQualifiedName}' because it is not an interface");
+ throw new ArgumentException($"Cannot get default name for '{type.FullyQualifiedName}' because it is not an interface.");
}
public string GetName(Type type, Method method)
diff --git a/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/TypeMetadata.cs b/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/TypeMetadata.cs
index 462930882e..f6f7af256b 100644
--- a/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/TypeMetadata.cs
+++ b/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/TypeMetadata.cs
@@ -67,6 +67,31 @@ public ClassTypeMetadata(ClassType type, Assembly assembly)
}
}
+ public class AbstractClassTypeMetadata : ClassTypeMetadata
+ {
+ public string ProxyName { get; private set; }
+
+ public string FrameworkFullyQualifiedProxyName => $"{Namespace}.{ProxyName}";
+
+ public AbstractClassTypeMetadata(ClassType type, Assembly assembly)
+ : base(type, assembly)
+ {
+ ProxyName = $"{Name}Proxy";
+ }
+
+ public override void ResolveTypeNameConflicts(ISet namespaceNames)
+ {
+ base.ResolveTypeNameConflicts(namespaceNames);
+
+ ISet memberNames = new HashSet(MemberNames.Values);
+
+ while (memberNames.Contains(ProxyName) || namespaceNames.Contains(FrameworkFullyQualifiedProxyName))
+ {
+ ProxyName += "_";
+ }
+ }
+ }
+
public class EnumTypeMetadata : TypeMetadata
{
public EnumTypeMetadata(EnumType type, Assembly assembly)
@@ -82,7 +107,6 @@ public EnumTypeMetadata(EnumType type, Assembly assembly)
MemberNames = new ReadOnlyDictionary(memberNames);
Name = NameUtils.ConvertTypeName(type.Name);
}
-
}
public class InterfaceTypeMetadata : TypeMetadata
diff --git a/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/TypeProxyGeneratorBase.cs b/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/TypeProxyGeneratorBase.cs
new file mode 100644
index 0000000000..62a3a1b658
--- /dev/null
+++ b/packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/TypeProxyGeneratorBase.cs
@@ -0,0 +1,101 @@
+using System.Collections.Generic;
+using System.Linq;
+using Amazon.JSII.JsonModel.Spec;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using SF = Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
+
+namespace Amazon.JSII.Generator
+{
+ public abstract class TypeProxyGeneratorBase : TypeGeneratorBase where T : Type
+ {
+ protected TypeProxyGeneratorBase(string package, T type, ISymbolMap symbols, INamespaceSet namespaces)
+ : base(package, type, symbols, namespaces)
+ {
+ }
+
+ protected override MemberDeclarationSyntax CreateType()
+ {
+ return SF.ClassDeclaration
+ (
+ CreateAttributes(),
+ SF.TokenList(
+ SF.Token(SyntaxKind.InternalKeyword),
+ SF.Token(SyntaxKind.SealedKeyword)),
+ GetProxyTypeNameSyntax(),
+ null,
+ CreateBaseList(),
+ SF.List(),
+ SF.List(CreateMembers())
+ );
+
+ SyntaxList CreateAttributes()
+ {
+ var typeOfExpression = SF.TypeOfExpression(Symbols.GetNameSyntax(Type));
+ var fullyQualifiedNameLiteral = SF.Literal(Type.FullyQualifiedName);
+
+ return SF.List(new[]
+ {
+ SF.AttributeList(SF.SeparatedList(new[]
+ {
+ SF.Attribute(
+ SF.ParseName("JsiiTypeProxy"),
+ SF.ParseAttributeArgumentList($"({typeOfExpression}, {fullyQualifiedNameLiteral})")
+ )
+ }))
+ });
+ }
+
+ BaseListSyntax CreateBaseList()
+ {
+ return SF.BaseList(SF.SeparatedList(GetBaseTypes()));
+
+ IEnumerable GetBaseTypes()
+ {
+ if (Type is InterfaceType)
+ {
+ yield return SF.SimpleBaseType(SF.ParseTypeName("DeputyBase"));
+ }
+
+ Namespaces.Add(Type);
+ yield return SF.SimpleBaseType(Symbols.GetNameSyntax(Type, disambiguate: true));
+ }
+ }
+
+ IEnumerable CreateMembers()
+ {
+ return CreateConstructors()
+ .Concat(CreateProperties())
+ .Concat(CreateMethods());
+ }
+ }
+
+ protected virtual IEnumerable CreateConstructors()
+ {
+ yield return SF.ConstructorDeclaration
+ (
+ SF.List(),
+
+ // Only Amazon.JSII.Runtime should create interface proxies,
+ // so we make the constructor private.
+ SF.TokenList(SF.Token(SyntaxKind.PrivateKeyword)),
+ GetProxyTypeNameSyntax(),
+ SF.ParseParameterList("(ByRefValue reference)"),
+ SF.ConstructorInitializer
+ (
+ SyntaxKind.BaseConstructorInitializer,
+ SF.ParseArgumentList("(reference)")
+ ),
+ SF.Block(),
+ null
+ );
+ }
+
+ protected abstract SyntaxToken GetProxyTypeNameSyntax();
+
+ protected abstract IEnumerable CreateProperties();
+
+ protected abstract IEnumerable CreateMethods();
+ }
+}
\ No newline at end of file
diff --git a/packages/jsii-dotnet-generator/src/NuGet.config b/packages/jsii-dotnet-generator/src/NuGet.config
index c84bdd28da..b5fb4a92ff 100644
--- a/packages/jsii-dotnet-generator/src/NuGet.config
+++ b/packages/jsii-dotnet-generator/src/NuGet.config
@@ -1,4 +1,4 @@
-
+
diff --git a/packages/jsii-dotnet-runtime-test/test/Amazon.JSII.Runtime.IntegrationTests/ComplianceTests.cs b/packages/jsii-dotnet-runtime-test/test/Amazon.JSII.Runtime.IntegrationTests/ComplianceTests.cs
index 5425aa009b..a9dca0351f 100644
--- a/packages/jsii-dotnet-runtime-test/test/Amazon.JSII.Runtime.IntegrationTests/ComplianceTests.cs
+++ b/packages/jsii-dotnet-runtime-test/test/Amazon.JSII.Runtime.IntegrationTests/ComplianceTests.cs
@@ -1,13 +1,10 @@
+using System;
+using System.Collections.Generic;
using Amazon.JSII.Runtime.Deputy;
-using Amazon.JSII.Runtime.Services;
using Amazon.JSII.Tests.CalculatorNamespace;
-using Amazon.JSII.Tests.CalculatorNamespace.composition;
using Amazon.JSII.Tests.CalculatorNamespace.composition.CompositeOperation;
using Amazon.JSII.Tests.CalculatorNamespace.LibNamespace;
using Newtonsoft.Json.Linq;
-using System;
-using System.Collections.Generic;
-using System.IO;
using Xunit;
using Xunit.Abstractions;
@@ -784,7 +781,8 @@ public void ReservedKeywordsAreSlugifiedInMethodNames()
}
[Fact(DisplayName = Prefix + nameof(NodeStandardLibrary))]
- public void NodeStandardLibrary() {
+ public void NodeStandardLibrary()
+ {
NodeStandardLibrary obj = new NodeStandardLibrary();
Assert.Equal("Hello, resource!", obj.FsReadFile());
Assert.Equal("Hello, resource! SYNC!", obj.FsReadFileSync());
@@ -792,6 +790,22 @@ public void NodeStandardLibrary() {
Assert.Equal("6a2da20943931e9834fc12cfe5bb47bbd9ae43489a30726962b576f4e3993e50",
obj.CryptoSha256());
}
+
+ [Fact(DisplayName = Prefix + nameof(ReturnAbstract))]
+ public void ReturnAbstract()
+ {
+ var obj = new AbstractClassReturner();
+ var obj2 = obj.GiveMeAbstract();
+
+ Assert.Equal("Hello, John!!", obj2.AbstractMethod("John"));
+ Assert.Equal("propFromInterfaceValue", obj2.PropFromInterface);
+ Assert.Equal(42, obj2.NonAbstractMethod());
+
+ var iface = obj.GiveMeInterface();
+ Assert.Equal("propFromInterfaceValue", iface.PropFromInterface);
+
+ Assert.Equal("hello-abstract-property", obj.ReturnAbstractFromProperty.AbstractProperty);
+ }
class MulTen : Multiply
diff --git a/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Deputy/JsiiInterfaceProxyAttribute.cs b/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Deputy/JsiiTypeProxyAttribute.cs
similarity index 56%
rename from packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Deputy/JsiiInterfaceProxyAttribute.cs
rename to packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Deputy/JsiiTypeProxyAttribute.cs
index 05761f8213..c6a98143a5 100644
--- a/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Deputy/JsiiInterfaceProxyAttribute.cs
+++ b/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Deputy/JsiiTypeProxyAttribute.cs
@@ -3,9 +3,9 @@
namespace Amazon.JSII.Runtime.Deputy
{
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
- public class JsiiInterfaceProxyAttribute : JsiiTypeAttributeBase
+ public class JsiiTypeProxyAttribute : JsiiTypeAttributeBase
{
- public JsiiInterfaceProxyAttribute(Type nativeType, string fullyQualifiedName)
+ public JsiiTypeProxyAttribute(Type nativeType, string fullyQualifiedName)
: base(nativeType, fullyQualifiedName)
{
}
diff --git a/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Services/Converters/FrameworkToJsiiConverter.cs b/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Services/Converters/FrameworkToJsiiConverter.cs
index 02ac1e6e3e..9dabadcb95 100644
--- a/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Services/Converters/FrameworkToJsiiConverter.cs
+++ b/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Services/Converters/FrameworkToJsiiConverter.cs
@@ -35,7 +35,7 @@ protected override bool TryConvertClass(IReferenceMap referenceMap, object value
System.Type type = value.GetType();
- if (type.GetCustomAttribute() != null)
+ if (type.GetCustomAttribute() != null)
{
throw new ArgumentException
(
diff --git a/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Services/Converters/ValueConverter.cs b/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Services/Converters/ValueConverter.cs
index 58a14fc5dd..af5e834506 100644
--- a/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Services/Converters/ValueConverter.cs
+++ b/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Services/Converters/ValueConverter.cs
@@ -115,7 +115,7 @@ bool IsReferenceType()
return
_types.GetClassType(fullyQualifiedName) != null ||
_types.GetInterfaceType(fullyQualifiedName) != null ||
- _types.GetInterfaceProxyType(fullyQualifiedName) != null;
+ _types.GetProxyType(fullyQualifiedName) != null;
}
}
diff --git a/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Services/ITypeCache.cs b/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Services/ITypeCache.cs
index 3d6d3cfbf9..b5c86bb9b1 100644
--- a/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Services/ITypeCache.cs
+++ b/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Services/ITypeCache.cs
@@ -10,7 +10,7 @@ public interface ITypeCache
Type GetInterfaceType(string fullyQualifiedName);
- Type GetInterfaceProxyType(string fullyQualifiedName);
+ Type GetProxyType(string fullyQualifiedName);
Type GetFrameworkType(JsonModel.Spec.TypeReference reference);
}
diff --git a/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Services/ReferenceMap.cs b/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Services/ReferenceMap.cs
index 0b8c171906..609ab784fb 100644
--- a/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Services/ReferenceMap.cs
+++ b/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Services/ReferenceMap.cs
@@ -1,8 +1,8 @@
-using Amazon.JSII.JsonModel.Api;
-using Amazon.JSII.Runtime.Deputy;
-using System;
+using System;
using System.Collections.Generic;
using System.Reflection;
+using Amazon.JSII.JsonModel.Api;
+using Amazon.JSII.Runtime.Deputy;
namespace Amazon.JSII.Runtime.Services
{
@@ -20,7 +20,9 @@ public void AddNativeReference(ByRefValue reference, DeputyBase nativeReference)
{
if (_references.ContainsKey(reference.Value))
{
- throw new ArgumentException($"Cannot add reference for {reference.Value}: A reference with this name already exists", nameof(reference));
+ throw new ArgumentException(
+ $"Cannot add reference for {reference.Value}: A reference with this name already exists",
+ nameof(reference));
}
_references[reference.Value] = nativeReference;
@@ -36,7 +38,7 @@ public DeputyBase GetOrCreateNativeReference(ByRefValue byRefValue)
if (!_references.ContainsKey(byRefValue.Value))
{
ConstructorInfo constructorInfo = GetByRefConstructor();
- _references[byRefValue.Value] = (DeputyBase)constructorInfo.Invoke(new object[] { byRefValue });
+ _references[byRefValue.Value] = (DeputyBase) constructorInfo.Invoke(new object[] {byRefValue});
}
return _references[byRefValue.Value];
@@ -44,10 +46,13 @@ public DeputyBase GetOrCreateNativeReference(ByRefValue byRefValue)
ConstructorInfo GetByRefConstructor()
{
Type type = _types.GetClassType(byRefValue.FullyQualifiedName);
- if (type == null)
+
+ // If type is an interface or abstract class
+ if (type == null || type.IsAbstract)
{
- type = _types.GetInterfaceProxyType(byRefValue.FullyQualifiedName);
+ type = _types.GetProxyType(byRefValue.FullyQualifiedName);
}
+
if (type == null)
{
throw new ArgumentException(
@@ -58,8 +63,8 @@ ConstructorInfo GetByRefConstructor()
BindingFlags constructorFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
- return type.GetConstructor(constructorFlags, null, new[] { typeof(ByRefValue) }, null);
+ return type.GetConstructor(constructorFlags, null, new[] {typeof(ByRefValue)}, null);
}
}
}
-}
+}
\ No newline at end of file
diff --git a/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Services/TypeCache.cs b/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Services/TypeCache.cs
index b0a5fac060..932df17336 100644
--- a/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Services/TypeCache.cs
+++ b/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Services/TypeCache.cs
@@ -1,11 +1,13 @@
-using Microsoft.Extensions.Logging;
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
-using PrimitiveType = Amazon.JSII.JsonModel.Spec.PrimitiveType;
-using CollectionKind = Amazon.JSII.JsonModel.Spec.CollectionKind;
+using Amazon.JSII.JsonModel.Spec;
using Amazon.JSII.Runtime.Deputy;
+using Microsoft.Extensions.Logging;
+using Newtonsoft.Json.Linq;
+using Assembly = System.Reflection.Assembly;
+using Type = System.Type;
namespace Amazon.JSII.Runtime.Services
{
@@ -42,12 +44,12 @@ public Type GetInterfaceType(string fullyQualifiedName)
return GetType(fullyQualifiedName);
}
- public Type GetInterfaceProxyType(string fullyQualifiedName)
+ public Type GetProxyType(string fullyQualifiedName)
{
- return GetType(fullyQualifiedName + ProxySuffix);
+ return GetType(fullyQualifiedName + ProxySuffix);
}
- public Type GetFrameworkType(JsonModel.Spec.TypeReference reference)
+ public Type GetFrameworkType(TypeReference reference)
{
bool isOptional = reference.IsOptional == true;
@@ -79,7 +81,7 @@ public Type GetFrameworkType(JsonModel.Spec.TypeReference reference)
case PrimitiveType.Date:
return MakeNullableIfOptional(typeof(DateTime));
case PrimitiveType.Json:
- return typeof(Newtonsoft.Json.Linq.JObject);
+ return typeof(JObject);
case PrimitiveType.Number:
return MakeNullableIfOptional(typeof(double));
case PrimitiveType.String:
@@ -158,7 +160,7 @@ void CacheTypes(Assembly assembly)
if (attribute != null)
{
string fullyQualifiedName = attribute.FullyQualifiedName;
- if (attribute is JsiiInterfaceProxyAttribute)
+ if (attribute is JsiiTypeProxyAttribute)
{
fullyQualifiedName += ProxySuffix;
}
diff --git a/packages/jsii-pacmak/test/expected.jsii-calc-base/dotnet/Amazon.JSII.Tests.CalculatorPackageId.BasePackageId/Amazon/JSII/Tests/CalculatorNamespace/BaseNamespace/BasePropsProxy.cs b/packages/jsii-pacmak/test/expected.jsii-calc-base/dotnet/Amazon.JSII.Tests.CalculatorPackageId.BasePackageId/Amazon/JSII/Tests/CalculatorNamespace/BaseNamespace/BasePropsProxy.cs
index 5a291279e5..afbeecf9b7 100644
--- a/packages/jsii-pacmak/test/expected.jsii-calc-base/dotnet/Amazon.JSII.Tests.CalculatorPackageId.BasePackageId/Amazon/JSII/Tests/CalculatorNamespace/BaseNamespace/BasePropsProxy.cs
+++ b/packages/jsii-pacmak/test/expected.jsii-calc-base/dotnet/Amazon.JSII.Tests.CalculatorPackageId.BasePackageId/Amazon/JSII/Tests/CalculatorNamespace/BaseNamespace/BasePropsProxy.cs
@@ -3,22 +3,22 @@
namespace Amazon.JSII.Tests.CalculatorNamespace.BaseNamespace
{
- [JsiiInterfaceProxy(typeof(IBaseProps), "@scope/jsii-calc-base.BaseProps")]
- internal class BasePropsProxy : DeputyBase, IBaseProps
+ [JsiiTypeProxy(typeof(IBaseProps), "@scope/jsii-calc-base.BaseProps")]
+ internal sealed class BasePropsProxy : DeputyBase, IBaseProps
{
private BasePropsProxy(ByRefValue reference): base(reference)
{
}
[JsiiProperty("bar", "{\"primitive\":\"string\"}")]
- public virtual string Bar
+ public string Bar
{
get => GetInstanceProperty();
set => SetInstanceProperty(value);
}
[JsiiProperty("foo", "{\"fqn\":\"@scope/jsii-calc-base-of-base.Very\"}")]
- public virtual Very Foo
+ public Very Foo
{
get => GetInstanceProperty();
set => SetInstanceProperty(value);
diff --git a/packages/jsii-pacmak/test/expected.jsii-calc-base/dotnet/Amazon.JSII.Tests.CalculatorPackageId.BasePackageId/Amazon/JSII/Tests/CalculatorNamespace/BaseNamespace/BaseProxy.cs b/packages/jsii-pacmak/test/expected.jsii-calc-base/dotnet/Amazon.JSII.Tests.CalculatorPackageId.BasePackageId/Amazon/JSII/Tests/CalculatorNamespace/BaseNamespace/BaseProxy.cs
new file mode 100644
index 0000000000..032ef8a878
--- /dev/null
+++ b/packages/jsii-pacmak/test/expected.jsii-calc-base/dotnet/Amazon.JSII.Tests.CalculatorPackageId.BasePackageId/Amazon/JSII/Tests/CalculatorNamespace/BaseNamespace/BaseProxy.cs
@@ -0,0 +1,13 @@
+using Amazon.JSII.Runtime.Deputy;
+
+namespace Amazon.JSII.Tests.CalculatorNamespace.BaseNamespace
+{
+ /// A base class.
+ [JsiiTypeProxy(typeof(Base), "@scope/jsii-calc-base.Base")]
+ internal sealed class BaseProxy : Base
+ {
+ private BaseProxy(ByRefValue reference): base(reference)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/Amazon/JSII/Tests/CalculatorNamespace/LibNamespace/IFriendlyProxy.cs b/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/Amazon/JSII/Tests/CalculatorNamespace/LibNamespace/IFriendlyProxy.cs
index 95ac50beeb..de8c7ddfb5 100644
--- a/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/Amazon/JSII/Tests/CalculatorNamespace/LibNamespace/IFriendlyProxy.cs
+++ b/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/Amazon/JSII/Tests/CalculatorNamespace/LibNamespace/IFriendlyProxy.cs
@@ -6,8 +6,8 @@ namespace Amazon.JSII.Tests.CalculatorNamespace.LibNamespace
/// Applies to classes that are considered friendly. These classes can be greeted with
/// a "hello" or "goodbye" blessing and they will respond back in a fun and friendly manner.
///
- [JsiiInterfaceProxy(typeof(IIFriendly), "@scope/jsii-calc-lib.IFriendly")]
- internal class IFriendlyProxy : DeputyBase, IIFriendly
+ [JsiiTypeProxy(typeof(IIFriendly), "@scope/jsii-calc-lib.IFriendly")]
+ internal sealed class IFriendlyProxy : DeputyBase, IIFriendly
{
private IFriendlyProxy(ByRefValue reference): base(reference)
{
@@ -15,7 +15,7 @@ private IFriendlyProxy(ByRefValue reference): base(reference)
/// Say hello!
[JsiiMethod("hello", "{\"primitive\":\"string\"}", "[]")]
- public virtual string Hello()
+ public string Hello()
{
return InvokeInstanceMethod(new object[]{});
}
diff --git a/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/Amazon/JSII/Tests/CalculatorNamespace/LibNamespace/MyFirstStructProxy.cs b/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/Amazon/JSII/Tests/CalculatorNamespace/LibNamespace/MyFirstStructProxy.cs
index 10ed352430..42231e2055 100644
--- a/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/Amazon/JSII/Tests/CalculatorNamespace/LibNamespace/MyFirstStructProxy.cs
+++ b/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/Amazon/JSII/Tests/CalculatorNamespace/LibNamespace/MyFirstStructProxy.cs
@@ -3,8 +3,8 @@
namespace Amazon.JSII.Tests.CalculatorNamespace.LibNamespace
{
/// This is the first struct we have created in jsii
- [JsiiInterfaceProxy(typeof(IMyFirstStruct), "@scope/jsii-calc-lib.MyFirstStruct")]
- internal class MyFirstStructProxy : DeputyBase, IMyFirstStruct
+ [JsiiTypeProxy(typeof(IMyFirstStruct), "@scope/jsii-calc-lib.MyFirstStruct")]
+ internal sealed class MyFirstStructProxy : DeputyBase, IMyFirstStruct
{
private MyFirstStructProxy(ByRefValue reference): base(reference)
{
@@ -12,7 +12,7 @@ private MyFirstStructProxy(ByRefValue reference): base(reference)
/// An awesome number value
[JsiiProperty("anumber", "{\"primitive\":\"number\"}")]
- public virtual double Anumber
+ public double Anumber
{
get => GetInstanceProperty();
set => SetInstanceProperty(value);
@@ -20,14 +20,14 @@ public virtual double Anumber
/// A string value
[JsiiProperty("astring", "{\"primitive\":\"string\"}")]
- public virtual string Astring
+ public string Astring
{
get => GetInstanceProperty();
set => SetInstanceProperty(value);
}
[JsiiProperty("firstOptional", "{\"collection\":{\"kind\":\"array\",\"elementtype\":{\"primitive\":\"string\"}},\"optional\":true}")]
- public virtual string[] FirstOptional
+ public string[] FirstOptional
{
get => GetInstanceProperty();
set => SetInstanceProperty(value);
diff --git a/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/Amazon/JSII/Tests/CalculatorNamespace/LibNamespace/OperationProxy.cs b/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/Amazon/JSII/Tests/CalculatorNamespace/LibNamespace/OperationProxy.cs
new file mode 100644
index 0000000000..d12a386669
--- /dev/null
+++ b/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/Amazon/JSII/Tests/CalculatorNamespace/LibNamespace/OperationProxy.cs
@@ -0,0 +1,27 @@
+using Amazon.JSII.Runtime.Deputy;
+
+namespace Amazon.JSII.Tests.CalculatorNamespace.LibNamespace
+{
+ /// Represents an operation on values.
+ [JsiiTypeProxy(typeof(Operation), "@scope/jsii-calc-lib.Operation")]
+ internal sealed class OperationProxy : Operation
+ {
+ private OperationProxy(ByRefValue reference): base(reference)
+ {
+ }
+
+ /// The value.
+ [JsiiProperty("value", "{\"primitive\":\"number\"}")]
+ public override double Value
+ {
+ get => GetInstanceProperty();
+ }
+
+ /// String representation of the value.
+ [JsiiMethod("toString", "{\"primitive\":\"string\"}", "[]")]
+ public override string ToString()
+ {
+ return InvokeInstanceMethod(new object[]{});
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/Amazon/JSII/Tests/CalculatorNamespace/LibNamespace/StructWithOnlyOptionalsProxy.cs b/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/Amazon/JSII/Tests/CalculatorNamespace/LibNamespace/StructWithOnlyOptionalsProxy.cs
index da65e4918b..8b6ba827ce 100644
--- a/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/Amazon/JSII/Tests/CalculatorNamespace/LibNamespace/StructWithOnlyOptionalsProxy.cs
+++ b/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/Amazon/JSII/Tests/CalculatorNamespace/LibNamespace/StructWithOnlyOptionalsProxy.cs
@@ -3,8 +3,8 @@
namespace Amazon.JSII.Tests.CalculatorNamespace.LibNamespace
{
/// This is a struct with only optional properties.
- [JsiiInterfaceProxy(typeof(IStructWithOnlyOptionals), "@scope/jsii-calc-lib.StructWithOnlyOptionals")]
- internal class StructWithOnlyOptionalsProxy : DeputyBase, IStructWithOnlyOptionals
+ [JsiiTypeProxy(typeof(IStructWithOnlyOptionals), "@scope/jsii-calc-lib.StructWithOnlyOptionals")]
+ internal sealed class StructWithOnlyOptionalsProxy : DeputyBase, IStructWithOnlyOptionals
{
private StructWithOnlyOptionalsProxy(ByRefValue reference): base(reference)
{
@@ -12,21 +12,21 @@ private StructWithOnlyOptionalsProxy(ByRefValue reference): base(reference)
/// The first optional!
[JsiiProperty("optional1", "{\"primitive\":\"string\",\"optional\":true}")]
- public virtual string Optional1
+ public string Optional1
{
get => GetInstanceProperty();
set => SetInstanceProperty(value);
}
[JsiiProperty("optional2", "{\"primitive\":\"number\",\"optional\":true}")]
- public virtual double? Optional2
+ public double? Optional2
{
get => GetInstanceProperty();
set => SetInstanceProperty(value);
}
[JsiiProperty("optional3", "{\"primitive\":\"boolean\",\"optional\":true}")]
- public virtual bool? Optional3
+ public bool? Optional3
{
get => GetInstanceProperty();
set => SetInstanceProperty(value);
diff --git a/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/Amazon/JSII/Tests/CalculatorNamespace/LibNamespace/ValueProxy.cs b/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/Amazon/JSII/Tests/CalculatorNamespace/LibNamespace/ValueProxy.cs
new file mode 100644
index 0000000000..8dbda90606
--- /dev/null
+++ b/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/Amazon/JSII/Tests/CalculatorNamespace/LibNamespace/ValueProxy.cs
@@ -0,0 +1,20 @@
+using Amazon.JSII.Runtime.Deputy;
+
+namespace Amazon.JSII.Tests.CalculatorNamespace.LibNamespace
+{
+ /// Abstract class which represents a numeric value.
+ [JsiiTypeProxy(typeof(Value_), "@scope/jsii-calc-lib.Value")]
+ internal sealed class ValueProxy : Value_
+ {
+ private ValueProxy(ByRefValue reference): base(reference)
+ {
+ }
+
+ /// The value.
+ [JsiiProperty("value", "{\"primitive\":\"number\"}")]
+ public override double Value
+ {
+ get => GetInstanceProperty();
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/AbstractClassBaseProxy.cs b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/AbstractClassBaseProxy.cs
new file mode 100644
index 0000000000..d12f04de48
--- /dev/null
+++ b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/AbstractClassBaseProxy.cs
@@ -0,0 +1,18 @@
+using Amazon.JSII.Runtime.Deputy;
+
+namespace Amazon.JSII.Tests.CalculatorNamespace
+{
+ [JsiiTypeProxy(typeof(AbstractClassBase), "jsii-calc.AbstractClassBase")]
+ internal sealed class AbstractClassBaseProxy : AbstractClassBase
+ {
+ private AbstractClassBaseProxy(ByRefValue reference): base(reference)
+ {
+ }
+
+ [JsiiProperty("abstractProperty", "{\"primitive\":\"string\"}")]
+ public override string AbstractProperty
+ {
+ get => GetInstanceProperty();
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/AbstractClassProxy.cs b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/AbstractClassProxy.cs
new file mode 100644
index 0000000000..97918b1966
--- /dev/null
+++ b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/AbstractClassProxy.cs
@@ -0,0 +1,24 @@
+using Amazon.JSII.Runtime.Deputy;
+
+namespace Amazon.JSII.Tests.CalculatorNamespace
+{
+ [JsiiTypeProxy(typeof(AbstractClass), "jsii-calc.AbstractClass")]
+ internal sealed class AbstractClassProxy : AbstractClass
+ {
+ private AbstractClassProxy(ByRefValue reference): base(reference)
+ {
+ }
+
+ [JsiiProperty("abstractProperty", "{\"primitive\":\"string\"}")]
+ public override string AbstractProperty
+ {
+ get => GetInstanceProperty();
+ }
+
+ [JsiiMethod("abstractMethod", "{\"primitive\":\"string\"}", "[{\"name\":\"name\",\"type\":{\"primitive\":\"string\"}}]")]
+ public override string AbstractMethod(string name)
+ {
+ return InvokeInstanceMethod(new object[]{name});
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/BinaryOperationProxy.cs b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/BinaryOperationProxy.cs
new file mode 100644
index 0000000000..46799d122d
--- /dev/null
+++ b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/BinaryOperationProxy.cs
@@ -0,0 +1,27 @@
+using Amazon.JSII.Runtime.Deputy;
+
+namespace Amazon.JSII.Tests.CalculatorNamespace
+{
+ /// Represents an operation with two operands.
+ [JsiiTypeProxy(typeof(BinaryOperation), "jsii-calc.BinaryOperation")]
+ internal sealed class BinaryOperationProxy : BinaryOperation
+ {
+ private BinaryOperationProxy(ByRefValue reference): base(reference)
+ {
+ }
+
+ /// The value.
+ [JsiiProperty("value", "{\"primitive\":\"number\"}")]
+ public override double Value
+ {
+ get => GetInstanceProperty();
+ }
+
+ /// String representation of the value.
+ [JsiiMethod("toString", "{\"primitive\":\"string\"}", "[]")]
+ public override string ToString()
+ {
+ return InvokeInstanceMethod(new object[]{});
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/CalculatorPropsProxy.cs b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/CalculatorPropsProxy.cs
index 3d8ba2c089..931e805cde 100644
--- a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/CalculatorPropsProxy.cs
+++ b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/CalculatorPropsProxy.cs
@@ -3,22 +3,22 @@
namespace Amazon.JSII.Tests.CalculatorNamespace
{
/// Properties for Calculator.
- [JsiiInterfaceProxy(typeof(ICalculatorProps), "jsii-calc.CalculatorProps")]
- internal class CalculatorPropsProxy : DeputyBase, ICalculatorProps
+ [JsiiTypeProxy(typeof(ICalculatorProps), "jsii-calc.CalculatorProps")]
+ internal sealed class CalculatorPropsProxy : DeputyBase, ICalculatorProps
{
private CalculatorPropsProxy(ByRefValue reference): base(reference)
{
}
[JsiiProperty("initialValue", "{\"primitive\":\"number\",\"optional\":true}")]
- public virtual double? InitialValue
+ public double? InitialValue
{
get => GetInstanceProperty();
set => SetInstanceProperty(value);
}
[JsiiProperty("maximumValue", "{\"primitive\":\"number\",\"optional\":true}")]
- public virtual double? MaximumValue
+ public double? MaximumValue
{
get => GetInstanceProperty();
set => SetInstanceProperty(value);
diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/DerivedStructProxy.cs b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/DerivedStructProxy.cs
index 59adc06210..67004f86bc 100644
--- a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/DerivedStructProxy.cs
+++ b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/DerivedStructProxy.cs
@@ -6,22 +6,22 @@
namespace Amazon.JSII.Tests.CalculatorNamespace
{
/// A struct which derives from another struct.
- [JsiiInterfaceProxy(typeof(IDerivedStruct), "jsii-calc.DerivedStruct")]
- internal class DerivedStructProxy : DeputyBase, IDerivedStruct
+ [JsiiTypeProxy(typeof(IDerivedStruct), "jsii-calc.DerivedStruct")]
+ internal sealed class DerivedStructProxy : DeputyBase, IDerivedStruct
{
private DerivedStructProxy(ByRefValue reference): base(reference)
{
}
[JsiiProperty("anotherRequired", "{\"primitive\":\"date\"}")]
- public virtual DateTime AnotherRequired
+ public DateTime AnotherRequired
{
get => GetInstanceProperty();
set => SetInstanceProperty(value);
}
[JsiiProperty("bool", "{\"primitive\":\"boolean\"}")]
- public virtual bool Bool
+ public bool Bool
{
get => GetInstanceProperty();
set => SetInstanceProperty(value);
@@ -29,7 +29,7 @@ public virtual bool Bool
/// An example of a non primitive property.
[JsiiProperty("nonPrimitive", "{\"fqn\":\"jsii-calc.DoubleTrouble\"}")]
- public virtual DoubleTrouble NonPrimitive
+ public DoubleTrouble NonPrimitive
{
get => GetInstanceProperty();
set => SetInstanceProperty(value);
@@ -37,21 +37,21 @@ public virtual DoubleTrouble NonPrimitive
/// This is optional.
[JsiiProperty("anotherOptional", "{\"collection\":{\"kind\":\"map\",\"elementtype\":{\"fqn\":\"@scope/jsii-calc-lib.Value\"}},\"optional\":true}")]
- public virtual IDictionary AnotherOptional
+ public IDictionary AnotherOptional
{
get => GetInstanceProperty>();
set => SetInstanceProperty(value);
}
[JsiiProperty("optionalAny", "{\"primitive\":\"any\",\"optional\":true}")]
- public virtual object OptionalAny
+ public object OptionalAny
{
get => GetInstanceProperty