diff --git a/migrator/src/com/ohos/migrator/java/JavaTransformer.java b/migrator/src/com/ohos/migrator/java/JavaTransformer.java index 1ab71e5f40ff8c11571f660a086f20d4a7615788..35347934524f4b2f766c04726d2ab64a01f61575 100644 --- a/migrator/src/com/ohos/migrator/java/JavaTransformer.java +++ b/migrator/src/com/ohos/migrator/java/JavaTransformer.java @@ -18,7 +18,6 @@ package com.ohos.migrator.java; import com.ohos.migrator.Main; import com.ohos.migrator.ResultCode; import com.ohos.migrator.Transformer; -import com.ohos.migrator.staticTS.NodeBuilder; import com.ohos.migrator.staticTS.parser.StaticTSParser; import com.ohos.migrator.staticTS.parser.StaticTSParser.*; @@ -26,7 +25,6 @@ import org.antlr.v4.runtime.ParserRuleContext; import org.antlr.v4.runtime.tree.ParseTree; import org.antlr.v4.runtime.tree.TerminalNode; import org.eclipse.jdt.core.dom.*; -import org.jetbrains.annotations.NotNull; import java.io.File; import java.util.*; @@ -526,7 +524,7 @@ public class JavaTransformer extends ASTVisitor implements Transformer { return false; } - private void translateNonAccessModifiers(@NotNull MethodDeclaration javaMethodDeclaration, boolean isInClassContext) { + private void translateNonAccessModifiers(MethodDeclaration javaMethodDeclaration, boolean isInClassContext) { int javaModifiers = javaMethodDeclaration.getModifiers(); // A method may not have both Abstract and Open modifiers. diff --git a/migrator/src/com/ohos/migrator/java/NodeBuilder.java b/migrator/src/com/ohos/migrator/java/NodeBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..f402439ecb709472e6589c89f4ce566856f80988 --- /dev/null +++ b/migrator/src/com/ohos/migrator/java/NodeBuilder.java @@ -0,0 +1,352 @@ +/* + * 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.java; + +import com.ohos.migrator.staticTS.NodeBuilderBase; +import com.ohos.migrator.staticTS.parser.StaticTSParser; +import com.ohos.migrator.staticTS.parser.StaticTSParser.*; +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.TerminalNode; +import org.eclipse.jdt.core.dom.*; + +public class NodeBuilder extends NodeBuilderBase { + private static final String UNTRANSLATED_TRY_RESOURCE = "__untranslated_try_resource"; + + public static TerminalNode terminalIdentifier(SimpleName name) { + return terminalIdentifier(name.getIdentifier()); + } + + public static QualifiedNameContext qualifiedName(Name javaName) { + return qualifiedName(javaName.getFullyQualifiedName()); + } + + private static int stsTypeNameCode(PrimitiveType.Code javaPrimitiveTypeCode) { + int stsTypeNameCode = -1; + + if (javaPrimitiveTypeCode == PrimitiveType.BOOLEAN) + stsTypeNameCode = StaticTSParser.Boolean; + else if (javaPrimitiveTypeCode == PrimitiveType.BYTE) + stsTypeNameCode = StaticTSParser.Byte; + else if (javaPrimitiveTypeCode == PrimitiveType.CHAR) + stsTypeNameCode = StaticTSParser.Char; + else if (javaPrimitiveTypeCode == PrimitiveType.INT) + stsTypeNameCode = StaticTSParser.Int; + else if (javaPrimitiveTypeCode == PrimitiveType.DOUBLE) + stsTypeNameCode = StaticTSParser.Double; + else if (javaPrimitiveTypeCode == PrimitiveType.FLOAT) + stsTypeNameCode = StaticTSParser.Float; + else if (javaPrimitiveTypeCode == PrimitiveType.LONG) + stsTypeNameCode = StaticTSParser.Long; + else if (javaPrimitiveTypeCode == PrimitiveType.SHORT) + stsTypeNameCode = StaticTSParser.Short; + else if (javaPrimitiveTypeCode == PrimitiveType.VOID) + stsTypeNameCode = StaticTSParser.Void; + else + assert false : "Unknown type"; + + return stsTypeNameCode; + } + + public static PredefinedTypeContext predefinedType(PrimitiveType.Code javaPrimitiveTypeCode) { + // predefinedType -> TerminalNode + PredefinedTypeContext stsPredefinedType = new PredefinedTypeContext(null, 0); + stsPredefinedType.addChild(terminalNode(stsTypeNameCode(javaPrimitiveTypeCode))); + return stsPredefinedType; + } + + public static AccessibilityModifierContext accessibilityModifier(int javaModifiers) { + int stsModifierCode = -1; + if ((javaModifiers & Modifier.PRIVATE) != 0) + stsModifierCode = StaticTSParser.Private; + else if ((javaModifiers & Modifier.PROTECTED) != 0) + stsModifierCode = StaticTSParser.Protected; + else if ((javaModifiers & Modifier.PUBLIC) != 0) + stsModifierCode = StaticTSParser.Public; + + if (stsModifierCode == -1) return null; + + AccessibilityModifierContext stsAccessMod = new AccessibilityModifierContext(null, 0); + stsAccessMod.addChild(terminalNode(stsModifierCode)); + return stsAccessMod; + } + + // Java: + // QualifiedType: Type . { Annotation } SimpleName + // SimpleType: { Annotation } TypeName + // STS: + // typeReference: typeReferencePart ('.' typeReferencePart)* + // typeReferencePart: qualifiedName typeArguments? + public static TypeReferenceContext typeReference(PrimitiveType javaPrimitiveType) { + PrimitiveType.Code javaPrimitiveTypeCode = javaPrimitiveType.getPrimitiveTypeCode(); + TypeReferenceContext stsTypeReference = new TypeReferenceContext(null, 0); + stsTypeReference.addChild(qualifiedName(stsName(stsTypeNameCode(javaPrimitiveTypeCode)))).setParent(stsTypeReference); + return stsTypeReference; + } + public static TypeReferenceContext typeReference(String stsQualifierText, Name javaName) { + String typeFQN = stsQualifierText + '.' + javaName.getFullyQualifiedName(); + + TypeReferenceContext stsTypeReference = new TypeReferenceContext(null, 0); + stsTypeReference.addChild(qualifiedName(typeFQN)).setParent(stsTypeReference); + return stsTypeReference; + } + + public static AssignmentOperatorContext assignmentOperator(Assignment.Operator javaAssignOp) { + int stsOperatorCode = -1; + + if (javaAssignOp == Assignment.Operator.PLUS_ASSIGN) + stsOperatorCode = StaticTSParser.PlusAssign; + else if (javaAssignOp == Assignment.Operator.MINUS_ASSIGN) + stsOperatorCode = StaticTSParser.MinusAssign; + else if (javaAssignOp == Assignment.Operator.TIMES_ASSIGN) + stsOperatorCode = StaticTSParser.MultiplyAssign; + else if (javaAssignOp == Assignment.Operator.DIVIDE_ASSIGN) + stsOperatorCode = StaticTSParser.DivideAssign; + else if (javaAssignOp == Assignment.Operator.BIT_AND_ASSIGN) + stsOperatorCode = StaticTSParser.BitAndAssign; + else if (javaAssignOp == Assignment.Operator.BIT_OR_ASSIGN) + stsOperatorCode = StaticTSParser.BitOrAssign; + else if (javaAssignOp == Assignment.Operator.BIT_XOR_ASSIGN) + stsOperatorCode = StaticTSParser.BitXorAssign; + else if (javaAssignOp == Assignment.Operator.REMAINDER_ASSIGN) + stsOperatorCode = StaticTSParser.ModulusAssign; + else if (javaAssignOp == Assignment.Operator.LEFT_SHIFT_ASSIGN) + stsOperatorCode = StaticTSParser.LeftShiftArithmeticAssign; + else if (javaAssignOp == Assignment.Operator.RIGHT_SHIFT_SIGNED_ASSIGN) + stsOperatorCode = StaticTSParser.RightShiftArithmeticAssign; + else if (javaAssignOp == Assignment.Operator.RIGHT_SHIFT_UNSIGNED_ASSIGN) + stsOperatorCode = StaticTSParser.RightShiftLogicalAssign; + + if (stsOperatorCode == -1) return null; + + AssignmentOperatorContext stsAssignOp = new AssignmentOperatorContext(null, 0); + stsAssignOp.addChild(terminalNode(stsOperatorCode)); + return stsAssignOp; + } + + public static void addExtraDimensions(ParserRuleContext stsCurrent, int extraDims) { + assert(stsCurrent instanceof TypeAnnotationContext && extraDims > 0); + + PrimaryTypeContext stsPrimaryType = ((TypeAnnotationContext)stsCurrent).primaryType(); + ArrayTypeContext stsArrayType = stsPrimaryType.arrayType(); + if (stsArrayType == null) { + // Should be either a type reference or predefined type. + ParserRuleContext stsType = stsPrimaryType.typeReference(); + if (stsType == null) stsType = stsPrimaryType.predefinedType(); + assert(stsType != null); + + // Drop the type which we just extracted above. + stsPrimaryType.removeLastChild(); + + // Construct new ArrayTypeContext and link it up to PrimaryTypeContext. + stsArrayType = new ArrayTypeContext(stsPrimaryType, 0); + stsArrayType.addChild(stsType).setParent(stsArrayType); + stsPrimaryType.addChild(stsArrayType); + } + + for (int i = 0; i < extraDims; ++i) { + stsArrayType.addChild(terminalNode(StaticTSParser.OpenBracket)); + stsArrayType.addChild(terminalNode(StaticTSParser.CloseBracket)); + } + } + + public static ParameterContext parameter(String stsParamName, PrimitiveType.Code javaPrimitiveTypeCode) { + ParameterContext stsParam = new ParameterContext(null, 0); + stsParam.addChild(terminalIdentifier(stsParamName)); + stsParam.addChild(typeAnnotation(predefinedType(javaPrimitiveTypeCode))).setParent(stsParam); + return stsParam; + } + + public static TypeAnnotationContext unknownTypeAnnotation(Type javaType) { + TypeAnnotationContext stsTypeAnnotation = unknownTypeAnnotation(); + + if (javaType != null) { + stsTypeAnnotation.addChild(multiLineComment("/* " + javaType.toString() + " */")); + } + + return stsTypeAnnotation; + } + + public static TypeAnnotationContext unknownTypeAnnotation(ITypeBinding javaTypeBinding) { + TypeAnnotationContext stsTypeAnnotation = unknownTypeAnnotation(); + + if (javaTypeBinding != null) { + stsTypeAnnotation.addChild(multiLineComment("/* " + javaTypeBinding.getName() + " */")); + } + + return stsTypeAnnotation; + } + + public static SingleExpressionContext untranslatedExpression(ASTNode node) { + return dummyCall(UNTRANSLATED_EXPRESSION, node.toString()); + } + + public static ParserRuleContext untranslatedStatement(ASTNode node, ParserRuleContext stsContext) { + StatementContext stsStatement = new StatementContext(null, 0); + ExpressionStatementContext stsExprStatement = new ExpressionStatementContext(stsStatement, 0); + stsStatement.addChild(stsExprStatement); + stsExprStatement.addChild(dummyCall(UNTRANSLATED_STATEMENT, node.toString())).setParent(stsExprStatement); + + if (needStatementOrLocalDeclaration(stsContext)) { + StatementOrLocalDeclarationContext stsStmtOrLocalDecl = new StatementOrLocalDeclarationContext(null, 0); + stsStmtOrLocalDecl.addChild(stsStatement).setParent(stsStmtOrLocalDecl); + return stsStmtOrLocalDecl; + } + + return stsStatement; + } + + public static ParserRuleContext untranslatedTryResource(ASTNode node, ParserRuleContext stsContext) { + StatementContext stsStatement = new StatementContext(null, 0); + ExpressionStatementContext stsExprStatement = new ExpressionStatementContext(stsStatement, 0); + stsStatement.addChild(stsExprStatement); + stsExprStatement.addChild(dummyCall(UNTRANSLATED_TRY_RESOURCE, node.toString())).setParent(stsExprStatement); + + if (needStatementOrLocalDeclaration(stsContext)) { + StatementOrLocalDeclarationContext stsStmtOrLocalDecl = new StatementOrLocalDeclarationContext(null, 0); + stsStmtOrLocalDecl.addChild(stsStatement).setParent(stsStmtOrLocalDecl); + return stsStmtOrLocalDecl; + } + + return stsStatement; + } + + public static ShiftOperatorContext shiftOperator(InfixExpression.Operator javaOp) { + ShiftOperatorContext stsShiftOp = new ShiftOperatorContext(null, 0); + + if (javaOp == InfixExpression.Operator.LEFT_SHIFT) { + stsShiftOp.addChild(NodeBuilder.terminalNode(StaticTSParser.LessThan)); + stsShiftOp.addChild(NodeBuilder.terminalNode(StaticTSParser.LessThan)); + } + else if (javaOp == InfixExpression.Operator.RIGHT_SHIFT_SIGNED) { + stsShiftOp.addChild(NodeBuilder.terminalNode(StaticTSParser.MoreThan)); + stsShiftOp.addChild(NodeBuilder.terminalNode(StaticTSParser.MoreThan)); + } + else if (javaOp == InfixExpression.Operator.RIGHT_SHIFT_UNSIGNED) { + stsShiftOp.addChild(NodeBuilder.terminalNode(StaticTSParser.MoreThan)); + stsShiftOp.addChild(NodeBuilder.terminalNode(StaticTSParser.MoreThan)); + stsShiftOp.addChild(NodeBuilder.terminalNode(StaticTSParser.MoreThan)); + } + + return stsShiftOp; + } + + public static ParserRuleContext translateTypeBinding(ITypeBinding javaType) { + if (javaType.isPrimitive()) { + return predefinedType(javaType.getName()); + } + + if (javaType.isArray()) { + ITypeBinding javaArrayElemType = javaType.getElementType(); + ParserRuleContext stsArrayElemType = translateTypeBinding(javaArrayElemType); + return arrayType(stsArrayElemType, javaType.getDimensions()); + } + + if (javaType.isParameterizedType()) { + ITypeBinding javaErasedType = javaType.getErasure(); + ParserRuleContext stsType = translateTypeBinding(javaErasedType); + if (stsType.getRuleIndex() != StaticTSParser.RULE_typeReference) { + stsType = unknownTypeReference(javaErasedType.getQualifiedName()); + } + + // Translate type arguments and inject them into last child of TypeReferenceContext node + TypeReferencePartContext stsLastTypePart = (TypeReferencePartContext)stsType.getChild(stsType.getChildCount()-1); + TypeArgumentsContext stsTypeArgs = translateTypeArguments(javaType.getTypeArguments()); + stsLastTypePart.addChild(stsTypeArgs).setParent(stsLastTypePart); + return stsType; + } + + if (javaType.isWildcardType()) { + WildcardTypeContext stsWildCardType = new WildcardTypeContext(null, 0); + ITypeBinding javaBoundType = javaType.getBound(); + if (javaBoundType != null) { + String stsInOrOutKeyword = javaType.isUpperbound() ? StaticTSParser.OUT : StaticTSParser.IN; + stsWildCardType.addChild(terminalIdentifier(stsInOrOutKeyword)); + ParserRuleContext stsBoundType = translateTypeBinding(javaBoundType); + stsWildCardType.addChild(stsBoundType).setParent(stsWildCardType); + } + else { + stsWildCardType.addChild(terminalIdentifier(StaticTSParser.OUT)); + } + return stsWildCardType; + } + + if (javaType.isIntersectionType()) { + IntersectionTypeContext stsIntersectionType = new IntersectionTypeContext(null, 0); + for (ITypeBinding javaIntersectedType : javaType.getTypeBounds()) { + ParserRuleContext stsIntersectedType = translateTypeBinding(javaIntersectedType); + stsIntersectionType.addChild(stsIntersectedType).setParent(stsIntersectionType); + } + return stsIntersectionType; + } + + // All other types should be named - just emit TypeReferenceContext + TypeReferenceContext stsTypeRef = typeReference(javaType.getQualifiedName()); + addEmptyTypeArgumentsToRawType(stsTypeRef, javaType); + return stsTypeRef; + } + + public static void addEmptyTypeArgumentsToRawType(TypeReferenceContext stsTypeRef, ITypeBinding javaTypeBinding) { + if (javaTypeBinding != null && javaTypeBinding.isRawType()) { + TypeReferencePartContext stsLastTypePart = (TypeReferencePartContext) stsTypeRef.getChild(stsTypeRef.getChildCount() - 1); + stsLastTypePart.addChild(new TypeArgumentsContext(stsLastTypePart, 0)).setParent(stsLastTypePart); + } + } + public static void addEmptyTypeArgumentsToRawType(TypeReferenceContext stsTypeRef, Type javaType) { + ITypeBinding javaTypeBinding = getTypeBinding(javaType); + addEmptyTypeArgumentsToRawType(stsTypeRef, javaTypeBinding); + } + public static TypeArgumentsContext translateTypeArguments(ITypeBinding[] javaTypeArgs) { + TypeArgumentsContext stsTypeArgs = new TypeArgumentsContext(null, 0); + + if (javaTypeArgs != null) { + TypeArgumentListContext stsTypeArgList = new TypeArgumentListContext(stsTypeArgs, 0); + stsTypeArgs.addChild(stsTypeArgList).setParent(stsTypeArgs); + + for (ITypeBinding javaTypeArg : javaTypeArgs) { + ParserRuleContext stsTypeArg = translateTypeBinding(javaTypeArg); + if (!isTypeArgument(stsTypeArg)) stsTypeArg = unknownTypeReference(null); + + TypeArgumentContext stsTypeArgNode = new TypeArgumentContext(stsTypeArgList, 0); + stsTypeArgNode.addChild(stsTypeArg).setParent(stsTypeArgNode); + stsTypeArgList.addChild(stsTypeArgNode).setParent(stsTypeArgList); + } + } + + return stsTypeArgs; + } + + public static boolean isTypeArgument(Type javaType) { + return isTypeReference(javaType) || javaType.isArrayType() || javaType.isWildcardType(); + } + + public static boolean isTypeReference(Type javaType) { + return javaType.isSimpleType() || javaType.isQualifiedType() || + javaType.isNameQualifiedType() || javaType.isParameterizedType(); + } + + public static ITypeBinding getTypeBinding(Type javaType) { + // Type.resolveBinding() can throw exceptions, so let's catch them + ITypeBinding javaTypeBinding; + try { + javaTypeBinding = javaType.resolveBinding(); + } + catch (Exception e) { + javaTypeBinding = null; + } + + return javaTypeBinding; + } +} diff --git a/migrator/src/com/ohos/migrator/kotlin/KotlinTransformer.java b/migrator/src/com/ohos/migrator/kotlin/KotlinTransformer.java index 1c05654be427c8de25eec84573fee9449a63fc85..05400fc2bc3b4a514503ff9cc9b2d2c3c4d17711 100644 --- a/migrator/src/com/ohos/migrator/kotlin/KotlinTransformer.java +++ b/migrator/src/com/ohos/migrator/kotlin/KotlinTransformer.java @@ -15,27 +15,34 @@ package com.ohos.migrator.kotlin; -import com.intellij.openapi.util.TextRange; import com.ohos.migrator.Main; import com.ohos.migrator.ResultCode; import com.ohos.migrator.Transformer; -import com.ohos.migrator.staticTS.NodeBuilder; import com.ohos.migrator.staticTS.parser.StaticTSParser; import com.ohos.migrator.staticTS.parser.StaticTSParser.*; import org.antlr.v4.runtime.ParserRuleContext; import org.antlr.v4.runtime.tree.TerminalNode; +import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import org.jetbrains.kotlin.analyzer.AnalysisResult; +import org.jetbrains.kotlin.descriptors.ClassifierDescriptor; +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; +import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor; import org.jetbrains.kotlin.diagnostics.PsiDiagnosticUtils; import org.jetbrains.kotlin.lexer.KtTokens; +import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.psi.psiUtil.KtPsiUtilKt; import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt; import org.jetbrains.kotlin.resolve.BindingContext; +import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt; +import org.jetbrains.kotlin.types.KotlinType; +import org.jetbrains.kotlin.types.error.ErrorUtils; import java.io.File; +import java.util.List; /** * Performs transformation of the Kotlin AST into StaticTS AST. @@ -82,6 +89,36 @@ public class KotlinTransformer extends KtVisitor implem Main.addError(ResultCode.TranspileError, message + " at " + loc); } + public static boolean isErrorDescriptor(DeclarationDescriptor ktDescriptor) { + return ktDescriptor == null || ErrorUtils.isError(ktDescriptor); + } + + public static boolean isErrorType(KotlinType ktType) { + return ktType == null || ErrorUtils.INSTANCE.containsErrorType(ktType); + } + + private TypeReferenceContext translateType(KotlinType ktType, KtElement ktElement) { + if (isErrorType(ktType)) { + reportError("Failed to resolve type", ktElement); + return NodeBuilder.unknownTypeReference(null); + } + + ClassifierDescriptor ktClassifierDescriptor = ktType.getConstructor().getDeclarationDescriptor(); + if (isErrorDescriptor(ktClassifierDescriptor)) { + reportError("Failed to resolve type", ktElement); + return NodeBuilder.unknownTypeReference(null); + } + + String typeName; + FqName ktFqName = DescriptorUtilsKt.getFqNameSafe(ktClassifierDescriptor); + if (ktFqName != null) { + typeName = ktFqName.asString(); + } else { + typeName = ktClassifierDescriptor.getName().asString(); + } + + return NodeBuilder.typeReference(typeName); + } /** * Visit element's children and add result of translation of each child to the specified STS context. @@ -153,18 +190,20 @@ public class KotlinTransformer extends KtVisitor implem stsResult.addChild(NodeBuilder.terminalNode(StaticTSParser.Class)); // } - if (KtPsiUtilKt.isAbstract(ktClass)) + if (ktClass.hasModifier(KtTokens.ABSTRACT_KEYWORD)) stsResult.addChild(NodeBuilder.terminalNode(StaticTSParser.Abstract)); else if (ktClass.hasModifier(KtTokens.OPEN_KEYWORD)) stsResult.addChild(NodeBuilder.terminalNode(StaticTSParser.Open)); - stsResult.addChild(NodeBuilder.terminalIdentifier(ktClass.getName())); ClassBodyContext stsClassBody = new ClassBodyContext(stsResult, 0); stsResult.addChild(stsClassBody).setParent(stsResult); - visitChildren(ktClass, stsClassBody); + KtClassBody ktClassBody = ktClass.getBody(); + if (ktClassBody != null) { + visitChildren(ktClassBody, stsClassBody); + } if (ktClass.isTopLevel()) { TopDeclarationContext stsTopDecl = new TopDeclarationContext(null, 0); @@ -183,4 +222,221 @@ public class KotlinTransformer extends KtVisitor implem return stsResult; } + @Override + public TypeReferenceContext visitTypeReference(KtTypeReference ktTypeReference, Void data) { + TypeReferenceContext stsTypeRef = (TypeReferenceContext) ktTypeReference.getTypeElement().accept(this, data); + + if (stsTypeRef == null) { + reportError("Failed to translate type", ktTypeReference); + stsTypeRef = NodeBuilder.unknownTypeReference(ktTypeReference.getText()); + } + + return stsTypeRef; + } + + @Override + public TypeReferenceContext visitUserType(KtUserType ktUserType, Void data) { + TypeReferenceContext stsTypeRef; + + KtUserType ktQualifier = ktUserType.getQualifier(); + if (ktQualifier != null) { + stsTypeRef = (TypeReferenceContext) ktQualifier.accept(this, data); + } + else { + stsTypeRef = new TypeReferenceContext(null, 0); + } + + TypeReferencePartContext stsTypeRefPart = NodeBuilder.typeReferencePart(ktUserType.getReferencedName()); + stsTypeRef.addChild(stsTypeRefPart).setParent(stsTypeRef); + + // TODO: Translate type arguments + + return stsTypeRef; + } + + @Override + public ParserRuleContext visitNamedFunction(KtNamedFunction ktNamedFunction, Void data) { + if (ktNamedFunction.isTopLevel()) { + return translateTopLevelFunction(ktNamedFunction); + } +// else if (ktNamedFunction.isLocal()) { +// TODO: +// } + else { + return translateClassMethod(ktNamedFunction); + } + } + + private ParserRuleContext translateTopLevelFunction(KtNamedFunction ktNamedFunction) { + TopDeclarationContext stsTopDecl = new TopDeclarationContext(null, 0); + + if (KtPsiUtilKt.isPublic(ktNamedFunction)) { + stsTopDecl.addChild(NodeBuilder.terminalNode(StaticTSParser.Export)); + } + + FunctionDeclarationContext stsFunctionDecl = new FunctionDeclarationContext(stsTopDecl, 0); + stsTopDecl.addChild(stsFunctionDecl).setParent(stsTopDecl); + + stsFunctionDecl.addChild(NodeBuilder.terminalNode(StaticTSParser.Function)); + + translateFunction(ktNamedFunction, stsFunctionDecl); + + return stsTopDecl; + } + + private ParserRuleContext translateClassMethod(KtNamedFunction ktNamedFunction) { + ClassMethodDeclarationContext stsClassMethod = new ClassMethodDeclarationContext(null, 0); + ParserRuleContext stsMethod; + if (ktNamedFunction.getBodyExpression() != null) { + stsMethod = new ClassMethodWithBodyContext(stsClassMethod); + } else { + stsMethod = new AbstractOrNativeClassMethodContext(stsClassMethod); + } + stsClassMethod.addChild(stsMethod).setParent(stsClassMethod); + + if (ktNamedFunction.hasModifier(KtTokens.ABSTRACT_KEYWORD)) + stsMethod.addChild(NodeBuilder.terminalNode(StaticTSParser.Abstract)); + else if (ktNamedFunction.hasModifier(KtTokens.OPEN_KEYWORD)) + stsMethod.addChild(NodeBuilder.terminalNode(StaticTSParser.Open)); + else if (ktNamedFunction.hasModifier(KtTokens.OVERRIDE_KEYWORD)) + stsMethod.addChild(NodeBuilder.terminalNode(StaticTSParser.Override)); + + translateFunction(ktNamedFunction, stsMethod); + + ClassMemberContext stsClassMember = new ClassMemberContext(null, 0); + AccessibilityModifierContext stsAccessMod = NodeBuilder.accessibilityModifier(ktNamedFunction); + if (stsAccessMod != null) stsClassMember.addChild(stsAccessMod).setParent(stsClassMember); + stsClassMember.addChild(stsClassMethod).setParent(stsClassMember); + + return stsClassMember; + } + + private void translateFunction(KtNamedFunction ktNamedFunction, ParserRuleContext stsFunction) { + stsFunction.addChild(NodeBuilder.terminalIdentifier(ktNamedFunction.getName())); + + SignatureContext stsSignature = translateFunctionHeader(ktNamedFunction); + stsFunction.addChild(stsSignature).setParent(stsFunction); + + KtExpression ktBodyExpr = ktNamedFunction.getBodyExpression(); + if (ktBodyExpr != null) { + BlockContext stsBlock = translateFunctionBody(ktBodyExpr); + stsFunction.addChild(stsBlock).setParent(stsFunction); + } + } + + private SignatureContext translateFunctionHeader(KtNamedFunction ktNamedFunction) { + SignatureContext stsSignature = new SignatureContext(null, 0); + + // TODO: Translate type parameters + + ParameterListContext stsParameterList = translateFunctionParameters(ktNamedFunction.getValueParameters()); + if (stsParameterList != null) { + stsSignature.addChild(stsParameterList).setParent(stsSignature); + } + + TypeReferenceContext stsTypeRef; + + KtTypeReference ktReturnType = ktNamedFunction.getTypeReference(); + if (ktReturnType != null) { + stsTypeRef = (TypeReferenceContext) ktNamedFunction.getTypeReference().accept(this, null); + } else { + // The return type might be omitted in source code. In this case, + // it is inferred by compiler. Use the function descriptor to + // retrieve the return type. + SimpleFunctionDescriptor ktDescriptor = bindingContext.get(BindingContext.FUNCTION, ktNamedFunction); + if (isErrorDescriptor(ktDescriptor)) { + reportError("Failed to resolve return type of function", ktNamedFunction); + stsTypeRef = NodeBuilder.unknownTypeReference(null); + } else { + stsTypeRef = translateType(ktDescriptor.getReturnType(), ktNamedFunction); + } + } + + stsSignature.addChild(NodeBuilder.typeAnnotation(stsTypeRef)).setParent(stsSignature); + + return stsSignature; + } + + private ParameterListContext translateFunctionParameters(List ktParameters) { + if (ktParameters == null || ktParameters.isEmpty()) + return null; + + ParameterListContext stsParameterList = new ParameterListContext(null, 0); + + for (KtParameter ktParameter : ktParameters) { + ParserRuleContext stsParam = ktParameter.accept(this, null); + stsParameterList.addChild(stsParam).setParent(stsParameterList); + } + + return stsParameterList; + } + + @Override + public ParserRuleContext visitParameter(KtParameter ktParameter, Void data) { + ParserRuleContext stsParam; + + if (ktParameter.isVarArg()) { + stsParam = new VariadicParameterContext(null, 0); + stsParam.addChild(NodeBuilder.terminalNode(StaticTSParser.Ellipsis)); + } + else { + stsParam = new ParameterContext(null, 0); + } + + stsParam.addChild(NodeBuilder.terminalIdentifier(ktParameter.getName())); + + TypeReferenceContext stsTypeRef = (TypeReferenceContext) ktParameter.getTypeReference().accept(this, null); + stsParam.addChild(NodeBuilder.typeAnnotation(stsTypeRef)).setParent(stsParam); + + return stsParam; + } + + private BlockContext translateFunctionBody(KtExpression ktBodyExpression) { + BlockContext stsBlock; + + if (ktBodyExpression instanceof KtBlockExpression) { + stsBlock = (BlockContext) ktBodyExpression.accept(this, null); + } else { + stsBlock = new BlockContext(null, 0); + + StatementOrLocalDeclarationContext stsStmtOrLocalDecl = new StatementOrLocalDeclarationContext(stsBlock, 0); + stsBlock.addChild(stsStmtOrLocalDecl); + + StatementContext stsStmt = new StatementContext(stsStmtOrLocalDecl, 0); + stsStmtOrLocalDecl.addChild(stsStmt); + + ReturnStatementContext stsReturn = new ReturnStatementContext(stsStmt, 0); + stsReturn.addChild(NodeBuilder.terminalNode(StaticTSParser.Return)); + stsStmt.addChild(stsReturn); + + ParserRuleContext stsRetExpr = ktBodyExpression.accept(this, null); + stsReturn.addChild(stsRetExpr).setParent(stsReturn); + } + + return stsBlock; + } + + + @Override + public BlockContext visitBlockExpression(KtBlockExpression ktBlockExpression, Void data) { + BlockContext stsBlock = new BlockContext(null, 0); + + for (KtExpression ktExpr : ktBlockExpression.getStatements()) { + // TODO: translate statement expressions. + } + + return stsBlock; + } + + @Override + public ParserRuleContext visitExpression(KtExpression ktBlockExpression, Void data) { + // For the moment, return untranslated expression/statement in order + // to avoid possible NullPointerExceptions while developing the translator. + // TODO: Remove this code, once all expressions are supported. + if (KtPsiUtil.isStatement(ktBlockExpression)) + return NodeBuilder.untranslatedStatement(ktBlockExpression); + else + return NodeBuilder.untranslatedExpression(ktBlockExpression); + } + } \ No newline at end of file diff --git a/migrator/src/com/ohos/migrator/kotlin/NodeBuilder.java b/migrator/src/com/ohos/migrator/kotlin/NodeBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..0848a300cd27f282d7e32c7323182770997c35c0 --- /dev/null +++ b/migrator/src/com/ohos/migrator/kotlin/NodeBuilder.java @@ -0,0 +1,56 @@ +/* + * 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.kotlin; + +import com.ohos.migrator.staticTS.NodeBuilderBase; +import com.ohos.migrator.staticTS.parser.StaticTSParser; +import com.ohos.migrator.staticTS.parser.StaticTSParser.*; +import org.jetbrains.kotlin.psi.KtElement; +import org.jetbrains.kotlin.psi.KtModifierListOwner; +import org.jetbrains.kotlin.psi.psiUtil.KtPsiUtilKt; + +public class NodeBuilder extends NodeBuilderBase { + + public static AccessibilityModifierContext accessibilityModifier(KtModifierListOwner ktModifierListOwner) { + int stsModifierCode = -1; + if (KtPsiUtilKt.isPublic(ktModifierListOwner)) + stsModifierCode = StaticTSParser.Public; + if (KtPsiUtilKt.isProtected(ktModifierListOwner)) + stsModifierCode = StaticTSParser.Protected; + if (KtPsiUtilKt.isPrivate(ktModifierListOwner)) + stsModifierCode = StaticTSParser.Private; + + if (stsModifierCode == -1) return null; + + AccessibilityModifierContext stsAccessMod = new AccessibilityModifierContext(null, 0); + stsAccessMod.addChild(terminalNode(stsModifierCode)); + return stsAccessMod; + } + + + public static SingleExpressionContext untranslatedExpression(KtElement ktElement) { + return dummyCall(UNTRANSLATED_EXPRESSION, ktElement.getText()); + } + + public static StatementContext untranslatedStatement(KtElement ktElement) { + StatementContext stsStatement = new StatementContext(null, 0); + ExpressionStatementContext stsExprStatement = new ExpressionStatementContext(stsStatement, 0); + stsStatement.addChild(stsExprStatement); + stsExprStatement.addChild(dummyCall(UNTRANSLATED_STATEMENT, ktElement.getText())).setParent(stsExprStatement); + return stsStatement; + } + +} diff --git a/migrator/src/com/ohos/migrator/staticTS/NodeBuilder.java b/migrator/src/com/ohos/migrator/staticTS/NodeBuilderBase.java similarity index 48% rename from migrator/src/com/ohos/migrator/staticTS/NodeBuilder.java rename to migrator/src/com/ohos/migrator/staticTS/NodeBuilderBase.java index 70c2e6eadd72058271cf0b9cc6b4a9a362928157..ed9ac8f233512f45daff6ec7000324b3d5435c52 100644 --- a/migrator/src/com/ohos/migrator/staticTS/NodeBuilder.java +++ b/migrator/src/com/ohos/migrator/staticTS/NodeBuilderBase.java @@ -22,11 +22,13 @@ import org.antlr.v4.runtime.ParserRuleContext; import org.antlr.v4.runtime.Vocabulary; import org.antlr.v4.runtime.tree.TerminalNode; import org.antlr.v4.runtime.tree.TerminalNodeImpl; -import org.eclipse.jdt.core.dom.*; -public class NodeBuilder { +public class NodeBuilderBase { private static final Vocabulary vocabulary = StaticTSParser.VOCABULARY; - private static final String UNKNOWN_TYPE_NAME = "__UnknownType__"; + protected static final String UNKNOWN_TYPE_NAME = "__UnknownType__"; + protected static final String UNTRANSLATED_EXPRESSION = "__untranslated_expression"; + protected static final String UNTRANSLATED_STATEMENT = "__untranslated_statement"; + public static TerminalNode terminalNode(int type) { return new TerminalNodeImpl(new CommonToken(type, stsName(type))); } @@ -54,9 +56,6 @@ public class NodeBuilder { public static TerminalNode multiLineComment(String comment) { return new TerminalNodeImpl(new CommonToken(StaticTSParser.MultiLineComment, comment)); } - public static TerminalNode terminalIdentifier(SimpleName name) { - return terminalIdentifier(name.getIdentifier()); - } // The 'name' here is expected to be a dot-separated sequence of names: 'name' '.' 'name' '.' 'name' ... public static QualifiedNameContext qualifiedName(String fqname) { @@ -65,68 +64,31 @@ public class NodeBuilder { return stsQualifiedName; } - public static QualifiedNameContext qualifiedName(Name javaName) { - return qualifiedName(javaName.getFullyQualifiedName()); - } - - private static int stsTypeNameCode(PrimitiveType.Code javaPrimitiveTypeCode) { - int stsTypeNameCode = -1; - - if (javaPrimitiveTypeCode == PrimitiveType.BOOLEAN) - stsTypeNameCode = StaticTSParser.Boolean; - else if (javaPrimitiveTypeCode == PrimitiveType.BYTE) - stsTypeNameCode = StaticTSParser.Byte; - else if (javaPrimitiveTypeCode == PrimitiveType.CHAR) - stsTypeNameCode = StaticTSParser.Char; - else if (javaPrimitiveTypeCode == PrimitiveType.INT) - stsTypeNameCode = StaticTSParser.Int; - else if (javaPrimitiveTypeCode == PrimitiveType.DOUBLE) - stsTypeNameCode = StaticTSParser.Double; - else if (javaPrimitiveTypeCode == PrimitiveType.FLOAT) - stsTypeNameCode = StaticTSParser.Float; - else if (javaPrimitiveTypeCode == PrimitiveType.LONG) - stsTypeNameCode = StaticTSParser.Long; - else if (javaPrimitiveTypeCode == PrimitiveType.SHORT) - stsTypeNameCode = StaticTSParser.Short; - else if (javaPrimitiveTypeCode == PrimitiveType.VOID) - stsTypeNameCode = StaticTSParser.Void; - else - assert false : "Unknown type"; - - return stsTypeNameCode; - } - - private static int stsTypeNameCode(String typeName) { - int stsTypeNameCode = -1; - - if ("boolean".equals(typeName)) - stsTypeNameCode = StaticTSParser.Boolean; - else if ("byte".equals(typeName)) - stsTypeNameCode = StaticTSParser.Byte; - else if ("char".equals(typeName)) - stsTypeNameCode = StaticTSParser.Char; - else if ("int".equals(typeName)) - stsTypeNameCode = StaticTSParser.Int; - else if ("double".equals(typeName)) - stsTypeNameCode = StaticTSParser.Double; - else if ("float".equals(typeName)) - stsTypeNameCode = StaticTSParser.Float; - else if ("long".equals(typeName)) - stsTypeNameCode = StaticTSParser.Long; - else if ("short".equals(typeName)) - stsTypeNameCode = StaticTSParser.Short; - else if ("void".equals(typeName)) - stsTypeNameCode = StaticTSParser.Void; - else - assert false : "Unknown type"; - - return stsTypeNameCode; - } - public static PredefinedTypeContext predefinedType(PrimitiveType.Code javaPrimitiveTypeCode) { - // predefinedType -> TerminalNode - PredefinedTypeContext stsPredefinedType = new PredefinedTypeContext(null, 0); - stsPredefinedType.addChild(terminalNode(stsTypeNameCode(javaPrimitiveTypeCode))); - return stsPredefinedType; + private static int stsTypeNameCode(String typeName) { + int stsTypeNameCode = -1; + + if ("boolean".equals(typeName)) + stsTypeNameCode = StaticTSParser.Boolean; + else if ("byte".equals(typeName)) + stsTypeNameCode = StaticTSParser.Byte; + else if ("char".equals(typeName)) + stsTypeNameCode = StaticTSParser.Char; + else if ("int".equals(typeName)) + stsTypeNameCode = StaticTSParser.Int; + else if ("double".equals(typeName)) + stsTypeNameCode = StaticTSParser.Double; + else if ("float".equals(typeName)) + stsTypeNameCode = StaticTSParser.Float; + else if ("long".equals(typeName)) + stsTypeNameCode = StaticTSParser.Long; + else if ("short".equals(typeName)) + stsTypeNameCode = StaticTSParser.Short; + else if ("void".equals(typeName)) + stsTypeNameCode = StaticTSParser.Void; + else + assert false : "Unknown type"; + + return stsTypeNameCode; } public static PredefinedTypeContext predefinedType(String typeName) { @@ -135,21 +97,6 @@ public class NodeBuilder { stsPredefinedType.addChild(terminalNode(stsTypeNameCode(typeName))); return stsPredefinedType; } - public static AccessibilityModifierContext accessibilityModifier(int javaModifiers) { - int stsModifierCode = -1; - if ((javaModifiers & Modifier.PRIVATE) != 0) - stsModifierCode = StaticTSParser.Private; - else if ((javaModifiers & Modifier.PROTECTED) != 0) - stsModifierCode = StaticTSParser.Protected; - else if ((javaModifiers & Modifier.PUBLIC) != 0) - stsModifierCode = StaticTSParser.Public; - - if (stsModifierCode == -1) return null; - - AccessibilityModifierContext stsAccessMod = new AccessibilityModifierContext(null, 0); - stsAccessMod.addChild(terminalNode(stsModifierCode)); - return stsAccessMod; - } // STS tree: // singleExpression: | literal # LiteralExpression @@ -256,9 +203,6 @@ public class NodeBuilder { return stsExpression; } - // Java: - // QualifiedType: Type . { Annotation } SimpleName - // SimpleType: { Annotation } TypeName // STS: // typeReference: typeReferencePart ('.' typeReferencePart)* // typeReferencePart: qualifiedName typeArguments? @@ -275,59 +219,12 @@ public class NodeBuilder { return stsTypeRefPart; } - public static TypeReferenceContext typeReference(PrimitiveType javaPrimitivetype) { - PrimitiveType.Code javaPrimitiveTypeCode = javaPrimitivetype.getPrimitiveTypeCode(); - TypeReferenceContext stsTypeReference = new TypeReferenceContext(null, 0); - stsTypeReference.addChild(qualifiedName(stsName(stsTypeNameCode(javaPrimitiveTypeCode)))).setParent(stsTypeReference); - return stsTypeReference; - } - public static TypeReferenceContext typeReference(String stsQualifierText, Name javaName) { - String typeFQN = stsQualifierText + '.' + javaName.getFullyQualifiedName(); - - TypeReferenceContext stsTypeReference = new TypeReferenceContext(null, 0); - stsTypeReference.addChild(qualifiedName(typeFQN)).setParent(stsTypeReference); - return stsTypeReference; - } - public static TypeReferenceContext unknownTypeReference(String comment) { String typeName = UNKNOWN_TYPE_NAME; if (comment != null) typeName += " /* " + comment + " */"; return typeReference(typeName); } - public static AssignmentOperatorContext assignmentOperator(Assignment.Operator javaAssignOp) { - int stsOperatorCode = -1; - - if (javaAssignOp == Assignment.Operator.PLUS_ASSIGN) - stsOperatorCode = StaticTSParser.PlusAssign; - else if (javaAssignOp == Assignment.Operator.MINUS_ASSIGN) - stsOperatorCode = StaticTSParser.MinusAssign; - else if (javaAssignOp == Assignment.Operator.TIMES_ASSIGN) - stsOperatorCode = StaticTSParser.MultiplyAssign; - else if (javaAssignOp == Assignment.Operator.DIVIDE_ASSIGN) - stsOperatorCode = StaticTSParser.DivideAssign; - else if (javaAssignOp == Assignment.Operator.BIT_AND_ASSIGN) - stsOperatorCode = StaticTSParser.BitAndAssign; - else if (javaAssignOp == Assignment.Operator.BIT_OR_ASSIGN) - stsOperatorCode = StaticTSParser.BitOrAssign; - else if (javaAssignOp == Assignment.Operator.BIT_XOR_ASSIGN) - stsOperatorCode = StaticTSParser.BitXorAssign; - else if (javaAssignOp == Assignment.Operator.REMAINDER_ASSIGN) - stsOperatorCode = StaticTSParser.ModulusAssign; - else if (javaAssignOp == Assignment.Operator.LEFT_SHIFT_ASSIGN) - stsOperatorCode = StaticTSParser.LeftShiftArithmeticAssign; - else if (javaAssignOp == Assignment.Operator.RIGHT_SHIFT_SIGNED_ASSIGN) - stsOperatorCode = StaticTSParser.RightShiftArithmeticAssign; - else if (javaAssignOp == Assignment.Operator.RIGHT_SHIFT_UNSIGNED_ASSIGN) - stsOperatorCode = StaticTSParser.RightShiftLogicalAssign; - - if (stsOperatorCode == -1) return null; - - AssignmentOperatorContext stsAssignOp = new AssignmentOperatorContext(null, 0); - stsAssignOp.addChild(terminalNode(stsOperatorCode)); - return stsAssignOp; - } - // STS tree: // singleExpression: | Identifier # IdentifierExpression public static SingleExpressionContext identifierExpression(String name) { @@ -339,32 +236,6 @@ public class NodeBuilder { return stsExpression; } - public static void addExtraDimensions(ParserRuleContext stsCurrent, int extraDims) { - assert(stsCurrent instanceof TypeAnnotationContext && extraDims > 0); - - PrimaryTypeContext stsPrimaryType = ((TypeAnnotationContext)stsCurrent).primaryType(); - ArrayTypeContext stsArrayType = stsPrimaryType.arrayType(); - if (stsArrayType == null) { - // Should be either a type reference or predefined type. - ParserRuleContext stsType = stsPrimaryType.typeReference(); - if (stsType == null) stsType = stsPrimaryType.predefinedType(); - assert(stsType != null); - - // Drop the type which we just extracted above. - stsPrimaryType.removeLastChild(); - - // Construct new ArrayTypeContext and link it up to PrimaryTypeContext. - stsArrayType = new ArrayTypeContext(stsPrimaryType, 0); - stsArrayType.addChild(stsType).setParent(stsArrayType); - stsPrimaryType.addChild(stsArrayType); - } - - for (int i = 0; i < extraDims; ++i) { - stsArrayType.addChild(terminalNode(StaticTSParser.OpenBracket)); - stsArrayType.addChild(terminalNode(StaticTSParser.CloseBracket)); - } - } - public static ArrayTypeContext arrayType(String elementTypeName, int dimensions) { return arrayType(typeReference(elementTypeName), dimensions); } @@ -414,13 +285,6 @@ public class NodeBuilder { return stsParam; } - public static ParameterContext parameter(String stsParamName, PrimitiveType.Code javaPrimitiveTypeCode) { - ParameterContext stsParam = new ParameterContext(null, 0); - stsParam.addChild(terminalIdentifier(stsParamName)); - stsParam.addChild(typeAnnotation(predefinedType(javaPrimitiveTypeCode))).setParent(stsParam); - return stsParam; - } - public static ConstructorCallContext ctorCall(boolean isSuperCall, String... stsArgNames) { ConstructorCallContext stsSuperCtorCall = new ConstructorCallContext(null, 0); stsSuperCtorCall.addChild(terminalNode(isSuperCall ? StaticTSParser.Super : StaticTSParser.This)); @@ -441,27 +305,7 @@ public class NodeBuilder { return typeAnnotation(UNKNOWN_TYPE_NAME); } - public static TypeAnnotationContext unknownTypeAnnotation(Type javaType) { - TypeAnnotationContext stsTypeAnnotation = unknownTypeAnnotation(); - - if (javaType != null) { - stsTypeAnnotation.addChild(multiLineComment("/* " + javaType.toString() + " */")); - } - - return stsTypeAnnotation; - } - - public static TypeAnnotationContext unknownTypeAnnotation(ITypeBinding javaTypeBinding) { - TypeAnnotationContext stsTypeAnnotation = unknownTypeAnnotation(); - - if (javaTypeBinding != null) { - stsTypeAnnotation.addChild(multiLineComment("/* " + javaTypeBinding.getName() + " */")); - } - - return stsTypeAnnotation; - } - - private static SingleExpressionContext dummyCall(String callName, String comment) { + protected static SingleExpressionContext dummyCall(String callName, String comment) { SingleExpressionContext stsExpression = new SingleExpressionContext(null, 0); CallExpressionContext stsCallExpression = new CallExpressionContext(stsExpression); stsExpression.addChild(stsCallExpression).setParent(stsExpression); @@ -477,65 +321,11 @@ public class NodeBuilder { return stsExpression; } - public static SingleExpressionContext untranslatedExpression(ASTNode node) { - return dummyCall("__untranslated_expression", node.toString()); - } - public static boolean needStatementOrLocalDeclaration(ParserRuleContext stsContext) { return stsContext.getRuleIndex() == StaticTSParser.RULE_block || stsContext.getRuleIndex() == StaticTSParser.RULE_constructorBody; } - public static ParserRuleContext untranslatedStatement(ASTNode node, ParserRuleContext stsContext) { - StatementContext stsStatement = new StatementContext(null, 0); - ExpressionStatementContext stsExprStatement = new ExpressionStatementContext(stsStatement, 0); - stsStatement.addChild(stsExprStatement); - stsExprStatement.addChild(dummyCall("__untranslated_statement", node.toString())).setParent(stsExprStatement); - - if (needStatementOrLocalDeclaration(stsContext)) { - StatementOrLocalDeclarationContext stsStmtOrLocalDecl = new StatementOrLocalDeclarationContext(null, 0); - stsStmtOrLocalDecl.addChild(stsStatement).setParent(stsStmtOrLocalDecl); - return stsStmtOrLocalDecl; - } - - return stsStatement; - } - - public static ParserRuleContext untranslatedTryResource(ASTNode node, ParserRuleContext stsContext) { - StatementContext stsStatement = new StatementContext(null, 0); - ExpressionStatementContext stsExprStatement = new ExpressionStatementContext(stsStatement, 0); - stsStatement.addChild(stsExprStatement); - stsExprStatement.addChild(dummyCall("__untranslated_try_resource", node.toString())).setParent(stsExprStatement); - - if (needStatementOrLocalDeclaration(stsContext)) { - StatementOrLocalDeclarationContext stsStmtOrLocalDecl = new StatementOrLocalDeclarationContext(null, 0); - stsStmtOrLocalDecl.addChild(stsStatement).setParent(stsStmtOrLocalDecl); - return stsStmtOrLocalDecl; - } - - return stsStatement; - } - - public static ShiftOperatorContext shiftOperator(InfixExpression.Operator javaOp) { - ShiftOperatorContext stsShiftOp = new ShiftOperatorContext(null, 0); - - if (javaOp == InfixExpression.Operator.LEFT_SHIFT) { - stsShiftOp.addChild(NodeBuilder.terminalNode(StaticTSParser.LessThan)); - stsShiftOp.addChild(NodeBuilder.terminalNode(StaticTSParser.LessThan)); - } - else if (javaOp == InfixExpression.Operator.RIGHT_SHIFT_SIGNED) { - stsShiftOp.addChild(NodeBuilder.terminalNode(StaticTSParser.MoreThan)); - stsShiftOp.addChild(NodeBuilder.terminalNode(StaticTSParser.MoreThan)); - } - else if (javaOp == InfixExpression.Operator.RIGHT_SHIFT_UNSIGNED) { - stsShiftOp.addChild(NodeBuilder.terminalNode(StaticTSParser.MoreThan)); - stsShiftOp.addChild(NodeBuilder.terminalNode(StaticTSParser.MoreThan)); - stsShiftOp.addChild(NodeBuilder.terminalNode(StaticTSParser.MoreThan)); - } - - return stsShiftOp; - } - public static void addArgument(CallExpressionContext stsCallExpr, SingleExpressionContext stsArg) { ArgumentsContext stsArgs = stsCallExpr.arguments(); if (stsArgs != null) { @@ -579,116 +369,9 @@ public class NodeBuilder { return stsSingleExpr; } - public static ParserRuleContext translateTypeBinding(ITypeBinding javaType) { - if (javaType.isPrimitive()) { - return predefinedType(javaType.getName()); - } - - if (javaType.isArray()) { - ITypeBinding javaArrayElemType = javaType.getElementType(); - ParserRuleContext stsArrayElemType = translateTypeBinding(javaArrayElemType); - return arrayType(stsArrayElemType, javaType.getDimensions()); - } - - if (javaType.isParameterizedType()) { - ITypeBinding javaErasedType = javaType.getErasure(); - ParserRuleContext stsType = translateTypeBinding(javaErasedType); - if (stsType.getRuleIndex() != StaticTSParser.RULE_typeReference) { - stsType = unknownTypeReference(javaErasedType.getQualifiedName()); - } - - // Translate type arguments and inject them into last child of TypeReferenceContext node - TypeReferencePartContext stsLastTypePart = (TypeReferencePartContext)stsType.getChild(stsType.getChildCount()-1); - TypeArgumentsContext stsTypeArgs = translateTypeArguments(javaType.getTypeArguments()); - stsLastTypePart.addChild(stsTypeArgs).setParent(stsLastTypePart); - return stsType; - } - - if (javaType.isWildcardType()) { - WildcardTypeContext stsWildCardType = new WildcardTypeContext(null, 0); - ITypeBinding javaBoundType = javaType.getBound(); - if (javaBoundType != null) { - String stsInOrOutKeyword = javaType.isUpperbound() ? StaticTSParser.OUT : StaticTSParser.IN; - stsWildCardType.addChild(terminalIdentifier(stsInOrOutKeyword)); - ParserRuleContext stsBoundType = translateTypeBinding(javaBoundType); - stsWildCardType.addChild(stsBoundType).setParent(stsWildCardType); - } - else { - stsWildCardType.addChild(terminalIdentifier(StaticTSParser.OUT)); - } - return stsWildCardType; - } - - if (javaType.isIntersectionType()) { - IntersectionTypeContext stsIntersectionType = new IntersectionTypeContext(null, 0); - for (ITypeBinding javaIntersectedType : javaType.getTypeBounds()) { - ParserRuleContext stsIntersectedType = translateTypeBinding(javaIntersectedType); - stsIntersectionType.addChild(stsIntersectedType).setParent(stsIntersectionType); - } - return stsIntersectionType; - } - - // All other types should be named - just emit TypeReferenceContext - TypeReferenceContext stsTypeRef = typeReference(javaType.getQualifiedName()); - addEmptyTypeArgumentsToRawType(stsTypeRef, javaType); - return stsTypeRef; - } - - public static void addEmptyTypeArgumentsToRawType(TypeReferenceContext stsTypeRef, ITypeBinding javaTypeBinding) { - if (javaTypeBinding != null && javaTypeBinding.isRawType()) { - TypeReferencePartContext stsLastTypePart = (TypeReferencePartContext) stsTypeRef.getChild(stsTypeRef.getChildCount() - 1); - stsLastTypePart.addChild(new TypeArgumentsContext(stsLastTypePart, 0)).setParent(stsLastTypePart); - } - } - public static void addEmptyTypeArgumentsToRawType(TypeReferenceContext stsTypeRef, Type javaType) { - ITypeBinding javaTypeBinding = getTypeBinding(javaType); - addEmptyTypeArgumentsToRawType(stsTypeRef, javaTypeBinding); - } - public static TypeArgumentsContext translateTypeArguments(ITypeBinding[] javaTypeArgs) { - TypeArgumentsContext stsTypeArgs = new TypeArgumentsContext(null, 0); - - if (javaTypeArgs != null) { - TypeArgumentListContext stsTypeArgList = new TypeArgumentListContext(stsTypeArgs, 0); - stsTypeArgs.addChild(stsTypeArgList).setParent(stsTypeArgs); - - for (ITypeBinding javaTypeArg : javaTypeArgs) { - ParserRuleContext stsTypeArg = translateTypeBinding(javaTypeArg); - if (!isTypeArgument(stsTypeArg)) stsTypeArg = unknownTypeReference(null); - - TypeArgumentContext stsTypeArgNode = new TypeArgumentContext(stsTypeArgList, 0); - stsTypeArgNode.addChild(stsTypeArg).setParent(stsTypeArgNode); - stsTypeArgList.addChild(stsTypeArgNode).setParent(stsTypeArgList); - } - } - - return stsTypeArgs; - } - public static boolean isTypeArgument(ParserRuleContext stsType) { return stsType.getRuleIndex() == StaticTSParser.RULE_arrayType || stsType.getRuleIndex() == StaticTSParser.RULE_typeReference || stsType.getRuleIndex() == StaticTSParser.RULE_wildcardType; } - - public static boolean isTypeArgument(Type javaType) { - return isTypeReference(javaType) || javaType.isArrayType() || javaType.isWildcardType(); - } - - public static boolean isTypeReference(Type javaType) { - return javaType.isSimpleType() || javaType.isQualifiedType() || - javaType.isNameQualifiedType() || javaType.isParameterizedType(); - } - - public static ITypeBinding getTypeBinding(Type javaType) { - // Type.resolveBinding() can throw exceptions, so let's catch them - ITypeBinding javaTypeBinding; - try { - javaTypeBinding = javaType.resolveBinding(); - } - catch (Exception e) { - javaTypeBinding = null; - } - - return javaTypeBinding; - } } diff --git a/migrator/src/com/ohos/migrator/staticTS/writer/StaticTSWriter.java b/migrator/src/com/ohos/migrator/staticTS/writer/StaticTSWriter.java index 125f03a9f61f97d19a58a4bd4dbaaf3785c2ba7e..a522fa378c5b6a85ccc7e9ab22dedf1c2aaea065 100644 --- a/migrator/src/com/ohos/migrator/staticTS/writer/StaticTSWriter.java +++ b/migrator/src/com/ohos/migrator/staticTS/writer/StaticTSWriter.java @@ -1463,8 +1463,8 @@ public class StaticTSWriter extends StaticTSParserBaseVisitor { public Void visitParameterList(ParameterListContext stsParameterList) { List stsParameters = stsParameterList.parameter(); + int i = 0; if (stsParameters != null) { - int i = 0; for (ParameterContext stsParameter : stsParameters) { if (i > 0) sb.append(", "); visitParameter(stsParameter); @@ -1474,7 +1474,7 @@ public class StaticTSWriter extends StaticTSParserBaseVisitor { VariadicParameterContext stsVariadicParameter = stsParameterList.variadicParameter(); if (stsVariadicParameter != null) { - sb.append(", "); + if (i > 0) sb.append(", "); visitVariadicParameter(stsVariadicParameter); } diff --git a/migrator/test/kotlin/global_functions.kt b/migrator/test/kotlin/global_functions.kt new file mode 100644 index 0000000000000000000000000000000000000000..8a1586c147b2af242dc2d7167e21f96c2f3119bf --- /dev/null +++ b/migrator/test/kotlin/global_functions.kt @@ -0,0 +1,24 @@ +/* + * 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.kotlin; + +fun main() { } + +public fun doubleNum(x: Int): Int = x * 2 + +private fun sum(vararg x: Int) = x.sum(); + +internal fun doNothing() {} diff --git a/migrator/test/kotlin/global_functions.kt.sts b/migrator/test/kotlin/global_functions.kt.sts new file mode 100644 index 0000000000000000000000000000000000000000..a7efad8055825cb6656b35e739a4a44164a27e9e --- /dev/null +++ b/migrator/test/kotlin/global_functions.kt.sts @@ -0,0 +1,27 @@ +/* + * 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.kotlin; + +export function main(): kotlin.Unit { +} +export function doubleNum(x : Int): Int { + return __untranslated_expression(/* x * 2 */); +} +function sum(... x: Int ): __UnknownType__ { + return __untranslated_expression(/* x.sum() */); +} +function doNothing(): kotlin.Unit { +} diff --git a/migrator/test/kotlin/imports.kt.sts b/migrator/test/kotlin/imports.kt.sts index 38e0ee32a1892db52ec7bc3675e5294115354dae..2a78c43790f5bc471f44c89267e1753a56a1ab01 100644 --- a/migrator/test/kotlin/imports.kt.sts +++ b/migrator/test/kotlin/imports.kt.sts @@ -17,4 +17,6 @@ package com.ohos.migrator.test.kotlin; import kotlin.random.Random; import kotlin.math.*; -import kotlin.reflect.KClass as Class; \ No newline at end of file +import kotlin.reflect.KClass as Class; +export function main(): kotlin.Unit { +} \ No newline at end of file diff --git a/migrator/test/kotlin/method_declaration.kt b/migrator/test/kotlin/method_declaration.kt new file mode 100644 index 0000000000000000000000000000000000000000..2440ea2436a1b92b9e6930283b70c07f7d877a7f --- /dev/null +++ b/migrator/test/kotlin/method_declaration.kt @@ -0,0 +1,30 @@ +/* + * 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.kotlin; + +abstract class C { + fun no_modifiers() { } + + abstract public fun abstract_public(): String; + + open fun open_m() { } + + private fun private_m(x : Int) { } + + protected fun protected_m(a: Int, vararg b: Double) { } + + internal fun internal_m() { } +} \ No newline at end of file diff --git a/migrator/test/kotlin/method_declaration.kt.sts b/migrator/test/kotlin/method_declaration.kt.sts new file mode 100644 index 0000000000000000000000000000000000000000..71e3679880f33993558e53bf9ec3887bb3af4b23 --- /dev/null +++ b/migrator/test/kotlin/method_declaration.kt.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.kotlin; + +export abstract class C { + public no_modifiers(): kotlin.Unit { + } + public abstract abstract_public(): String ; + public open open_m(): kotlin.Unit { + } + private private_m(x : Int): kotlin.Unit { + } + protected protected_m(a : Int, ... b: Double ): kotlin.Unit { + } + internal_m(): kotlin.Unit { + } +} +