From e1367591d80643ef7a762b8ee8b2dd9ccd328289 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Fri, 3 Jan 2020 11:59:55 +0100 Subject: [PATCH 1/2] fix(rosetta): crashes on behavioral interfaces Behavioral interfaces (`ISomething`) weren't translated at all, and used to crash the Java translator. Add translations for them. Make the `jsii-rosetta` command-line tool more robust against errors in the translator: catch and report the error, instead of crashing. Add support for shorthand property assignments in object literals (`someFunction({ foo });`) for Java as well, which wasn't covered by any test yet. --- packages/jsii-rosetta/lib/commands/extract.ts | 17 +++- packages/jsii-rosetta/lib/languages/csharp.ts | 31 ++++++- .../jsii-rosetta/lib/languages/default.ts | 8 +- packages/jsii-rosetta/lib/languages/java.ts | 91 ++++++++++++++----- packages/jsii-rosetta/lib/languages/python.ts | 6 ++ packages/jsii-rosetta/lib/renderer.ts | 13 ++- .../jsii-rosetta/test/translations.test.ts | 3 +- .../calls/default_struct_fields.cs | 4 +- .../translations/calls/shorthand_property.cs | 2 + .../calls/shorthand_property.java | 2 + .../translations/calls/shorthand_property.py | 2 + .../translations/calls/shorthand_property.ts | 2 + ...ucts_directly_if_type_info_is_available.cs | 8 +- .../classes/class_with_props_argument.cs | 4 +- .../expressions/struct_assignment.cs | 2 +- .../interfaces/interface_with_method.cs | 4 + .../interfaces/interface_with_method.java | 3 + .../interfaces/interface_with_method.ts | 3 + .../interfaces/interface_with_props.cs | 4 + .../interfaces/interface_with_props.java | 3 + .../interfaces/interface_with_props.ts | 3 + 21 files changed, 172 insertions(+), 43 deletions(-) create mode 100644 packages/jsii-rosetta/test/translations/calls/shorthand_property.cs create mode 100644 packages/jsii-rosetta/test/translations/calls/shorthand_property.java create mode 100644 packages/jsii-rosetta/test/translations/calls/shorthand_property.py create mode 100644 packages/jsii-rosetta/test/translations/calls/shorthand_property.ts create mode 100644 packages/jsii-rosetta/test/translations/interfaces/interface_with_method.cs create mode 100644 packages/jsii-rosetta/test/translations/interfaces/interface_with_method.java create mode 100644 packages/jsii-rosetta/test/translations/interfaces/interface_with_method.ts create mode 100644 packages/jsii-rosetta/test/translations/interfaces/interface_with_props.cs create mode 100644 packages/jsii-rosetta/test/translations/interfaces/interface_with_props.java create mode 100644 packages/jsii-rosetta/test/translations/interfaces/interface_with_props.ts diff --git a/packages/jsii-rosetta/lib/commands/extract.ts b/packages/jsii-rosetta/lib/commands/extract.ts index 6d994b3f00..d504f9f535 100644 --- a/packages/jsii-rosetta/lib/commands/extract.ts +++ b/packages/jsii-rosetta/lib/commands/extract.ts @@ -96,12 +96,25 @@ async function translateAll(snippets: IterableIterator, inclu export function singleThreadedTranslateAll(snippets: IterableIterator, includeCompilerDiagnostics: boolean): TranslateAllResult { const translatedSnippets = new Array(); + const failures = new Array(); + const translator = new Translator(includeCompilerDiagnostics); for (const block of snippets) { - translatedSnippets.push(translator.translate(block)); + try { + translatedSnippets.push(translator.translate(block)); + } catch(e) { + failures.push({ + category: ts.DiagnosticCategory.Error, + code: 999, + messageText: `Error translating snippet: ${e}\n${block.completeSource}`, + file: undefined, + start: undefined, + length: undefined, + }); + } } - return { translatedSnippets, diagnostics: translator.diagnostics }; + return { translatedSnippets, diagnostics: [...translator.diagnostics, ...failures] }; } /** diff --git a/packages/jsii-rosetta/lib/languages/csharp.ts b/packages/jsii-rosetta/lib/languages/csharp.ts index 81eeed4443..57049deee9 100644 --- a/packages/jsii-rosetta/lib/languages/csharp.ts +++ b/packages/jsii-rosetta/lib/languages/csharp.ts @@ -24,6 +24,11 @@ interface CSharpLanguageContext { */ readonly inStructInterface: boolean; + /** + * So we know how to render property signatures + */ + readonly inRegularInterface: boolean; + /** * So we know how to render property assignments */ @@ -53,9 +58,12 @@ interface CSharpLanguageContext { type CSharpRenderer = AstRenderer; export class CSharpVisitor extends DefaultVisitor { + public readonly language = 'csharp'; + public readonly defaultContext = { propertyOrMethod: false, inStructInterface: false, + inRegularInterface: false, inKeyValueList: false, stringAsIdentifier: false, identifierAsString: false, @@ -136,6 +144,17 @@ export class CSharpVisitor extends DefaultVisitor { return this.functionLike(node, renderer); } + public methodSignature(node: ts.MethodSignature, renderer: CSharpRenderer): OTree { + return new OTree([ + this.renderTypeNode(node.type, false, renderer), + ' ', + renderer.updateContext({ propertyOrMethod: true }).convert(node.name), + '(', + new OTree([], renderer.convertAll(node.parameters), { separator: ', ' }), + ');' + ], [], { canBreakLine: true }); + } + // tslint:disable-next-line:max-line-length public functionLike(node: ts.FunctionLikeDeclarationBase, renderer: CSharpRenderer, opts: { isConstructor?: boolean } = {}): OTree { const methodName = opts.isConstructor ? renderer.currentContext.currentClassName || 'MyClass' : renderer.updateContext({ propertyOrMethod: true }).convert(node.name); @@ -248,13 +267,15 @@ export class CSharpVisitor extends DefaultVisitor { } public propertySignature(node: ts.PropertySignature, renderer: CSharpRenderer): OTree { + const canSet = renderer.currentContext.inStructInterface || !isReadOnly(node); + return new OTree([ - visibility(node), - ' ', + !renderer.currentContext.inRegularInterface ? visibility(node) + ' ' : NO_SYNTAX, this.renderTypeNode(node.type, node.questionToken !== undefined, renderer), ' ', renderer.updateContext({ propertyOrMethod: true }).convert(node.name), - ';', + ' ', + canSet ? '{ get; set; }' : '{ get; }', ], [], { canBreakLine: true }); } @@ -308,7 +329,7 @@ export class CSharpVisitor extends DefaultVisitor { ...this.classHeritage(node, renderer), '\n{', ], - renderer.convertAll(node.members), + renderer.updateContext({ inRegularInterface: true }).convertAll(node.members), { indent: 4, canBreakLine: true, @@ -503,7 +524,7 @@ function typeNameFromType(type: ts.Type, fallback: string): string { } function csharpTypeName(jsTypeName: string | undefined): string { - if (jsTypeName === undefined) { return '???'; } + if (jsTypeName === undefined) { return 'void'; } switch (jsTypeName) { case 'number': return 'int'; case 'any': return 'object'; diff --git a/packages/jsii-rosetta/lib/languages/default.ts b/packages/jsii-rosetta/lib/languages/default.ts index 6cc274435c..f62853ef69 100644 --- a/packages/jsii-rosetta/lib/languages/default.ts +++ b/packages/jsii-rosetta/lib/languages/default.ts @@ -5,12 +5,14 @@ import { ImportStatement } from '../typescript/imports'; import { isStructInterface, isStructType } from '../jsii/jsii-utils'; import { mapElementType, typeWithoutUndefinedUnion } from '../typescript/types'; import { voidExpressionString } from '../typescript/ast-utils'; +import { TargetLanguage } from '.'; /** * A basic visitor that applies for most curly-braces-based languages */ export abstract class DefaultVisitor implements AstHandler { public abstract readonly defaultContext: C; + public abstract readonly language: TargetLanguage; public abstract mergeContext(old: C, update: C): C; @@ -240,6 +242,10 @@ export abstract class DefaultVisitor implements AstHandler { return this.notImplemented(node, context); } + public methodSignature(node: ts.MethodSignature, context: AstRenderer): OTree { + return this.notImplemented(node, context); + } + public asExpression(node: ts.AsExpression, context: AstRenderer): OTree { return this.notImplemented(node, context); } @@ -284,7 +290,7 @@ export abstract class DefaultVisitor implements AstHandler { } private notImplemented(node: ts.Node, context: AstRenderer) { - context.reportUnsupported(node); + context.reportUnsupported(node, this.language); return nimpl(node, context); } } diff --git a/packages/jsii-rosetta/lib/languages/java.ts b/packages/jsii-rosetta/lib/languages/java.ts index c815978851..9ab37adc22 100644 --- a/packages/jsii-rosetta/lib/languages/java.ts +++ b/packages/jsii-rosetta/lib/languages/java.ts @@ -1,7 +1,7 @@ import * as ts from 'typescript'; import { DefaultVisitor } from './default'; import { AstRenderer } from '../renderer'; -import { OTree } from '../o-tree'; +import { OTree, NO_SYNTAX } from '../o-tree'; import { builtInTypeName, mapElementType, typeWithoutUndefinedUnion } from '../typescript/types'; import { isReadOnly, matchAst, nodeOfType, quoteStringLiteral, visibility } from '../typescript/ast-utils'; import { ImportStatement } from '../typescript/imports'; @@ -72,11 +72,17 @@ interface InsideTypeDeclaration { * Needed to correctly generate the constructor. */ readonly typeName: ts.Node | undefined; + + /** + * Is this an interface (true) or a class (unset/false) + */ + readonly isInterface?: boolean; } type JavaRenderer = AstRenderer; export class JavaVisitor extends DefaultVisitor { + public readonly language = 'java'; public readonly defaultContext = {}; public mergeContext(old: JavaContext, update: Partial): JavaContext { @@ -110,11 +116,34 @@ export class JavaVisitor extends DefaultVisitor { return this.renderClassDeclaration(node, renderer); } + public regularInterfaceDeclaration(node: ts.InterfaceDeclaration, renderer: JavaRenderer): OTree { + return new OTree( + [ + 'public ', + 'interface ', + renderer.convert(node.name), + ...this.typeHeritage(node, renderer.updateContext({ ignorePropertyPrefix: true })), + ' {', + ], + renderer + .updateContext({ insideTypeDeclaration: { typeName: node.name, isInterface: true } }) + .convertAll(node.members), + { + indent: 4, + canBreakLine: true, + suffix: '\n}', + }, + ); + } + public propertySignature(node: ts.PropertySignature, renderer: JavaRenderer): OTree { const propertyType = this.renderTypeNode(node.type, renderer, 'Object'); const propertyName = renderer.convert(node.name); - const field = new OTree( + const isClass = !renderer.currentContext.insideTypeDeclaration?.isInterface; + const blockSep = isClass ? ' ' : ';'; + + const field = isClass ? new OTree( [], [ 'private ', @@ -126,16 +155,16 @@ export class JavaVisitor extends DefaultVisitor { { canBreakLine: true, }, - ); + ) : NO_SYNTAX; const getter = new OTree( [], [ - 'public ', + isClass ? 'public ' : NO_SYNTAX, propertyType, ' ', - `get${capitalize(renderer.textOf(node.name))}() `, - this.renderBlock([ + `get${capitalize(renderer.textOf(node.name))}()${blockSep}`, + isClass ? this.renderBlock([ new OTree( [ '\n', @@ -146,17 +175,19 @@ export class JavaVisitor extends DefaultVisitor { ';', ], ), - ]), + ]) : NO_SYNTAX, ], { canBreakLine: true, }, ); - const setter = new OTree( + const hasSetter = isClass || !isReadOnly(node); + + const setter = hasSetter ? new OTree( [], [ - 'public ', + isClass ? 'public ' : NO_SYNTAX, renderer.convert(renderer.currentContext.insideTypeDeclaration!.typeName), ' ', propertyName, // don't prefix the setter with `set` - makes it more aligned with JSII builders @@ -164,8 +195,8 @@ export class JavaVisitor extends DefaultVisitor { propertyType, ' ', propertyName, - ') ', - this.renderBlock([ + `)${blockSep}`, + isClass ? this.renderBlock([ new OTree( [ '\n', @@ -186,12 +217,12 @@ export class JavaVisitor extends DefaultVisitor { 'return this;', ], ), - ]), + ]) : NO_SYNTAX, ], { canBreakLine: true, }, - ); + ) : NO_SYNTAX; return new OTree([], [field, getter, setter], { canBreakLine: true, separator: '\n' }); } @@ -234,6 +265,18 @@ export class JavaVisitor extends DefaultVisitor { this.renderTypeNode(node.type, renderer, 'void')); } + public methodSignature(node: ts.MethodSignature, renderer: JavaRenderer): OTree { + return new OTree([ + this.renderTypeNode(node.type, renderer, 'void'), + ' ', + renderer.convert(node.name), + '(', + new OTree([], renderer.convertAll(node.parameters), { separator: ', ' }), + ');', + ], [], { canBreakLine: true }, + ); + } + public parameterDeclaration(node: ts.ParameterDeclaration, renderer: JavaRenderer): OTree { return new OTree([ this.renderTypeNode(node.type, renderer), @@ -472,8 +515,14 @@ export class JavaVisitor extends DefaultVisitor { public propertyAssignment(node: ts.PropertyAssignment, renderer: JavaRenderer): OTree { return renderer.currentContext.inKeyValueList - ? this.singlePropertyInJavaScriptObjectLiteralToJavaMap(node, renderer) - : this.singlePropertyInJavaScriptObjectLiteralToFluentSetters(node, renderer); + ? this.singlePropertyInJavaScriptObjectLiteralToJavaMap(node.name, node.initializer, renderer) + : this.singlePropertyInJavaScriptObjectLiteralToFluentSetters(node.name, node.initializer, renderer); + } + + public shorthandPropertyAssignment(node: ts.ShorthandPropertyAssignment, renderer: JavaRenderer): OTree { + return renderer.currentContext.inKeyValueList + ? this.singlePropertyInJavaScriptObjectLiteralToJavaMap(node.name, node.name, renderer) + : this.singlePropertyInJavaScriptObjectLiteralToFluentSetters(node.name, node.name, renderer); } public propertyAccessExpression(node: ts.PropertyAccessExpression, renderer: JavaRenderer): OTree { @@ -530,13 +579,13 @@ export class JavaVisitor extends DefaultVisitor { ); } - private singlePropertyInJavaScriptObjectLiteralToJavaMap(node: ts.PropertyAssignment, renderer: JavaRenderer): OTree { + private singlePropertyInJavaScriptObjectLiteralToJavaMap(name: ts.Node, initializer: ts.Node, renderer: JavaRenderer): OTree { return new OTree( [], [ - renderer.updateContext({ identifierAsString: true }).convert(node.name), + renderer.updateContext({ identifierAsString: true }).convert(name), ', ', - renderer.updateContext({ inKeyValueList: false }).convert(node.initializer), + renderer.updateContext({ inKeyValueList: false }).convert(initializer), ], { canBreakLine: true, @@ -544,14 +593,14 @@ export class JavaVisitor extends DefaultVisitor { ); } - private singlePropertyInJavaScriptObjectLiteralToFluentSetters(node: ts.PropertyAssignment, renderer: JavaRenderer): OTree { + private singlePropertyInJavaScriptObjectLiteralToFluentSetters(name: ts.Node, initializer: ts.Node, renderer: JavaRenderer): OTree { return new OTree( [], [ '.', - renderer.updateContext({ stringLiteralAsIdentifier: true }).convert(node.name), + renderer.updateContext({ stringLiteralAsIdentifier: true }).convert(name), '(', - renderer.updateContext({ inNewExprWithObjectLiteralAsLastArg: false }).convert(node.initializer), + renderer.updateContext({ inNewExprWithObjectLiteralAsLastArg: false }).convert(initializer), ')', ], { diff --git a/packages/jsii-rosetta/lib/languages/python.ts b/packages/jsii-rosetta/lib/languages/python.ts index 4ee050f89d..0899dc5df6 100644 --- a/packages/jsii-rosetta/lib/languages/python.ts +++ b/packages/jsii-rosetta/lib/languages/python.ts @@ -69,6 +69,7 @@ export interface PythonVisitorOptions { } export class PythonVisitor extends DefaultVisitor { + public readonly language = 'python'; public readonly defaultContext = {}; public constructor(private readonly options: PythonVisitorOptions = {}) { @@ -442,6 +443,11 @@ export class PythonVisitor extends DefaultVisitor { return NO_SYNTAX; } + public methodSignature(_node: ts.MethodSignature, _context: PythonVisitorContext): OTree { + // Does not represent in Python + return NO_SYNTAX; + } + public asExpression(node: ts.AsExpression, context: PythonVisitorContext): OTree { return context.convert(node.expression); } diff --git a/packages/jsii-rosetta/lib/renderer.ts b/packages/jsii-rosetta/lib/renderer.ts index dfe8452eb3..7c608b2d76 100644 --- a/packages/jsii-rosetta/lib/renderer.ts +++ b/packages/jsii-rosetta/lib/renderer.ts @@ -3,6 +3,7 @@ import { NO_SYNTAX, OTree, UnknownSyntax, Span } from './o-tree'; import { commentRangeFromTextRange, extractMaskingVoidExpression, extractShowingVoidExpression, nodeChildren, repeatNewlines, scanText } from './typescript/ast-utils'; import { analyzeImportDeclaration, analyzeImportEquals, ImportStatement } from './typescript/imports'; +import { TargetLanguage } from './languages'; /** * Render a TypeScript AST to some other representation (encoded in OTrees) @@ -136,10 +137,14 @@ export class AstRenderer { }); } - public reportUnsupported(node: ts.Node): void { + public reportUnsupported(node: ts.Node, language: TargetLanguage | undefined): void { const nodeKind = ts.SyntaxKind[node.kind]; // tslint:disable-next-line:max-line-length - this.report(node, `This TypeScript language feature (${nodeKind}) is not supported in examples because we cannot translate it. Please rewrite this example.`); + if (language) { + this.report(node, `This TypeScript feature (${nodeKind}) is not supported in examples because we cannot translate it to ${language}. Please rewrite this example.`); + } else { + this.report(node, `This TypeScript feature (${nodeKind}) is not supported in examples. Please rewrite this example.`); + } } /** @@ -208,6 +213,7 @@ export class AstRenderer { if (ts.isMethodDeclaration(tree)) { return visitor.methodDeclaration(tree, this); } if (ts.isInterfaceDeclaration(tree)) { return visitor.interfaceDeclaration(tree, this); } if (ts.isPropertySignature(tree)) { return visitor.propertySignature(tree, this); } + if (ts.isMethodSignature(tree)) { return visitor.methodSignature(tree, this); } if (ts.isAsExpression(tree)) { return visitor.asExpression(tree, this); } if (ts.isPrefixUnaryExpression(tree)) { return visitor.prefixUnaryExpression(tree, this); } if (ts.isSpreadAssignment(tree)) { @@ -223,7 +229,7 @@ export class AstRenderer { if (ts.isParenthesizedExpression(tree)) { return visitor.parenthesizedExpression(tree, this); } if (ts.isVoidExpression(tree)) { return visitor.maskingVoidExpression(tree, this); } - this.reportUnsupported(tree); + this.reportUnsupported(tree, undefined); if (this.options.bestEffort !== false) { // When doing best-effort conversion and we don't understand the node type, just return the complete text of it as-is @@ -322,6 +328,7 @@ export interface AstHandler { methodDeclaration(node: ts.MethodDeclaration, context: AstRenderer): OTree; interfaceDeclaration(node: ts.InterfaceDeclaration, context: AstRenderer): OTree; propertySignature(node: ts.PropertySignature, context: AstRenderer): OTree; + methodSignature(node: ts.MethodSignature, context: AstRenderer): OTree; asExpression(node: ts.AsExpression, context: AstRenderer): OTree; prefixUnaryExpression(node: ts.PrefixUnaryExpression, context: AstRenderer): OTree; spreadElement(node: ts.SpreadElement, context: AstRenderer): OTree; diff --git a/packages/jsii-rosetta/test/translations.test.ts b/packages/jsii-rosetta/test/translations.test.ts index f3acd790e9..ad7680aaa0 100644 --- a/packages/jsii-rosetta/test/translations.test.ts +++ b/packages/jsii-rosetta/test/translations.test.ts @@ -85,9 +85,8 @@ function makeTests() { testConstructor(`to ${supportedLanguage.name}`, () => { const expected = fs.readFileSync(languageFile, { encoding: 'utf-8' }); - const translation = translator.renderUsing(supportedLanguage.visitor); - try { + const translation = translator.renderUsing(supportedLanguage.visitor); expect(stripEmptyLines(translation)).toEqual(stripEmptyLines(stripCommonWhitespace(expected))); } catch(e) { anyFailed = true; diff --git a/packages/jsii-rosetta/test/translations/calls/default_struct_fields.cs b/packages/jsii-rosetta/test/translations/calls/default_struct_fields.cs index dd66b67b4e..d75f42f3dd 100644 --- a/packages/jsii-rosetta/test/translations/calls/default_struct_fields.cs +++ b/packages/jsii-rosetta/test/translations/calls/default_struct_fields.cs @@ -1,7 +1,7 @@ class Struct { - public string? X; - public string? Y; + public string? X { get; set; } + public string? Y { get; set; } } public void Foo(Struct s) { diff --git a/packages/jsii-rosetta/test/translations/calls/shorthand_property.cs b/packages/jsii-rosetta/test/translations/calls/shorthand_property.cs new file mode 100644 index 0000000000..595427e1b6 --- /dev/null +++ b/packages/jsii-rosetta/test/translations/calls/shorthand_property.cs @@ -0,0 +1,2 @@ +string foo = "hello"; +CallFunction(new Struct { Foo = foo }); \ No newline at end of file diff --git a/packages/jsii-rosetta/test/translations/calls/shorthand_property.java b/packages/jsii-rosetta/test/translations/calls/shorthand_property.java new file mode 100644 index 0000000000..32e91fafb4 --- /dev/null +++ b/packages/jsii-rosetta/test/translations/calls/shorthand_property.java @@ -0,0 +1,2 @@ +String foo = "hello"; +callFunction(Map.of("foo", foo)); \ No newline at end of file diff --git a/packages/jsii-rosetta/test/translations/calls/shorthand_property.py b/packages/jsii-rosetta/test/translations/calls/shorthand_property.py new file mode 100644 index 0000000000..23a24fccb8 --- /dev/null +++ b/packages/jsii-rosetta/test/translations/calls/shorthand_property.py @@ -0,0 +1,2 @@ +foo = "hello" +call_function(foo=foo) \ No newline at end of file diff --git a/packages/jsii-rosetta/test/translations/calls/shorthand_property.ts b/packages/jsii-rosetta/test/translations/calls/shorthand_property.ts new file mode 100644 index 0000000000..418bd61844 --- /dev/null +++ b/packages/jsii-rosetta/test/translations/calls/shorthand_property.ts @@ -0,0 +1,2 @@ +const foo = 'hello'; +callFunction({ foo }); \ No newline at end of file diff --git a/packages/jsii-rosetta/test/translations/calls/will_type_deep_structs_directly_if_type_info_is_available.cs b/packages/jsii-rosetta/test/translations/calls/will_type_deep_structs_directly_if_type_info_is_available.cs index 4f21a6833a..5a887695c9 100644 --- a/packages/jsii-rosetta/test/translations/calls/will_type_deep_structs_directly_if_type_info_is_available.cs +++ b/packages/jsii-rosetta/test/translations/calls/will_type_deep_structs_directly_if_type_info_is_available.cs @@ -1,16 +1,16 @@ class BaseDeeperStruct { - public int A; + public int A { get; set; } } class DeeperStruct : BaseDeeperStruct { - public int B; + public int B { get; set; } } class OuterStruct { - public int Foo; - public DeeperStruct Deeper; + public int Foo { get; set; } + public DeeperStruct Deeper { get; set; } } public void Foo(int x, OuterStruct outer) diff --git a/packages/jsii-rosetta/test/translations/classes/class_with_props_argument.cs b/packages/jsii-rosetta/test/translations/classes/class_with_props_argument.cs index 3838adc964..0deadc6097 100644 --- a/packages/jsii-rosetta/test/translations/classes/class_with_props_argument.cs +++ b/packages/jsii-rosetta/test/translations/classes/class_with_props_argument.cs @@ -1,7 +1,7 @@ class MyClassProps { - public string Prop1; - public int Prop2; + public string Prop1 { get; set; } + public int Prop2 { get; set; } } class MyClass : cdk.SomeOtherClass diff --git a/packages/jsii-rosetta/test/translations/expressions/struct_assignment.cs b/packages/jsii-rosetta/test/translations/expressions/struct_assignment.cs index b79d92274d..975d97e10f 100644 --- a/packages/jsii-rosetta/test/translations/expressions/struct_assignment.cs +++ b/packages/jsii-rosetta/test/translations/expressions/struct_assignment.cs @@ -1,6 +1,6 @@ class Test { - public string Key; + public string Key { get; set; } } Test x = new Test { Key = "value" }; diff --git a/packages/jsii-rosetta/test/translations/interfaces/interface_with_method.cs b/packages/jsii-rosetta/test/translations/interfaces/interface_with_method.cs new file mode 100644 index 0000000000..441b04e9f4 --- /dev/null +++ b/packages/jsii-rosetta/test/translations/interfaces/interface_with_method.cs @@ -0,0 +1,4 @@ +interface IThing +{ + void DoAThing(); +} \ No newline at end of file diff --git a/packages/jsii-rosetta/test/translations/interfaces/interface_with_method.java b/packages/jsii-rosetta/test/translations/interfaces/interface_with_method.java new file mode 100644 index 0000000000..9d0c527e92 --- /dev/null +++ b/packages/jsii-rosetta/test/translations/interfaces/interface_with_method.java @@ -0,0 +1,3 @@ +public interface IThing { + void doAThing(); +} \ No newline at end of file diff --git a/packages/jsii-rosetta/test/translations/interfaces/interface_with_method.ts b/packages/jsii-rosetta/test/translations/interfaces/interface_with_method.ts new file mode 100644 index 0000000000..93eb57145a --- /dev/null +++ b/packages/jsii-rosetta/test/translations/interfaces/interface_with_method.ts @@ -0,0 +1,3 @@ +interface IThing { + doAThing(): void; +} \ No newline at end of file diff --git a/packages/jsii-rosetta/test/translations/interfaces/interface_with_props.cs b/packages/jsii-rosetta/test/translations/interfaces/interface_with_props.cs new file mode 100644 index 0000000000..b387d2810f --- /dev/null +++ b/packages/jsii-rosetta/test/translations/interfaces/interface_with_props.cs @@ -0,0 +1,4 @@ +interface IThing +{ + string ThingArn { get; } +} \ No newline at end of file diff --git a/packages/jsii-rosetta/test/translations/interfaces/interface_with_props.java b/packages/jsii-rosetta/test/translations/interfaces/interface_with_props.java new file mode 100644 index 0000000000..060a9dc09e --- /dev/null +++ b/packages/jsii-rosetta/test/translations/interfaces/interface_with_props.java @@ -0,0 +1,3 @@ +public interface IThing { + String getThingArn(); +} \ No newline at end of file diff --git a/packages/jsii-rosetta/test/translations/interfaces/interface_with_props.ts b/packages/jsii-rosetta/test/translations/interfaces/interface_with_props.ts new file mode 100644 index 0000000000..8d5fba3de7 --- /dev/null +++ b/packages/jsii-rosetta/test/translations/interfaces/interface_with_props.ts @@ -0,0 +1,3 @@ +interface IThing { + readonly thingArn: string; +} From fab7501a9a3b8c89859fc7a7ab0da8dda9ce0616 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Fri, 3 Jan 2020 13:30:01 +0100 Subject: [PATCH 2/2] eslint fixes --- packages/jsii-rosetta/lib/commands/extract.ts | 2 +- packages/jsii-rosetta/lib/languages/csharp.ts | 2 +- packages/jsii-rosetta/lib/languages/java.ts | 15 +++++++-------- packages/jsii-rosetta/lib/languages/visualize.ts | 4 ++++ 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/packages/jsii-rosetta/lib/commands/extract.ts b/packages/jsii-rosetta/lib/commands/extract.ts index d504f9f535..4200342490 100644 --- a/packages/jsii-rosetta/lib/commands/extract.ts +++ b/packages/jsii-rosetta/lib/commands/extract.ts @@ -106,7 +106,7 @@ export function singleThreadedTranslateAll(snippets: IterableIterator { const canSet = renderer.currentContext.inStructInterface || !isReadOnly(node); return new OTree([ - !renderer.currentContext.inRegularInterface ? visibility(node) + ' ' : NO_SYNTAX, + !renderer.currentContext.inRegularInterface ? `${visibility(node)} ` : NO_SYNTAX, this.renderTypeNode(node.type, node.questionToken !== undefined, renderer), ' ', renderer.updateContext({ propertyOrMethod: true }).convert(node.name), diff --git a/packages/jsii-rosetta/lib/languages/java.ts b/packages/jsii-rosetta/lib/languages/java.ts index 9ab37adc22..e8f09000d6 100644 --- a/packages/jsii-rosetta/lib/languages/java.ts +++ b/packages/jsii-rosetta/lib/languages/java.ts @@ -267,14 +267,13 @@ export class JavaVisitor extends DefaultVisitor { public methodSignature(node: ts.MethodSignature, renderer: JavaRenderer): OTree { return new OTree([ - this.renderTypeNode(node.type, renderer, 'void'), - ' ', - renderer.convert(node.name), - '(', - new OTree([], renderer.convertAll(node.parameters), { separator: ', ' }), - ');', - ], [], { canBreakLine: true }, - ); + this.renderTypeNode(node.type, renderer, 'void'), + ' ', + renderer.convert(node.name), + '(', + new OTree([], renderer.convertAll(node.parameters), { separator: ', ' }), + ');', + ], [], { canBreakLine: true }); } public parameterDeclaration(node: ts.ParameterDeclaration, renderer: JavaRenderer): OTree { diff --git a/packages/jsii-rosetta/lib/languages/visualize.ts b/packages/jsii-rosetta/lib/languages/visualize.ts index 619b46e7f0..1a81248309 100644 --- a/packages/jsii-rosetta/lib/languages/visualize.ts +++ b/packages/jsii-rosetta/lib/languages/visualize.ts @@ -138,6 +138,10 @@ export class VisualizeAstVisitor implements AstHandler { return this.defaultNode('propertySignature', node, context); } + public methodSignature(node: ts.MethodSignature, context: AstRenderer): OTree { + return this.defaultNode('methodSignature', node, context); + } + public asExpression(node: ts.AsExpression, context: AstRenderer): OTree { return this.defaultNode('asExpression', node, context); }