diff --git a/migrator/src/com/ohos/migrator/java/JavaTransformer.java b/migrator/src/com/ohos/migrator/java/JavaTransformer.java index fe5c73d17e7a9a44bf03b280fdf29adda9245428..bf5b8d6226fc2c3b4f2084377f5d41d9c953b6b5 100644 --- a/migrator/src/com/ohos/migrator/java/JavaTransformer.java +++ b/migrator/src/com/ohos/migrator/java/JavaTransformer.java @@ -44,6 +44,13 @@ public class JavaTransformer extends ASTVisitor implements Transformer { private final Stack stsSaved = new Stack<>(); private final Stack stsCurrentTrapStatement = new Stack<>(); + // 'nested' methods may be declared through the local classes, + // so the list of collected exceptions for the 'outer' method might get mixed + // with exceptions of the method of 'nested' class so use stack + private final Stack> javaThrownExceptions = new Stack<>(); + + private final String INIT_THROWN_EXEPTIONS = "INIT_THROWN_EXCEPTIONS"; + private final String INSTANCE_INITIALIZER = "INSTANCE_INITIALIZER"; private final String USED_IN_ANOTHER_CASE_CLAUSE = "USED_IN_ANOTHER_CASE_CLAUSE"; private final String ENUM_TYPE_NAME = "ENUM_TYPE_NAME"; @@ -130,6 +137,55 @@ public class JavaTransformer extends ASTVisitor implements Transformer { stsCurrent = stsSaved.pop(); } + // Entering each method create set of exceptions this method may throw + // If exception is caught inside method remove it from set + private void pushExceptionSet() { + Set excpSet = new HashSet<>(); + javaThrownExceptions.push( excpSet ); + } + + private void popExceptionSet() { + javaThrownExceptions.pop(); + } + + private boolean checkThrownExceptionSet(ASTNode javaNode) { + if( javaThrownExceptions.isEmpty()) { + reportError("Not initialized exception set", javaNode); + return false; + } + return true; + } + private Set currentExceptionsSet(ASTNode javaNode) { + if( checkThrownExceptionSet(javaNode)) + return javaThrownExceptions.peek(); + else + return new HashSet(); + } + private void addThrownException(ITypeBinding e) { + // java runtime exceptions transform into STS panics not exceptions + // so exclude them + if( (e != null) && !isRuntimeExceptionType(e) ) + javaThrownExceptions.peek().add(e); + } + + private void addMultipleThrownExceptions( ITypeBinding[] e) { + for( ITypeBinding excp : e) + addThrownException(excp); + } + + private void removeThrownException(ITypeBinding e) { + Set javaExceptionSet = javaThrownExceptions.peek(); + // use Iterator due to bad design of Java collections! + Iterator iterator = javaThrownExceptions.peek().iterator(); + while( iterator.hasNext()) { + // check if catch superclass for exception + ITypeBinding exception = (ITypeBinding) iterator.next(); + if( exception.isSubTypeCompatible(e)) + iterator.remove(); + } + javaThrownExceptions.peek().remove(e); + } + private void pushStatement(ParserRuleContext stsStatement) { if (NodeBuilder.needStatementOrLocalDeclaration(stsCurrent)) pushCurrent(new StatementOrLocalDeclarationContext(stsCurrent, 0)); @@ -712,6 +768,7 @@ public class JavaTransformer extends ASTVisitor implements Transformer { // Put statements from instance initializers into constructors which don't call // another constructor (i.e. don't have 'this()' call). List stsInitStmts = (List)javaTypeDeclaration.getProperty(INSTANCE_INITIALIZER); + Set stsInitThrownExceptions = (Set)javaTypeDeclaration.getProperty(INIT_THROWN_EXEPTIONS); if (stsCurrent instanceof ClassBodyContext && stsInitStmts != null && !stsInitStmts.isEmpty()) { ClassBodyContext stsClassBody = (ClassBodyContext) stsCurrent; @@ -721,6 +778,11 @@ public class JavaTransformer extends ASTVisitor implements Transformer { if (stsCtorDecl != null) { addInstanceInitializersToCtor(stsCtorDecl, stsInitStmts); needDefaultCtor = false; + + // if constructor already has 'throws' clause - do nothing + // else check thrown exceptions set for init blocks + if( (stsCtorDecl.Throws() == null) && !stsInitThrownExceptions.isEmpty() ) + stsCtorDecl.addChild(NodeBuilder.terminalNode(StaticTSParser.Throws)); } } @@ -735,6 +797,9 @@ public class JavaTransformer extends ASTVisitor implements Transformer { stsCurrent.addChild(NodeBuilder.terminalNode(StaticTSParser.Constructor)); stsCurrent.addChild(new ConstructorBodyContext(stsCurrent, 0)).setParent(stsCurrent); + if( !stsInitThrownExceptions.isEmpty() ) + stsCurrent.addChild(NodeBuilder.terminalNode(StaticTSParser.Throws)); + popCurrent(); // stsDefaultCtor popCurrent(); // ClassMemberContext @@ -1565,8 +1630,12 @@ public class JavaTransformer extends ASTVisitor implements Transformer { // signature: typeParameters? OpenParen parameterList? CloseParen typeAnnotation @Override public boolean visit(MethodDeclaration javaMethodDeclaration) { + SignatureContext stsSignature = null; + ConstructorDeclarationContext stsConstructor = null; boolean isInClassContext = stsCurrent instanceof ClassBodyContext; assert(isInClassContext || (stsCurrent instanceof InterfaceBodyContext)); + boolean methodHasThrowsClause = false; + Set javaMethodExceptionSet = new HashSet<>(); // Sanity check: Constructors cannot be body-less and methods cannot be without return type Block javaBlock = javaMethodDeclaration.getBody(); @@ -1583,6 +1652,8 @@ public class JavaTransformer extends ASTVisitor implements Transformer { javaMethodDeclaration.toString() + "\n*/\n")); return false; } + // create thrown exception set for current method + pushExceptionSet(); // Get current enclosing context - we'll need it later if // current method is synchronized (see below). Also store @@ -1595,7 +1666,8 @@ public class JavaTransformer extends ASTVisitor implements Transformer { pushCurrent(createDeclarationOrMemberContextWithAccessModifier(javaMods)); if (javaMethodDeclaration.isConstructor()) { - pushCurrent(new ConstructorDeclarationContext(stsCurrent, 0)); + stsConstructor = new ConstructorDeclarationContext(stsCurrent, 0); + pushCurrent(stsConstructor); stsCurrent.addChild(NodeBuilder.terminalNode(StaticTSParser.Constructor)).setParent(stsCurrent); // STS: typeParameters: LessThan typeParameterList? MoreThan @@ -1615,7 +1687,16 @@ public class JavaTransformer extends ASTVisitor implements Transformer { pushCurrent(new ClassMethodWithBodyContext(stsClassMethodDeclaration)); } - translateMethodHeader(javaMethodDeclaration, isInClassContext); + stsSignature = translateMethodHeader(javaMethodDeclaration, isInClassContext); + } + + // process method thrown exceptions + List javaExceptions = javaMethodDeclaration.thrownExceptionTypes(); + methodHasThrowsClause = ! javaExceptions.isEmpty(); + for (Type javaExcp : javaExceptions) { + ITypeBinding javaExcpType = javaExcp.resolveBinding(); + if( !isRuntimeExceptionType(javaExcpType) ) + javaMethodExceptionSet.add(javaExcpType); } if (javaBlock == null) { // Abstract method. @@ -1675,6 +1756,21 @@ public class JavaTransformer extends ASTVisitor implements Transformer { popCurrent(); // ConstructorBodyContext or BlockContext } + // If method has 'throws' clause with exceptions which are not panics - add 'throws' in STS + // else emit message that only panics present + // If there is no 'throws' - get results from analize + if( methodHasThrowsClause && javaMethodExceptionSet.isEmpty()) { + String message = String.format("Java method '%s' throws only panics", javaMethodDeclaration.getName()); + reportError(message, javaMethodDeclaration); + } + if( !javaMethodExceptionSet.isEmpty() || !currentExceptionsSet(javaMethodDeclaration).isEmpty()) { + if( javaMethodDeclaration.isConstructor() ) { + stsConstructor.addChild(NodeBuilder.terminalNode(StaticTSParser.Throws)); + } else if (stsSignature != null) + stsSignature.addChild(NodeBuilder.terminalNode(StaticTSParser.Throws)); + } + popExceptionSet(); // remove thrown exception set for current method + if (javaMethodDeclaration.isConstructor()) { popCurrent(); // ConstructorDeclarationContext } else { @@ -1688,13 +1784,14 @@ public class JavaTransformer extends ASTVisitor implements Transformer { return false; } - private void translateMethodHeader(MethodDeclaration javaMethodDeclaration, boolean isInClassContext) { + private SignatureContext translateMethodHeader(MethodDeclaration javaMethodDeclaration, boolean isInClassContext) { // Non-access modifiers. translateNonAccessModifiers(javaMethodDeclaration, isInClassContext); // STS: signature: typeParameters? OpenParen parameterList? CloseParen typeAnnotation stsCurrent.addChild(NodeBuilder.terminalIdentifier(javaMethodDeclaration.getName())); - pushCurrent(new SignatureContext(stsCurrent, 0)); + SignatureContext stsSignature = new SignatureContext(stsCurrent, 0); + pushCurrent(stsSignature); // STS: typeParameters: LessThan typeParameterList? MoreThan createStsTypeParameters(javaMethodDeclaration.typeParameters()); @@ -1703,14 +1800,22 @@ public class JavaTransformer extends ASTVisitor implements Transformer { createStsParameterList(javaMethodDeclaration.parameters()); // typeAnnotation - pushCurrent(new TypeAnnotationContext(stsCurrent, 0)); - javaMethodDeclaration.getReturnType2().accept(this); + if(javaMethodDeclaration.getReturnType2() != null) { + pushCurrent(new TypeAnnotationContext(stsCurrent, 0)); + javaMethodDeclaration.getReturnType2().accept(this); + } + else { + // Warn and emit __UnknownType__ as variable type + reportError("Failed to resolve method returned type", javaMethodDeclaration); + stsCurrent.addChild(NodeBuilder.unknownTypeAnnotation()).setParent(stsCurrent); + } int javaExtraDims = javaMethodDeclaration.getExtraDimensions(); if (javaExtraDims > 0) NodeBuilder.addExtraDimensions(stsCurrent, javaExtraDims); popCurrent(); // TypeAnnotationContext popCurrent(); // SignatureContext + return stsSignature; } // Java tree: @@ -2189,7 +2294,6 @@ public class JavaTransformer extends ASTVisitor implements Transformer { return false; } - private void translateBlockStatements(Block javaBlock) { List javaBlockStmts = javaBlock.statements(); for(Statement javaStmt : javaBlockStmts) { @@ -2432,17 +2536,24 @@ public class JavaTransformer extends ASTVisitor implements Transformer { // static block @Override public boolean visit(Initializer javaInitializer) { - boolean isStatic = Modifier.isStatic(javaInitializer.getModifiers()); - // Sanity check: Initializers are allowed only in class body context. if (stsCurrent.getRuleIndex() != StaticTSParser.RULE_classBody) { // Warn and emit a comment with original source code of initializer reportError("Invalid context for initializer", javaInitializer); stsCurrent.addChild(NodeBuilder.multiLineComment("/* Untranslated initializer:\n" + - javaInitializer.toString() + "\n*/\n")); + javaInitializer.toString() + "\n*/\n")); return false; } + ASTNode javaInitParent = javaInitializer.getParent(); + Set javaInitThrownExceptions = (Set) javaInitParent.getProperty(INIT_THROWN_EXEPTIONS); + if( javaInitThrownExceptions == null ) { + javaInitThrownExceptions = new HashSet(); + javaInitParent.setProperty(INIT_THROWN_EXEPTIONS, javaInitThrownExceptions); + } + + boolean isStatic = Modifier.isStatic(javaInitializer.getModifiers()); + if (isStatic) { // StaticTS permits only one static initializer per class declaration. // Thus, we gather statements from all Java's static initializers @@ -2483,7 +2594,6 @@ public class JavaTransformer extends ASTVisitor implements Transformer { // StaticTS doesn't have syntax for separate instance initializer blocks. // We gather all statements from such blocks in class declaration and place // at the beginning of all constructor's bodies that don't call another constructor. - ASTNode javaInitParent = javaInitializer.getParent(); List stsInitStmts = (List) javaInitParent.getProperty(INSTANCE_INITIALIZER); if (stsInitStmts == null) { @@ -2496,11 +2606,16 @@ public class JavaTransformer extends ASTVisitor implements Transformer { BlockContext stsBlock = new BlockContext(null, 0); pushCurrent(stsBlock, false); + pushExceptionSet(); + List javaStmts = javaInitializer.getBody().statements(); for(Statement javaStmt : javaStmts) { javaStmt.accept(this); } + javaInitThrownExceptions.addAll(currentExceptionsSet(javaInitializer)); + popExceptionSet(); + popCurrent(); // BlockContext stsInitStmts.addAll(stsBlock.statementOrLocalDeclaration()); @@ -2637,6 +2752,8 @@ public class JavaTransformer extends ASTVisitor implements Transformer { boolean isThrowingCall = false; if (javaCtorBinding != null) { isThrowingCall = javaCtorBinding.getExceptionTypes().length > 0; + if(isThrowingCall && checkThrownExceptionSet(javaCtorInvocation)) + addMultipleThrownExceptions(javaCtorBinding.getExceptionTypes()); } else { reportError("Failed to resolve constructor call", javaCtorInvocation); @@ -2670,6 +2787,8 @@ public class JavaTransformer extends ASTVisitor implements Transformer { boolean isThrowingCall = false; if (javaCtorBinding != null) { isThrowingCall = javaCtorBinding.getExceptionTypes().length > 0; + if(isThrowingCall && checkThrownExceptionSet(javaSuperCtorInvocation)) + addMultipleThrownExceptions(javaCtorBinding.getExceptionTypes()); } else { reportError("Failed to report constructor call", javaSuperCtorInvocation); @@ -2692,8 +2811,9 @@ public class JavaTransformer extends ASTVisitor implements Transformer { pushCurrent(new ConstructorCallContext(stsCurrent, 0)); // Add 'try' keyword if this is a throwing call. - if (isThrowingCall) stsCurrent.addChild(NodeBuilder.terminalNode(StaticTSParser.Try)); - + if (isThrowingCall) { + stsCurrent.addChild(NodeBuilder.terminalNode(StaticTSParser.Try)); + } if (javaCtorExpr != null) { javaCtorExpr.accept(this); } @@ -2896,6 +3016,8 @@ public class JavaTransformer extends ASTVisitor implements Transformer { // Add TryExpressionContext if ctor invoked can throw if (ctorCanThrow) { + if(checkThrownExceptionSet(javaClassInstanceCreation)) + addMultipleThrownExceptions(javaCtorBinding.getExceptionTypes()); pushCurrent(new TryExpressionContext(pushSingleExpression())); stsCurrent.addChild(NodeBuilder.terminalNode(StaticTSParser.Try)); } @@ -3208,6 +3330,8 @@ public class JavaTransformer extends ASTVisitor implements Transformer { // Add TryExpressionContext if this is a throwing call. if (isThrowingCall) { + if(checkThrownExceptionSet(javaMethodInvocation)) + addMultipleThrownExceptions(javaMethodBinding.getExceptionTypes()); pushCurrent(new TryExpressionContext(pushSingleExpression())); stsCurrent.addChild(NodeBuilder.terminalNode(StaticTSParser.Try)); } @@ -3640,6 +3764,7 @@ public class JavaTransformer extends ASTVisitor implements Transformer { pushCurrent(new LambdaExpressionContext(pushSingleExpression())); createStsParameterList(javaLambdaExpr.parameters()); + pushExceptionSet(); // resolveMethodBinding() can throw exceptions, // so let's catch them to make sure we proceed. @@ -3653,6 +3778,8 @@ public class JavaTransformer extends ASTVisitor implements Transformer { if (lambdaMethod != null) { translateType(lambdaMethod.getReturnType(), javaLambdaExpr); + if(checkThrownExceptionSet(javaLambdaExpr)) + addMultipleThrownExceptions(lambdaMethod.getExceptionTypes()); } else { // Warn and emit __UnknownType__ as return type @@ -3675,6 +3802,8 @@ public class JavaTransformer extends ASTVisitor implements Transformer { popCurrent(); // BlockContext } + popExceptionSet(); + popCurrent(); // LambdaBodyContext popSingleExpression(); // LambdaExpressionContext @@ -4276,6 +4405,9 @@ public class JavaTransformer extends ASTVisitor implements Transformer { reportError("Failed to resolve exception type", javaExceptionType); stsCurrent.addChild(NodeBuilder.unknownTypeAnnotation(javaExceptionType)).setParent(stsCurrent); } + // Do check to save some machine cycles on method call + if( !isRuntimeExceptionType(javaExcTypeBinding) && checkThrownExceptionSet(javaClauseBody)) + removeThrownException(javaExcTypeBinding); popCurrent(); // ExceptionParameterContext // NOTE: Can't call javaClauseBody.accept as that will @@ -4554,10 +4686,21 @@ public class JavaTransformer extends ASTVisitor implements Transformer { @Override public boolean visit(ThrowStatement javaThrowStatement) { - // TODO: To be implemented - // Emit __untranslated_statement call with commented-out original syntax as argument for now. - // This is done to avoid building invalid STS AST which causes exceptions in StaticTSWriter. - stsCurrent.addChild(NodeBuilder.untranslatedStatement(javaThrowStatement, stsCurrent)).setParent(stsCurrent); + Expression exceptionExpr = javaThrowStatement.getExpression(); + + if( isRuntimeExceptionType(exceptionExpr.resolveTypeBinding()) ) { + pushStatement(new PanicStatementContext(stsCurrent, 0)); + stsCurrent.addChild(NodeBuilder.terminalNode(StaticTSParser.Panic)); + } else { + pushStatement(new ThrowStatementContext(stsCurrent, 0)); + stsCurrent.addChild(NodeBuilder.terminalNode(StaticTSParser.Throw)); + if(checkThrownExceptionSet(javaThrowStatement)) + addThrownException(exceptionExpr.resolveTypeBinding()); + } + exceptionExpr.accept(this); + + popStatement(); + stmtTransformed.add(javaThrowStatement); return false; } diff --git a/migrator/src/com/ohos/migrator/staticTS/parser/StaticTSLexer.g4 b/migrator/src/com/ohos/migrator/staticTS/parser/StaticTSLexer.g4 index 839c8c4e38f8231d148996a472c4940e4dfe263a..75be039e919cc8431bce180eb267436aa8cd51a5 100644 --- a/migrator/src/com/ohos/migrator/staticTS/parser/StaticTSLexer.g4 +++ b/migrator/src/com/ohos/migrator/staticTS/parser/StaticTSLexer.g4 @@ -122,6 +122,7 @@ Default: 'default'; Assert: 'assert'; If: 'if'; Throw: 'throw'; +Panic: 'panic'; Of: 'of'; Try: 'try'; Defer: 'defer'; @@ -155,6 +156,7 @@ Override: 'override'; Open: 'open'; Const: 'const'; Native: 'native'; +Throws: 'throws'; // Predefined types Byte: 'byte'; diff --git a/migrator/src/com/ohos/migrator/staticTS/parser/StaticTSParser.g4 b/migrator/src/com/ohos/migrator/staticTS/parser/StaticTSParser.g4 index 5d07e2e2d58168ad31f14cd3a4c795a081fd0e26..7b455b61b23b24c244848a62b3fbeb97c8d4ed3c 100644 --- a/migrator/src/com/ohos/migrator/staticTS/parser/StaticTSParser.g4 +++ b/migrator/src/com/ohos/migrator/staticTS/parser/StaticTSParser.g4 @@ -113,7 +113,7 @@ classMember ; constructorDeclaration - : Constructor typeParameters? OpenParen parameterList? CloseParen constructorBody + : Constructor typeParameters? OpenParen parameterList? CloseParen Throws? constructorBody ; parameterList @@ -172,7 +172,7 @@ classInitializer ; signature - : typeParameters? OpenParen parameterList? CloseParen typeAnnotation + : typeParameters? OpenParen parameterList? CloseParen typeAnnotation Throws? ; // Interfaces @@ -327,6 +327,7 @@ statement | returnStatement | labelledStatement | switchStatement + | panicStatement | throwStatement | deferStatement | trapStatement @@ -392,6 +393,10 @@ defaultClause : Default ':' statement* ; +panicStatement + : Panic {this.notLineTerminator()}? singleExpression SemiColon + ; + throwStatement : Throw {this.notLineTerminator()}? singleExpression SemiColon ; diff --git a/migrator/src/com/ohos/migrator/staticTS/writer/StaticTSWriter.java b/migrator/src/com/ohos/migrator/staticTS/writer/StaticTSWriter.java index 3fba2b340c05af650cc40a037126c2d75d643142..4a3cadf5cad3f3fc2a669f418e21838a8c5745fb 100644 --- a/migrator/src/com/ohos/migrator/staticTS/writer/StaticTSWriter.java +++ b/migrator/src/com/ohos/migrator/staticTS/writer/StaticTSWriter.java @@ -402,6 +402,9 @@ public class StaticTSWriter extends StaticTSParserBaseVisitor { visitTypeAnnotation(stsSignature.typeAnnotation()); + if( stsSignature.Throws() != null) + sb.append(' ').append(stsSignature.Throws().getText()).append(' '); + return null; } @@ -433,7 +436,12 @@ public class StaticTSWriter extends StaticTSParserBaseVisitor { visitParameterList(stsParameterList); } - sb.append(") {\n"); + sb.append(')'); + + if( stsConstructorDeclaration.Throws() != null) + sb.append(' ').append(stsConstructorDeclaration.Throws().getText()); + + sb.append(" {\n"); indentIncrement(); visitConstructorBody(stsConstructorDeclaration.constructorBody()); @@ -1210,6 +1218,16 @@ public class StaticTSWriter extends StaticTSParserBaseVisitor { return null; } + @Override + public Void visitPanicStatement(PanicStatementContext stsPanicStatement) { + doNeededIndent(); + sb.append(stsPanicStatement.Panic().getText()).append(' '); + stsPanicStatement.singleExpression().accept(this); + sb.append(";\n"); + + return null; + } + // trapStatement: Trap block catchOrRecoverClause+; @Override public Void visitTrapStatement(TrapStatementContext stsTrapStatement) { diff --git a/migrator/test/java/generic_interface_2.java.sts b/migrator/test/java/generic_interface_2.java.sts index 9bd613d2f5af512579e0cf9c316193b6050bdba7..7c24c7520f5616838167a522e29620d9e7d5ed82 100644 --- a/migrator/test/java/generic_interface_2.java.sts +++ b/migrator/test/java/generic_interface_2.java.sts @@ -15,11 +15,11 @@ package com.ohos.migrator.test.java; interface G1 { - m(): Object ; + m(): Object throws ; } interface G2 { - m(): String ; + m(): String throws ; } interface G extends G1, G2 { diff --git a/migrator/test/java/method_invocation.java.sts b/migrator/test/java/method_invocation.java.sts index 2b2b6899f58d7e423e30226f323e547b96a81858..2dabc2f98c1adf2bfb699c9287dfd7ddb00206aa 100644 --- a/migrator/test/java/method_invocation.java.sts +++ b/migrator/test/java/method_invocation.java.sts @@ -12,7 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.ohos.migrator.tests.java; open class SuperClass { @@ -23,8 +22,7 @@ open class SuperClass { open class SubClass1 extends SuperClass { override foo(): void { - __untranslated_statement(/* throw new UnsupportedOperationException(); - */); + panic new UnsupportedOperationException(); } tweak : Runnable = new Runnable() { public override run(): void { @@ -41,8 +39,7 @@ interface SuperInterface { open class SubClass2 implements SuperInterface { public override foo(): void { - __untranslated_statement(/* throw new UnsupportedOperationException(); - */); + panic new UnsupportedOperationException(); } open tweak(): void { SuperInterface.super.foo(); @@ -51,8 +48,7 @@ open class SubClass2 implements SuperInterface { open class SubClass3 implements SuperInterface { public override foo(): void { - __untranslated_statement(/* throw new UnsupportedOperationException(); - */); + panic new UnsupportedOperationException(); } tweak : Runnable = new Runnable() { public override run(): void { @@ -115,4 +111,4 @@ open class Test3 { let cp : ColoredPoint2 = new ColoredPoint2(); } } - \ No newline at end of file + diff --git a/migrator/test/java/method_references.java.sts b/migrator/test/java/method_references.java.sts index 6659df0137710db49e91922bbdfe790444804e23..8bba70d107f7517b085c3f7dfc23689ef593610e 100644 --- a/migrator/test/java/method_references.java.sts +++ b/migrator/test/java/method_references.java.sts @@ -210,21 +210,21 @@ open class MethodReferencesExamples { } interface TryFunction0 { - apply(): T ; + apply(): T throws ; } interface TryFunction1 { - apply(t : T): R ; + apply(t : T): R throws ; } open class MyException extends Exception { } static open class Exceptions { - public constructor() { + public constructor() throws { } - public open getName(): String { + public open getName(): String throws { return "George"; } } @@ -241,4 +241,4 @@ open class MethodReferencesExamples { } } - \ No newline at end of file + diff --git a/migrator/test/java/throw_statement.java b/migrator/test/java/throw_statement.java new file mode 100644 index 0000000000000000000000000000000000000000..1a8abaa1b930d6cb4ad6c68c0d5fd48418f87fcf --- /dev/null +++ b/migrator/test/java/throw_statement.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2022-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.ohos.migrator.test.java; + +public class throw_statement { + private final int i = 0x7fff; + + public class Panic extends RuntimeException {} + + public int divide_test(int j) throws Exception { + if( j == 0 ) throw new Exception(); + return i / j ; + } + + public int divide_test(long l) throws Panic { + if( l > i ) throw new Panic(); + return (int) (i / l) ; + } + +} diff --git a/migrator/test/java/throw_statement.java.sts b/migrator/test/java/throw_statement.java.sts new file mode 100644 index 0000000000000000000000000000000000000000..12020ddb54a2962892b0a3cccc8f3c5660027170 --- /dev/null +++ b/migrator/test/java/throw_statement.java.sts @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ohos.migrator.test.java; + +export open class throw_statement { + private const i : int = 0x7fff; + public open class Panic extends RuntimeException { + } + + public open divide_test(j : int): int throws { + if (j == 0) throw new Exception(); + return i / j; + } + public open divide_test(l : long): int { + if (l > i) panic new Panic(); + return (i / l) as int; + } +} + diff --git a/migrator/test/java/throws_test.java b/migrator/test/java/throws_test.java new file mode 100644 index 0000000000000000000000000000000000000000..2529cc4d8f022ff3ac98821ac7ed0be4e8a31b81 --- /dev/null +++ b/migrator/test/java/throws_test.java @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2022-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.ohos.migrator.tests.java; + +class MyException extends Exception { + MyException() { } + MyException(String s) { super(s); } +} + +class AnotherException extends Exception { +} + +class SuperClass { + private String s; + public SuperClass(String s) throws MyException { + if(s == null) throw new MyException(); + this.s = s; + } + void foo() { System.out.println(s); } +} + +class SubClass1 extends SuperClass { + + public SubClass1(String s) throws AnotherException, MyException { + super(s); + if(s == null ) throw new AnotherException(); + } + + void foo() throws UnsupportedOperationException { + throw new UnsupportedOperationException(); + } + + public void run() throws UnsupportedOperationException { + foo(); + } + + public void toto() throws MyException { throw new MyException(); } +} + + +class SubClass2 extends SubClass1 { + + public SubClass2(String s) throws AnotherException, MyException, UnsupportedOperationException { + super(s); + if( s == "!" ) throw new UnsupportedOperationException(); + } + + public void foo() throws UnsupportedOperationException { super.foo(); } + public void bar() throws UnsupportedOperationException, AnotherException { super.foo(); throw new AnotherException(); } + public void toto() throws MyException { super.toto(); } +} + + +class Test { + + // throws + public static void test1(String s) throws MyException, AnotherException { + SubClass1 sc1 = new SubClass1(s); + sc1.foo(); + } + + // throws + public static void test2(String s) throws AnotherException { + try { + SubClass1 sc1 = new SubClass1(s); + } + catch( MyException e ) {} + } + + // no throws - all excepyions are catched + public static void test3(String s) { + try { + SubClass1 sc1 = new SubClass1(s); + } + catch( MyException | AnotherException e) {} + } + + // no throws - only panic + public static void test4(String s) { + try { + SubClass2 sc2 = new SubClass2(s); + } + catch( MyException | AnotherException e) {} + } + + // no throws - only panic + public static void test5(String s) { + try { + SubClass2 sc2 = new SubClass2(s); + sc2.foo(); + } + catch( MyException | AnotherException e) {} + } + + // throws + public static void test6(String s) throws AnotherException { + try { + SubClass2 sc2 = new SubClass2(s); + sc2.bar(); + } + catch( MyException e) {} + + } + + + // test for constructor with static initializer + static class E1 extends Exception {} + static class E2 extends Exception {} + static class E3 extends Exception {} + + static abstract class Ta { + public abstract void m() throws E1, E2; + } + + interface Tb { + void m() throws E2, E3; + } + + + // intersect throws clauses + static abstract class Tc extends Ta implements Tb { + { + try { + m(); + } + catch ( E2 e2 ) { + } + } + } + + + // STS constructor must have throws clause + static abstract class Td extends Ta { + { + try { + m(); + } + catch ( E2 e2 ) { + } + } + + public Td() throws E1 { + } + + } + + + // snippet untranslateble by Java, uncomment to check there is no NPE! + /*** + interface FunctionalInterface { void foo(); } + abstract class AbstractException extends Error implements FunctionalInterface {} + + final AbstractException notInitialized = (AbstractException)( (FunctionalInterface)( () -> { throw notInitialized; } ) ); + ***/ +} + diff --git a/migrator/test/java/throws_test.java.sts b/migrator/test/java/throws_test.java.sts new file mode 100644 index 0000000000000000000000000000000000000000..5bce61a9beec0adde104f0fd26682bc26007273c --- /dev/null +++ b/migrator/test/java/throws_test.java.sts @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2022-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ohos.migrator.tests.java; + +open class MyException extends Exception { + constructor() { + } + + constructor(s : String) { + super(s); + } + +} + +open class AnotherException extends Exception { +} + +open class SuperClass { + private s : String ; + public constructor(s : String) throws { + if (s == null) throw new MyException(); + this.s = s; + } + + open foo(): void { + System.out.println(s); + } +} + +open class SubClass1 extends SuperClass { + public constructor(s : String) throws { + try super(s); + if (s == null) throw new AnotherException(); + } + + override foo(): void { + panic new UnsupportedOperationException(); + } + public open run(): void { + try foo(); + } + public open toto(): void throws { + throw new MyException(); + } +} + +open class SubClass2 extends SubClass1 { + public constructor(s : String) throws { + try super(s); + if (s == "!") panic new UnsupportedOperationException(); + } + + public override foo(): void { + super.foo(); + } + public open bar(): void throws { + super.foo(); + throw new AnotherException(); + } + public override toto(): void throws { + super.toto(); + } +} + +open class Test { + public static test1(s : String): void throws { + let sc1 : SubClass1 = try new SubClass1(s); + try sc1.foo(); + } + public static test2(s : String): void throws { + trap { + let sc1 : SubClass1 = try new SubClass1(s); + } + catch (e : MyException) { + } + + } + public static test3(s : String): void { + trap { + let sc1 : SubClass1 = try new SubClass1(s); + } + catch (e : MyException) { + } + catch (e : AnotherException) { + } + + } + public static test4(s : String): void { + trap { + let sc2 : SubClass2 = try new SubClass2(s); + } + catch (e : MyException) { + } + catch (e : AnotherException) { + } + + } + public static test5(s : String): void { + trap { + let sc2 : SubClass2 = try new SubClass2(s); + try sc2.foo(); + } + catch (e : MyException) { + } + catch (e : AnotherException) { + } + + } + public static test6(s : String): void throws { + trap { + let sc2 : SubClass2 = try new SubClass2(s); + try sc2.bar(); + } + catch (e : MyException) { + } + + } + static open class E1 extends Exception { + } + + static open class E2 extends Exception { + } + + static open class E3 extends Exception { + } + + abstract static class Ta { + public abstract m(): void throws ; + } + + interface Tb { + m(): void throws ; + } + + abstract static class Tc extends Ta implements Tb { + public constructor() { + trap { + try m(); + } + catch (e2 : E2) { + } + + } + + } + + abstract static class Td extends Ta { + public constructor() throws { + trap { + try m(); + } + catch (e2 : E2) { + } + + } + + } + +} + diff --git a/migrator/test/java/try_catch_finally.java.sts b/migrator/test/java/try_catch_finally.java.sts index c48f24f9766957135b3c9878bbd45d5f1c9699f5..61ee0a7a4c9ebfe8937d043bf9b94fa645a979f0 100644 --- a/migrator/test/java/try_catch_finally.java.sts +++ b/migrator/test/java/try_catch_finally.java.sts @@ -12,38 +12,36 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.ohos.migrator.test.java; open class BlewIt extends Exception { - constructor() { + constructor() { } - constructor(s : String) { - super(s); + + constructor(s : String) { + super(s); } + } export open class try_catch_finally { - public constructor() { + public constructor() throws { } - public constructor(i : int) { - try this(); + public constructor(i : int) throws { + try this(); } - static blowUp(): void { + static blowUp(): void throws { } - - private static foo(): void { + private static foo(): void throws { { defer { System.out.println("In finally"); } - try blowUp(); } } - public static main(args : String[]): void { trap { defer { @@ -67,5 +65,7 @@ export open class try_catch_finally { catch (e : Exception) { System.out.println("Caught Exception"); } + } } + diff --git a/migrator/test/java/try_with_resources.java.sts b/migrator/test/java/try_with_resources.java.sts index 6d0f35cd6b6ddb69e4496f3bab7ca6e5b848d620..157fc7a516af7611feaf9aacdf674d3045fcf4e2 100644 --- a/migrator/test/java/try_with_resources.java.sts +++ b/migrator/test/java/try_with_resources.java.sts @@ -26,7 +26,7 @@ import java.sql.Statement; import java.sql.SQLException; import java.util.Scanner; open class TryWithResources { - open readFile(): void { + open readFile(): void throws { let line : String = ""; let path : String = ""; { @@ -93,7 +93,7 @@ open class TryWithResources { } } - open viewTable(con : Connection): void { + open viewTable(con : Connection): void throws { let query : String = "select COF_NAME, SUP_ID, PRICE, SALES, TOTAL from COFFEES"; trap { const stmt : Statement = try con.createStatement(); @@ -139,7 +139,7 @@ open class TryWithResources { } } - open readFile2(): void { + open readFile2(): void throws { let line : String = ""; let path : String = ""; { @@ -438,14 +438,13 @@ open class TryWithResources { open class Y implements AutoCloseable { public val : int = 10; - public override close(): void { + public override close(): void throws { if (val < 0) { - __untranslated_statement(/* throw new IOException("Invalid value: " + val); - */); + throw new IOException("Invalid value: " + val); } System.out.println("Closed"); } } } - \ No newline at end of file +