From b17effd3a34c436267352b4d26e912288cf636bc Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Wed, 30 May 2012 20:57:31 +0200 Subject: [PATCH] converted to kotlin; doesn't compile yet because of errors in frontend --- src/org/jetbrains/jet/j2k/Converter.kt | 2 +- .../jet/j2k/ast/NewClassExpression.java | 59 -- .../jet/j2k/ast/NewClassExpression.kt | 26 + src/org/jetbrains/jet/j2k/ast/Statements.kt | 6 + .../jet/j2k/ast/SynchronizedStatement.java | 38 -- .../jet/j2k/visitors/ElementVisitor.kt | 2 +- .../jet/j2k/visitors/ExpressionVisitor.java | 508 ------------------ .../jet/j2k/visitors/ExpressionVisitor.kt | 451 ++++++++++++++++ .../jet/j2k/visitors/StatementVisitor.java | 393 -------------- .../jet/j2k/visitors/StatementVisitor.kt | 278 ++++++++++ .../jetbrains/jet/j2k/visitors/TypeVisitor.kt | 4 +- 11 files changed, 765 insertions(+), 1002 deletions(-) delete mode 100644 src/org/jetbrains/jet/j2k/ast/NewClassExpression.java create mode 100644 src/org/jetbrains/jet/j2k/ast/NewClassExpression.kt delete mode 100644 src/org/jetbrains/jet/j2k/ast/SynchronizedStatement.java delete mode 100644 src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.java create mode 100644 src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.kt delete mode 100644 src/org/jetbrains/jet/j2k/visitors/StatementVisitor.java create mode 100644 src/org/jetbrains/jet/j2k/visitors/StatementVisitor.kt diff --git a/src/org/jetbrains/jet/j2k/Converter.kt b/src/org/jetbrains/jet/j2k/Converter.kt index 72eef417389..008c10d8867 100644 --- a/src/org/jetbrains/jet/j2k/Converter.kt +++ b/src/org/jetbrains/jet/j2k/Converter.kt @@ -351,7 +351,7 @@ public open class Converter() { return typeVisitor.getResult() } - public open fun typesToTypeList(types: Array): List { + public open fun typesToTypeList(types: Array): List { return types.map { typeToType(it) } } diff --git a/src/org/jetbrains/jet/j2k/ast/NewClassExpression.java b/src/org/jetbrains/jet/j2k/ast/NewClassExpression.java deleted file mode 100644 index e0d93b812b9..00000000000 --- a/src/org/jetbrains/jet/j2k/ast/NewClassExpression.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2010-2012 JetBrains s.r.o. - * - * 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 org.jetbrains.jet.j2k.ast; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.j2k.util.AstUtil; - -import java.util.List; - -/** - * @author ignatov - */ -public class NewClassExpression extends Expression { - private final Element myName; - private final List myArguments; - private Expression myQualifier; - @Nullable - private AnonymousClass myAnonymousClass = null; - - private NewClassExpression(Element name, List arguments) { - myName = name; - myQualifier = EMPTY_EXPRESSION; - myArguments = arguments; - } - - public NewClassExpression(@NotNull Element name, @NotNull List arguments, @NotNull Expression qualifier, - @Nullable AnonymousClass anonymousClass) { - this(name, arguments); - myQualifier = qualifier; - myAnonymousClass = anonymousClass; - } - - @NotNull - @Override - public String toKotlin() { - final String callOperator = myQualifier.isNullable() ? QUESTDOT : DOT; - final String qualifier = myQualifier.isEmpty() ? EMPTY : myQualifier.toKotlin() + callOperator; - String appliedArguments = AstUtil.joinNodes(myArguments, COMMA_WITH_SPACE); - return myAnonymousClass != null ? - "object" + SPACE + ":" + SPACE + qualifier + myName.toKotlin() + "(" + appliedArguments + ")" + myAnonymousClass.toKotlin() - : - qualifier + myName.toKotlin() + "(" + appliedArguments + ")"; - } -} diff --git a/src/org/jetbrains/jet/j2k/ast/NewClassExpression.kt b/src/org/jetbrains/jet/j2k/ast/NewClassExpression.kt new file mode 100644 index 00000000000..d5beb8a698a --- /dev/null +++ b/src/org/jetbrains/jet/j2k/ast/NewClassExpression.kt @@ -0,0 +1,26 @@ +package org.jetbrains.jet.j2k.ast + +import org.jetbrains.annotations.Nullable +import org.jetbrains.jet.j2k.util.AstUtil +import java.util.List + +public open class NewClassExpression(val name: Element, + val arguments: List, + val qualifier: Expression = Expression.EMPTY_EXPRESSION, + val anonymousClass: AnonymousClass? = null): Expression() { + public override fun toKotlin(): String { + val callOperator: String? = (if (qualifier.isNullable().sure()) + "?." + else + ".") + val qualifier: String? = (if (qualifier.isEmpty().sure()) + "" + else + qualifier.toKotlin() + callOperator) + val appliedArguments: String = arguments.toKotlin(", ") + return (if (anonymousClass != null) + "object : " + qualifier + name.toKotlin() + "(" + appliedArguments + ")" + anonymousClass.toKotlin() + else + qualifier + name.toKotlin() + "(" + appliedArguments + ")") + } +} diff --git a/src/org/jetbrains/jet/j2k/ast/Statements.kt b/src/org/jetbrains/jet/j2k/ast/Statements.kt index 8ada7925a2a..04cc9d234db 100644 --- a/src/org/jetbrains/jet/j2k/ast/Statements.kt +++ b/src/org/jetbrains/jet/j2k/ast/Statements.kt @@ -115,3 +115,9 @@ public open class SwitchLabelStatement(val expression: Expression): Statement() public open class DefaultSwitchLabelStatement(): Statement() { public override fun toKotlin() = "else" } + +// Other ------------------------------------------------------------------------------------------------------ + +public open class SynchronizedStatement(val expression: Expression, val block: Block): Statement() { + public override fun toKotlin() = "synchronized (" + expression?.toKotlin() + ") "+ block.toKotlin() +} diff --git a/src/org/jetbrains/jet/j2k/ast/SynchronizedStatement.java b/src/org/jetbrains/jet/j2k/ast/SynchronizedStatement.java deleted file mode 100644 index a635853a2db..00000000000 --- a/src/org/jetbrains/jet/j2k/ast/SynchronizedStatement.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2010-2012 JetBrains s.r.o. - * - * 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 org.jetbrains.jet.j2k.ast; - -import org.jetbrains.annotations.NotNull; - -/** - * @author ignatov - */ -public class SynchronizedStatement extends Statement { - private final Expression myExpression; - private final Block myBlock; - - public SynchronizedStatement(Expression expression, Block block) { - myExpression = expression; - myBlock = block; - } - - @NotNull - @Override - public String toKotlin() { - return "synchronized" + SPACE + "(" + myExpression.toKotlin() + ")" + SPACE + myBlock.toKotlin(); - } -} diff --git a/src/org/jetbrains/jet/j2k/visitors/ElementVisitor.kt b/src/org/jetbrains/jet/j2k/visitors/ElementVisitor.kt index e7ffcc7b7c0..29691186826 100644 --- a/src/org/jetbrains/jet/j2k/visitors/ElementVisitor.kt +++ b/src/org/jetbrains/jet/j2k/visitors/ElementVisitor.kt @@ -32,7 +32,7 @@ public open class ElementVisitor(val myConverter : Converter) : JavaElementVisit public override fun visitReferenceElement(reference : PsiJavaCodeReferenceElement?) : Unit { val theReference = reference!! - val types : List = myConverter.typesToTypeList(theReference.getTypeParameters()).requireNoNulls() + val types : List = myConverter.typesToTypeList(theReference.getTypeParameters()) if (!theReference.isQualified()) { myResult = ReferenceElement(Identifier(theReference.getReferenceName()), types) } diff --git a/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.java b/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.java deleted file mode 100644 index c8cf0b5b263..00000000000 --- a/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.java +++ /dev/null @@ -1,508 +0,0 @@ -/* - * Copyright 2010-2012 JetBrains s.r.o. - * - * 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 org.jetbrains.jet.j2k.visitors; - -import com.intellij.psi.*; -import com.intellij.psi.tree.IElementType; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.j2k.Converter; -import org.jetbrains.jet.j2k.ast.*; -import org.jetbrains.jet.j2k.ast.types.EmptyType; -import org.jetbrains.jet.j2k.ast.types.Type; -import org.jetbrains.jet.lang.types.expressions.OperatorConventions; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import static com.intellij.psi.CommonClassNames.*; - -/** - * @author ignatov - */ -public class ExpressionVisitor extends StatementVisitor { - @NotNull - Expression myResult = Expression.EMPTY_EXPRESSION; - - public ExpressionVisitor(@NotNull Converter converter) { - super(converter); - } - - @Override - public void visitExpression(final PsiExpression expression) { - myResult = Expression.EMPTY_EXPRESSION; - } - - @NotNull - @Override - public Expression getResult() { - return myResult; - } - - @Override - public void visitArrayAccessExpression(@NotNull PsiArrayAccessExpression expression) { - super.visitArrayAccessExpression(expression); - myResult = new ArrayAccessExpression( - getConverter().expressionToExpression(expression.getArrayExpression()), - getConverter().expressionToExpression(expression.getIndexExpression()) - ); - } - - @Override - public void visitArrayInitializerExpression(@NotNull PsiArrayInitializerExpression expression) { - super.visitArrayInitializerExpression(expression); - myResult = new ArrayInitializerExpression( - getConverter().typeToType(expression.getType()), - getConverter().expressionsToExpressionList(expression.getInitializers()) - ); - } - - @Override - public void visitAssignmentExpression(@NotNull PsiAssignmentExpression expression) { - super.visitAssignmentExpression(expression); - - // TODO: simplify - - final IElementType tokenType = expression.getOperationSign().getTokenType(); - - String secondOp = ""; - if (tokenType == JavaTokenType.GTGTEQ) secondOp = "shr"; - if (tokenType == JavaTokenType.LTLTEQ) secondOp = "shl"; - if (tokenType == JavaTokenType.XOREQ) secondOp = "xor"; - if (tokenType == JavaTokenType.ANDEQ) secondOp = "and"; - if (tokenType == JavaTokenType.OREQ) secondOp = "or"; - if (tokenType == JavaTokenType.GTGTGTEQ) secondOp = "ushr"; - - if (!secondOp.isEmpty()) // if not Kotlin operators - { - myResult = new AssignmentExpression( - getConverter().expressionToExpression(expression.getLExpression()), - new BinaryExpression( - getConverter().expressionToExpression(expression.getLExpression()), - getConverter().expressionToExpression(expression.getRExpression()), - secondOp - ), - "=" - ); - } - else { - myResult = new AssignmentExpression( - getConverter().expressionToExpression(expression.getLExpression()), - getConverter().expressionToExpression(expression.getRExpression()), - expression.getOperationSign().getText() // TODO - ); - } - } - - @NotNull - private static String getOperatorString(@NotNull IElementType tokenType) { - if (tokenType == JavaTokenType.PLUS) return "+"; - if (tokenType == JavaTokenType.MINUS) return "-"; - if (tokenType == JavaTokenType.ASTERISK) return "*"; - if (tokenType == JavaTokenType.DIV) return "/"; - if (tokenType == JavaTokenType.PERC) return "%"; - if (tokenType == JavaTokenType.GTGT) return "shr"; - if (tokenType == JavaTokenType.LTLT) return "shl"; - if (tokenType == JavaTokenType.XOR) return "xor"; - if (tokenType == JavaTokenType.AND) return "and"; - if (tokenType == JavaTokenType.OR) return "or"; - if (tokenType == JavaTokenType.GTGTGT) return "ushr"; - if (tokenType == JavaTokenType.GT) return ">"; - if (tokenType == JavaTokenType.LT) return "<"; - if (tokenType == JavaTokenType.GE) return ">="; - if (tokenType == JavaTokenType.LE) return "<="; - if (tokenType == JavaTokenType.EQEQ) return "=="; - if (tokenType == JavaTokenType.NE) return "!="; - if (tokenType == JavaTokenType.ANDAND) return "&&"; - if (tokenType == JavaTokenType.OROR) return "||"; - if (tokenType == JavaTokenType.PLUSPLUS) return "++"; - if (tokenType == JavaTokenType.MINUSMINUS) return "--"; - if (tokenType == JavaTokenType.EXCL) return "!"; - - System.out.println("UNSUPPORTED TOKEN TYPE: " + tokenType.toString()); - return ""; - } - - @Override - public void visitBinaryExpression(@NotNull PsiBinaryExpression expression) { - super.visitBinaryExpression(expression); - - if (expression.getOperationSign().getTokenType() == JavaTokenType.GTGTGT) { - myResult = new DummyMethodCallExpression( - getConverter().expressionToExpression(expression.getLOperand()), - "ushr", - getConverter().expressionToExpression(expression.getROperand())); - } - else { - myResult = - new BinaryExpression( - getConverter().expressionToExpression(expression.getLOperand(), expression.getType()), - getConverter().expressionToExpression(expression.getROperand(), expression.getType()), - getOperatorString(expression.getOperationSign().getTokenType()) - ); - } - } - - @Override - public void visitClassObjectAccessExpression(@NotNull PsiClassObjectAccessExpression expression) { - super.visitClassObjectAccessExpression(expression); - myResult = new ClassObjectAccessExpression(getConverter().elementToElement(expression.getOperand())); - } - - @Override - public void visitConditionalExpression(@NotNull PsiConditionalExpression expression) { - super.visitConditionalExpression(expression); - PsiExpression condition = expression.getCondition(); - PsiType type = condition.getType(); - Expression e = type != null ? - this.getConverter().expressionToExpression(condition, type) : - getConverter().expressionToExpression(condition); - myResult = new ParenthesizedExpression( - new IfStatement( - e, - getConverter().expressionToExpression(expression.getThenExpression()), - getConverter().expressionToExpression(expression.getElseExpression()) - ) - ); - } - - @Override - public void visitExpressionList(@NotNull PsiExpressionList list) { - super.visitExpressionList(list); - myResult = new ExpressionList(getConverter().expressionsToExpressionList(list.getExpressions())); - } - - @Override - public void visitInstanceOfExpression(@NotNull PsiInstanceOfExpression expression) { - super.visitInstanceOfExpression(expression); - PsiTypeElement checkType = expression.getCheckType(); - myResult = new IsOperator( - getConverter().expressionToExpression(expression.getOperand()), - new TypeElement(checkType == null ? new EmptyType() : myConverter.typeToType(checkType.getType()))); - } - - @Override - public void visitLiteralExpression(@NotNull PsiLiteralExpression expression) { - super.visitLiteralExpression(expression); - - final Object value = expression.getValue(); - String text = expression.getText(); - boolean isQuotingNeeded = true; - - final PsiType type = expression.getType(); - if (type != null) { - String canonicalTypeStr = type.getCanonicalText(); - if (canonicalTypeStr.equals("double") || canonicalTypeStr.equals(JAVA_LANG_DOUBLE)) { - text = text.replace("D", "").replace("d", ""); - if (!text.contains(".")) { - text += ".0"; - } - } - if (canonicalTypeStr.equals("float") || canonicalTypeStr.equals(JAVA_LANG_FLOAT)) { - text = text.replace("F", "").replace("f", "") + "." + OperatorConventions.FLOAT + "()"; - } - if (canonicalTypeStr.equals("long") || canonicalTypeStr.equals(JAVA_LANG_LONG)) { - text = text.replace("L", "").replace("l", ""); - } - if (canonicalTypeStr.equals("int") || canonicalTypeStr.equals(JAVA_LANG_INTEGER)) // need for hex support - { - text = value != null ? value.toString() : text; - } - - if (canonicalTypeStr.equals(JAVA_LANG_STRING)) { - isQuotingNeeded = false; - } - if (canonicalTypeStr.equals("char") || canonicalTypeStr.equals(JAVA_LANG_CHARACTER)) { - isQuotingNeeded = false; - } - } - myResult = new LiteralExpression(new Identifier(text, false, isQuotingNeeded)); - } - - @Override - public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) { - super.visitMethodCallExpression(expression); - if (!SuperVisitor.$classobj.isSuper(expression.getMethodExpression()) || !isInsidePrimaryConstructor(expression)) { - myResult = // TODO: not resolved - new MethodCallExpression( - getConverter().expressionToExpression(expression.getMethodExpression()), - getConverter().argumentsToExpressionList(expression), - getConverter().typesToTypeList(expression.getTypeArguments()), getConverter().typeToType(expression.getType()).getNullable() - ); - } - } - - @Override - public void visitCallExpression(PsiCallExpression callExpression) { - super.visitCallExpression(callExpression); - } - - @Override - public void visitNewExpression(@NotNull PsiNewExpression expression) { - super.visitNewExpression(expression); - if (expression.getArrayInitializer() != null) // new Foo[] {Foo(1), Foo(2)} - { - myResult = createNewEmptyArray(expression); - } - else if (expression.getArrayDimensions().length > 0) { // new Foo[5] - myResult = createNewEmptyArrayWithoutInitialization(expression); - } - else { // new Class(): common case - myResult = createNewClassExpression(expression); - } - } - - @NotNull - private Expression createNewClassExpression(@NotNull PsiNewExpression expression) { - final PsiAnonymousClass anonymousClass = expression.getAnonymousClass(); - final PsiMethod constructor = expression.resolveMethod(); - PsiJavaCodeReferenceElement classReference = expression.getClassOrAnonymousClassReference(); - final boolean isNotConvertedClass = classReference != null && !getConverter().getClassIdentifiers().contains(classReference.getQualifiedName()); - PsiExpressionList argumentList = expression.getArgumentList(); - PsiExpression[] arguments = argumentList != null ? argumentList.getExpressions() : new PsiExpression[]{}; - if (constructor == null || Converter.$classobj.isConstructorPrimary(constructor) || isNotConvertedClass) { - return new NewClassExpression( - getConverter().elementToElement(classReference), getConverter().argumentsToExpressionList(expression), getConverter().expressionToExpression(expression.getQualifier()), - anonymousClass != null ? getConverter().anonymousClassToAnonymousClass(anonymousClass) : null - ); - } - // is constructor secondary - final PsiJavaCodeReferenceElement reference = expression.getClassReference(); - final List typeParameters = reference != null - ? getConverter().typesToTypeList(reference.getTypeParameters()) - : Collections.emptyList(); - return new CallChainExpression( - new Identifier(constructor.getName(), false), - new MethodCallExpression( - new Identifier("init"), - getConverter().expressionsToExpressionList(arguments), - typeParameters, false)); - } - - @NotNull - private Expression createNewEmptyArrayWithoutInitialization(@NotNull PsiNewExpression expression) { - return new ArrayWithoutInitializationExpression( - getConverter().typeToType(expression.getType(), true), - getConverter().expressionsToExpressionList(expression.getArrayDimensions()) - ); - } - - @NotNull - private Expression createNewEmptyArray(@NotNull PsiNewExpression expression) { - return getConverter().expressionToExpression(expression.getArrayInitializer()); - } - - @Override - public void visitParenthesizedExpression(@NotNull PsiParenthesizedExpression expression) { - super.visitParenthesizedExpression(expression); - myResult = new ParenthesizedExpression( - getConverter().expressionToExpression(expression.getExpression()) - ); - } - - @Override - public void visitPostfixExpression(@NotNull PsiPostfixExpression expression) { - super.visitPostfixExpression(expression); - myResult = new PostfixOperator( - getOperatorString(expression.getOperationSign().getTokenType()), - getConverter().expressionToExpression(expression.getOperand()) - ); - } - - @Override - public void visitPrefixExpression(@NotNull PsiPrefixExpression expression) { - super.visitPrefixExpression(expression); - if (expression.getOperationTokenType() == JavaTokenType.TILDE) { - myResult = new DummyMethodCallExpression( - new ParenthesizedExpression(getConverter().expressionToExpression(expression.getOperand())), "inv", Expression.EMPTY_EXPRESSION - ); - } - else { - myResult = new PrefixOperator( - getOperatorString(expression.getOperationSign().getTokenType()), - getConverter().expressionToExpression(expression.getOperand()) - ); - } - } - - @Override - public void visitReferenceExpression(@NotNull PsiReferenceExpression expression) { - super.visitReferenceExpression(expression); - - final boolean isFieldReference = isFieldReference(expression, getContainingClass(expression)); - final boolean insideSecondaryConstructor = isInsideSecondaryConstructor(expression); - final boolean hasReceiver = isFieldReference && insideSecondaryConstructor; - final boolean isThis = isThisExpression(expression); - final boolean isNullable = getConverter().typeToType(expression.getType()).getNullable(); - final String className = getClassNameWithConstructor(expression); - - Expression identifier = new Identifier(expression.getReferenceName(), isNullable); - - final String __ = "__"; - if (hasReceiver) { - identifier = new CallChainExpression(new Identifier(__, false), new Identifier(expression.getReferenceName(), isNullable)); - } - else if (insideSecondaryConstructor && isThis) { - identifier = new Identifier("val __ = " + className); // TODO: hack - } - - myResult = new CallChainExpression( - getConverter().expressionToExpression(expression.getQualifierExpression()), - identifier // TODO: if type exists so identifier is nullable - ); - } - - @NotNull - private static String getClassNameWithConstructor(@NotNull PsiReferenceExpression expression) { - PsiElement context = expression.getContext(); - while (context != null) { - if (context instanceof PsiMethod && ((PsiMethod) context).isConstructor()) { - final PsiClass containingClass = ((PsiMethod) context).getContainingClass(); - if (containingClass != null) { - final PsiIdentifier identifier = containingClass.getNameIdentifier(); - if (identifier != null) { - return identifier.getText(); - } - } - } - context = context.getContext(); - } - return ""; - } - - @NotNull - static String getClassName(@NotNull PsiExpression expression) { - PsiElement context = expression.getContext(); - while (context != null) { - if (context instanceof PsiClass) { - final PsiClass containingClass = (PsiClass) context; - final PsiIdentifier identifier = containingClass.getNameIdentifier(); - if (identifier != null) { - return identifier.getText(); - } - } - context = context.getContext(); - } - return ""; - } - - private static boolean isFieldReference(@NotNull PsiReferenceExpression expression, PsiClass currentClass) { - final PsiReference reference = expression.getReference(); - if (reference != null) { - final PsiElement resolvedReference = reference.resolve(); - if (resolvedReference != null) { - if (resolvedReference instanceof PsiField) { - return ((PsiField) resolvedReference).getContainingClass() == currentClass; - } - } - } - return false; - } - - private static boolean isInsideSecondaryConstructor(@NotNull PsiReferenceExpression expression) { - PsiElement context = expression.getContext(); - while (context != null) { - if (context instanceof PsiMethod && ((PsiMethod) context).isConstructor()) { - return !Converter.$classobj.isConstructorPrimary((PsiMethod) context); - } - context = context.getContext(); - } - return false; - } - - private static boolean isInsidePrimaryConstructor(@NotNull PsiExpression expression) { - PsiElement context = expression.getContext(); - while (context != null) { - if (context instanceof PsiMethod && ((PsiMethod) context).isConstructor()) { - return Converter.$classobj.isConstructorPrimary((PsiMethod) context); - } - context = context.getContext(); - } - return false; - } - - @Nullable - private static PsiClass getContainingClass(@NotNull PsiExpression expression) { - PsiElement context = expression.getContext(); - while (context != null) { - if (context instanceof PsiMethod && ((PsiMethod) context).isConstructor()) { - return ((PsiMethod) context).getContainingClass(); - } - context = context.getContext(); - } - return null; - } - - private static boolean isThisExpression(@NotNull PsiReferenceExpression expression) { - for (PsiReference r : expression.getReferences()) - if (r.getCanonicalText().equals("this")) { - final PsiElement res = r.resolve(); - if (res != null && res instanceof PsiMethod && ((PsiMethod) res).isConstructor()) { - return true; - } - } - return false; - } - - @Override - public void visitSuperExpression(@NotNull PsiSuperExpression expression) { - super.visitSuperExpression(expression); - final PsiJavaCodeReferenceElement qualifier = expression.getQualifier(); - myResult = new SuperExpression( - qualifier != null ? - new Identifier(qualifier.getQualifiedName()) : - Identifier.EMPTY_IDENTIFIER - ); - } - - @Override - public void visitThisExpression(@NotNull PsiThisExpression expression) { - super.visitThisExpression(expression); - final PsiJavaCodeReferenceElement qualifier = expression.getQualifier(); - myResult = new ThisExpression( - qualifier != null ? - new Identifier(qualifier.getQualifiedName()) : - Identifier.EMPTY_IDENTIFIER - ); - } - - @Override - public void visitTypeCastExpression(@NotNull PsiTypeCastExpression expression) { - super.visitTypeCastExpression(expression); - - final PsiTypeElement castType = expression.getCastType(); - if (castType != null) { - myResult = new TypeCastExpression( - getConverter().typeToType(castType.getType()), - getConverter().expressionToExpression(expression.getOperand()) - ); - } - } - - @Override - public void visitPolyadicExpression(@NotNull PsiPolyadicExpression expression) { - List parameters = new ArrayList(); - for (PsiExpression operand : expression.getOperands()) { - parameters.add(getConverter().expressionToExpression(operand, expression.getType())); - } - myResult = new PolyadicExpression( - parameters, - getOperatorString(expression.getOperationTokenType()) - ); - } -} diff --git a/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.kt b/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.kt new file mode 100644 index 00000000000..64b4fbb0672 --- /dev/null +++ b/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.kt @@ -0,0 +1,451 @@ +package org.jetbrains.jet.j2k.visitors + +import com.intellij.psi.* +import com.intellij.psi.tree.IElementType +import org.jetbrains.annotations.Nullable +import org.jetbrains.jet.j2k.Converter +import org.jetbrains.jet.j2k.ast.* +import org.jetbrains.jet.j2k.ast.types.EmptyType +import org.jetbrains.jet.j2k.ast.types.Type +import org.jetbrains.jet.lang.types.expressions.OperatorConventions +import java.util.ArrayList +import java.util.Collections +import java.util.List +import com.intellij.psi.CommonClassNames.* + +public open class ExpressionVisitor(converter: Converter): StatementVisitor(converter) { + var myResult: Expression = Expression.EMPTY_EXPRESSION + + public override fun visitExpression(expression: PsiExpression?): Unit { + myResult = Expression.EMPTY_EXPRESSION + } + + public override fun getResult(): Expression { + return myResult + } + + public override fun visitArrayAccessExpression(expression: PsiArrayAccessExpression?): Unit { + myResult = ArrayAccessExpression(getConverter().expressionToExpression(expression?.getArrayExpression()), + getConverter().expressionToExpression(expression?.getIndexExpression())) + } + + public override fun visitArrayInitializerExpression(expression: PsiArrayInitializerExpression?): Unit { + myResult = ArrayInitializerExpression(getConverter().typeToType(expression?.getType()), + getConverter().expressionsToExpressionList(expression?.getInitializers()!!)) + } + + public override fun visitAssignmentExpression(expression: PsiAssignmentExpression?): Unit { + val tokenType: IElementType = expression?.getOperationSign()?.getTokenType()!! + val secondOp: String = when(tokenType) { + JavaTokenType.GTGTEQ -> "shr" + JavaTokenType.LTLTEQ -> "shl" + JavaTokenType.XOREQ -> "xor" + JavaTokenType.ANDEQ -> "and" + JavaTokenType.OREQ -> "or" + JavaTokenType.GTGTGTEQ -> "ushr" + else -> "" + } + + val lhs = getConverter().expressionToExpression(expression?.getLExpression()!!) + val rhs = getConverter().expressionToExpression(expression?.getRExpression()!!) + if (!secondOp.isEmpty()) { + myResult = AssignmentExpression(lhs, BinaryExpression(lhs, rhs, secondOp), "=") + } + else { + myResult = AssignmentExpression(lhs, rhs, expression?.getOperationSign()?.getText()!!) + } + } + + public override fun visitBinaryExpression(expression: PsiBinaryExpression?): Unit { + val lhs = getConverter().expressionToExpression(expression?.getLOperand()!!, expression?.getType()) + val rhs = getConverter().expressionToExpression(expression?.getROperand(), expression?.getType()) + if (expression?.getOperationSign()?.getTokenType() == JavaTokenType.GTGTGT) { + myResult = DummyMethodCallExpression(lhs, "ushr", rhs) + } + else { + myResult = BinaryExpression(lhs, rhs, + getOperatorString(expression?.getOperationSign()?.getTokenType()!!)) + } + } + + public override fun visitClassObjectAccessExpression(expression: PsiClassObjectAccessExpression?): Unit { + myResult = ClassObjectAccessExpression(getConverter().elementToElement(expression?.getOperand())) + } + + public override fun visitConditionalExpression(expression: PsiConditionalExpression?): Unit { + val condition: PsiExpression? = expression?.getCondition() + val `type`: PsiType? = condition?.getType() + val e: Expression = (if (`type` != null) + getConverter().expressionToExpression(condition, `type`) + else + getConverter().expressionToExpression(condition)) + myResult = ParenthesizedExpression(IfStatement(e, + getConverter().expressionToExpression(expression?.getThenExpression()), + getConverter().expressionToExpression(expression?.getElseExpression()))) + } + + public override fun visitExpressionList(list: PsiExpressionList?): Unit { + myResult = ExpressionList(getConverter().expressionsToExpressionList(list!!.getExpressions())) + } + + public override fun visitInstanceOfExpression(expression: PsiInstanceOfExpression?): Unit { + val checkType: PsiTypeElement? = expression?.getCheckType() + myResult = IsOperator(getConverter().expressionToExpression(expression?.getOperand()), TypeElement(if (checkType == null) + EmptyType() + else + myConverter.typeToType(checkType.getType()))) + } + + public override fun visitLiteralExpression(expression: PsiLiteralExpression?): Unit { + val value: Any? = expression?.getValue() + var text: String = expression?.getText()!! + var isQuotingNeeded: Boolean = true + val `type`: PsiType? = expression?.getType() + if (`type` != null) + { + var canonicalTypeStr: String? = `type`.getCanonicalText() + if (canonicalTypeStr?.equals("double")!! || canonicalTypeStr?.equals(JAVA_LANG_DOUBLE)!!) { + text = text.replace("D", "").replace("d", "") + if (!text.contains(".")) { + text += ".0" + } + + } + + if (canonicalTypeStr?.equals("float")!! || canonicalTypeStr?.equals(JAVA_LANG_FLOAT)!!) { + text = text.replace("F", "").replace("f", "") + "." + OperatorConventions.FLOAT + "()" + } + + if (canonicalTypeStr?.equals("long")!! || canonicalTypeStr?.equals(JAVA_LANG_LONG)!!) { + text = text.replace("L", "").replace("l", "") + } + + if (canonicalTypeStr?.equals("int")!! || canonicalTypeStr?.equals(JAVA_LANG_INTEGER)!!) { + text = (if (value != null) value.toString() else text) + } + + if (canonicalTypeStr?.equals(JAVA_LANG_STRING)!!) { + isQuotingNeeded = false + } + + if (canonicalTypeStr?.equals("char")!! || canonicalTypeStr?.equals(JAVA_LANG_CHARACTER)!!) { + isQuotingNeeded = false + } + + } + + myResult = LiteralExpression(Identifier(text, false, isQuotingNeeded)) + } + + public override fun visitMethodCallExpression(expression: PsiMethodCallExpression?): Unit { + if (!SuperVisitor.isSuper(expression!!.getMethodExpression()) || !isInsidePrimaryConstructor(expression!!)) + { + myResult = MethodCallExpression(getConverter().expressionToExpression(expression?.getMethodExpression()), + getConverter().argumentsToExpressionList(expression!!), + getConverter().typesToTypeList(expression?.getTypeArguments()!!), + getConverter().typeToType(expression?.getType()).nullable) + } + + } + + public override fun visitNewExpression(expression: PsiNewExpression?): Unit { + if (expression?.getArrayInitializer() != null) + { + myResult = createNewEmptyArray(expression) + } + else + if (expression?.getArrayDimensions()?.size!! > 0) { + myResult = createNewEmptyArrayWithoutInitialization(expression!!) + } + else + { + myResult = createNewClassExpression(expression) + } + } + + private fun createNewClassExpression(expression: PsiNewExpression?): Expression { + val anonymousClass: PsiAnonymousClass? = expression?.getAnonymousClass() + val constructor: PsiMethod? = expression?.resolveMethod() + var classReference: PsiJavaCodeReferenceElement? = expression?.getClassOrAnonymousClassReference() + val isNotConvertedClass: Boolean = classReference != null && !getConverter().getClassIdentifiers().contains(classReference?.getQualifiedName()) + var argumentList: PsiExpressionList? = expression?.getArgumentList() + var arguments: Array = (if (argumentList != null) + argumentList?.getExpressions()!! + else + array()) + if (constructor == null || Converter.isConstructorPrimary(constructor) || isNotConvertedClass) + { + return NewClassExpression(getConverter().elementToElement(classReference), + getConverter().argumentsToExpressionList(expression!!), + getConverter().expressionToExpression(expression?.getQualifier()), + (if (anonymousClass != null) + getConverter().anonymousClassToAnonymousClass(anonymousClass) + else + null)) + } + + val reference: PsiJavaCodeReferenceElement? = expression?.getClassReference() + val typeParameters: List = (if (reference != null) + getConverter().typesToTypeList(reference.getTypeParameters()) + else + Collections.emptyList()!!) + return CallChainExpression(Identifier(constructor.getName(), false), + MethodCallExpression(Identifier("init"), getConverter().expressionsToExpressionList(arguments), typeParameters, false)) + } + + private fun createNewEmptyArrayWithoutInitialization(expression: PsiNewExpression): Expression { + return ArrayWithoutInitializationExpression( + getConverter().typeToType(expression?.getType(), true), + getConverter().expressionsToExpressionList(expression?.getArrayDimensions())) + } + + private fun createNewEmptyArray(expression: PsiNewExpression?): Expression { + return getConverter().expressionToExpression(expression?.getArrayInitializer()) + } + + public override fun visitParenthesizedExpression(expression: PsiParenthesizedExpression?): Unit { + myResult = ParenthesizedExpression(getConverter().expressionToExpression(expression?.getExpression())) + } + + public override fun visitPostfixExpression(expression: PsiPostfixExpression?): Unit { + myResult = PostfixOperator(getOperatorString(expression!!.getOperationSign().getTokenType()!!), + getConverter().expressionToExpression(expression?.getOperand())) + } + + public override fun visitPrefixExpression(expression: PsiPrefixExpression?): Unit { + val operand = getConverter().expressionToExpression(expression?.getOperand(), expression?.getOperand()!!.getType()) + val token = expression?.getOperationTokenType()!! + if (token == JavaTokenType.TILDE) { + myResult = DummyMethodCallExpression(ParenthesizedExpression(operand), "inv", Expression.EMPTY_EXPRESSION) + } + else { + myResult = PrefixOperator(getOperatorString(token), operand) + } + } + + public override fun visitReferenceExpression(expression: PsiReferenceExpression?): Unit { + val isFieldReference: Boolean = isFieldReference(expression!!, getContainingClass(expression!!)) + val insideSecondaryConstructor: Boolean = isInsideSecondaryConstructor(expression!!) + val hasReceiver: Boolean = isFieldReference && insideSecondaryConstructor + val isThis: Boolean = isThisExpression(expression!!) + val isNullable: Boolean = getConverter().typeToType(expression?.getType()).nullable + val className: String = getClassNameWithConstructor(expression!!) + var identifier: Expression = Identifier(expression?.getReferenceName(), isNullable) + val __: String? = "__" + if (hasReceiver){ + identifier = CallChainExpression(Identifier(__, false), Identifier(expression?.getReferenceName(), isNullable)) + } + else + if (insideSecondaryConstructor && isThis) { + identifier = Identifier("val __ = " + className) + } + + myResult = CallChainExpression(getConverter().expressionToExpression(expression?.getQualifierExpression()), identifier) + } + + public override fun visitSuperExpression(expression: PsiSuperExpression?): Unit { + val qualifier: PsiJavaCodeReferenceElement? = expression?.getQualifier() + myResult = SuperExpression((if (qualifier != null) + Identifier(qualifier.getQualifiedName()) + else + Identifier.EMPTY_IDENTIFIER)) + } + + public override fun visitThisExpression(expression: PsiThisExpression?): Unit { + val qualifier: PsiJavaCodeReferenceElement? = expression?.getQualifier() + myResult = ThisExpression((if (qualifier != null) + Identifier(qualifier.getQualifiedName()) + else + Identifier.EMPTY_IDENTIFIER)) + } + + public override fun visitTypeCastExpression(expression: PsiTypeCastExpression?): Unit { + val castType: PsiTypeElement? = expression?.getCastType() + if (castType != null) { + myResult = TypeCastExpression(getConverter()?.typeToType(castType.getType()), + getConverter().expressionToExpression(expression?.getOperand())) + } + } + + public override fun visitPolyadicExpression(expression: PsiPolyadicExpression?): Unit { + var parameters: List = ArrayList() + for (operand : PsiExpression? in expression?.getOperands()) { + parameters?.add(getConverter().expressionToExpression(operand, expression?.getType())) + } + myResult = PolyadicExpression(parameters, getOperatorString(expression?.getOperationTokenType()!!)) + } + + class object { + private fun getOperatorString(tokenType: IElementType): String { + if (tokenType == JavaTokenType.PLUS) + return "+" + + if (tokenType == JavaTokenType.MINUS) + return "-" + + if (tokenType == JavaTokenType.ASTERISK) + return "*" + + if (tokenType == JavaTokenType.DIV) + return "/" + + if (tokenType == JavaTokenType.PERC) + return "%" + + if (tokenType == JavaTokenType.GTGT) + return "shr" + + if (tokenType == JavaTokenType.LTLT) + return "shl" + + if (tokenType == JavaTokenType.XOR) + return "xor" + + if (tokenType == JavaTokenType.AND) + return "and" + + if (tokenType == JavaTokenType.OR) + return "or" + + if (tokenType == JavaTokenType.GTGTGT) + return "ushr" + + if (tokenType == JavaTokenType.GT) + return ">" + + if (tokenType == JavaTokenType.LT) + return "<" + + if (tokenType == JavaTokenType.GE) + return ">=" + + if (tokenType == JavaTokenType.LE) + return "<=" + + if (tokenType == JavaTokenType.EQEQ) + return "==" + + if (tokenType == JavaTokenType.NE) + return "!=" + + if (tokenType == JavaTokenType.ANDAND) + return "&&" + + if (tokenType == JavaTokenType.OROR) + return "||" + + if (tokenType == JavaTokenType.PLUSPLUS) + return "++" + + if (tokenType == JavaTokenType.MINUSMINUS) + return "--" + + if (tokenType == JavaTokenType.EXCL) + return "!" + + System.out?.println("UNSUPPORTED TOKEN TYPE: " + tokenType?.toString()) + return "" + } + + private fun getClassNameWithConstructor(expression: PsiReferenceExpression): String { + var context: PsiElement? = expression?.getContext() + while (context != null) { + if (context is PsiMethod && ((context as PsiMethod)).isConstructor()) { + val containingClass: PsiClass? = ((context as PsiMethod)).getContainingClass() + if (containingClass != null) { + val identifier: PsiIdentifier? = containingClass?.getNameIdentifier() + if (identifier != null) { + return identifier.getText()!! + } + + } + + } + + context = context?.getContext() + } + return "" + } + + open fun getClassName(expression: PsiExpression): String { + var context: PsiElement? = expression.getContext() + while (context != null) + { + if ((context is PsiClass?)) { + val containingClass: PsiClass? = (context as PsiClass?) + val identifier: PsiIdentifier? = containingClass?.getNameIdentifier() + if (identifier != null) { + return identifier.getText()!! + } + + } + + context = context?.getContext() + } + return "" + } + + private fun isFieldReference(expression: PsiReferenceExpression, currentClass: PsiClass?): Boolean { + val reference: PsiReference? = expression?.getReference() + if (reference != null) { + val resolvedReference: PsiElement? = reference?.resolve() + if (resolvedReference is PsiField) { + return (resolvedReference as PsiField).getContainingClass() == currentClass + } + } + + return false + } + + private fun isInsideSecondaryConstructor(expression: PsiReferenceExpression): Boolean { + var context: PsiElement? = expression.getContext() + while (context != null) { + if (context is PsiMethod && (context as PsiMethod).isConstructor()) { + return !Converter.isConstructorPrimary((context as PsiMethod)) + } + + context = context?.getContext() + } + return false + } + + private fun isInsidePrimaryConstructor(expression: PsiExpression): Boolean { + var context: PsiElement? = expression.getContext() + while (context != null) { + if (context is PsiMethod && (context as PsiMethod).isConstructor()) { + return Converter.isConstructorPrimary(context as PsiMethod) + } + + context = context?.getContext() + } + return false + } + + private fun getContainingClass(expression: PsiExpression): PsiClass? { + var context: PsiElement? = expression.getContext() + while (context != null) + { + if (context is PsiMethod && (context as PsiMethod).isConstructor()) + { + return (context as PsiMethod).getContainingClass() + } + + context = context?.getContext() + } + return null + } + private fun isThisExpression(expression: PsiReferenceExpression): Boolean { + for (r : PsiReference? in expression.getReferences()) + if (r?.getCanonicalText()?.equals("this")!!) + { + val res: PsiElement? = r?.resolve() + if (res is PsiMethod && res.isConstructor()) { + return true + } + + } + + return false + } + } +} diff --git a/src/org/jetbrains/jet/j2k/visitors/StatementVisitor.java b/src/org/jetbrains/jet/j2k/visitors/StatementVisitor.java deleted file mode 100644 index 6cd0d0b02c2..00000000000 --- a/src/org/jetbrains/jet/j2k/visitors/StatementVisitor.java +++ /dev/null @@ -1,393 +0,0 @@ -/* - * Copyright 2010-2012 JetBrains s.r.o. - * - * 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 org.jetbrains.jet.j2k.visitors; - -import com.intellij.psi.*; -import com.intellij.psi.tree.IElementType; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.j2k.Converter; -import org.jetbrains.jet.j2k.ast.*; - -import java.util.Arrays; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; - -import static org.jetbrains.jet.j2k.ConverterUtil.countWritingAccesses; - -/** - * @author ignatov - */ -public class StatementVisitor extends ElementVisitor { - private Statement myResult = Statement.EMPTY_STATEMENT; - - public StatementVisitor(@NotNull Converter converter) { - super(converter); - } - - @NotNull - @Override - public Statement getResult() { - return myResult; - } - - @Override - public void visitAssertStatement(@NotNull PsiAssertStatement statement) { - super.visitAssertStatement(statement); - myResult = new AssertStatement( - getConverter().expressionToExpression(statement.getAssertCondition()), - getConverter().expressionToExpression(statement.getAssertDescription()) - ); - } - - @Override - public void visitBlockStatement(@NotNull PsiBlockStatement statement) { - super.visitBlockStatement(statement); - myResult = new Block( - getConverter().statementsToStatementList(statement.getCodeBlock().getStatements()), - true - ); - } - - @Override - public void visitBreakStatement(@NotNull PsiBreakStatement statement) { - super.visitBreakStatement(statement); - if (statement.getLabelIdentifier() == null) { - myResult = new BreakStatement(Identifier.EMPTY_IDENTIFIER); - } - else { - myResult = new BreakStatement( - Converter.$classobj.identifierToIdentifier(statement.getLabelIdentifier()) - ); - } - } - - @Override - public void visitContinueStatement(@NotNull PsiContinueStatement statement) { - super.visitContinueStatement(statement); - if (statement.getLabelIdentifier() == null) { - myResult = new ContinueStatement(Identifier.EMPTY_IDENTIFIER); - } - else { - myResult = new ContinueStatement( - Converter.$classobj.identifierToIdentifier(statement.getLabelIdentifier()) - ); - } - } - - @Override - public void visitDeclarationStatement(@NotNull PsiDeclarationStatement statement) { - super.visitDeclarationStatement(statement); - myResult = new DeclarationStatement( - getConverter().elementsToElementList(statement.getDeclaredElements()) - ); - } - - @Override - public void visitDoWhileStatement(@NotNull PsiDoWhileStatement statement) { - super.visitDoWhileStatement(statement); - PsiExpression condition = statement.getCondition(); - @SuppressWarnings("ConstantConditions") - Expression expression = condition != null && condition.getType() != null ? - this.getConverter().expressionToExpression(condition, condition.getType()) : - getConverter().expressionToExpression(condition); - myResult = new DoWhileStatement( - expression, - getConverter().statementToStatement(statement.getBody()) - ); - } - - @Override - public void visitExpressionStatement(@NotNull PsiExpressionStatement statement) { - super.visitExpressionStatement(statement); - myResult = getConverter().expressionToExpression(statement.getExpression()); - } - - @Override - public void visitExpressionListStatement(@NotNull PsiExpressionListStatement statement) { - super.visitExpressionListStatement(statement); - myResult = - new ExpressionListStatement(getConverter().expressionsToExpressionList(statement.getExpressionList().getExpressions())); - } - - @Override - public void visitForStatement(@NotNull PsiForStatement statement) { - super.visitForStatement(statement); - - final PsiStatement initialization = statement.getInitialization(); - final PsiStatement update = statement.getUpdate(); - final PsiExpression condition = statement.getCondition(); - final PsiStatement body = statement.getBody(); - - final PsiLocalVariable firstChild = initialization != null && initialization.getFirstChild() instanceof PsiLocalVariable - ? - (PsiLocalVariable) initialization.getFirstChild() - : null; - - int bodyWriteCount = countWritingAccesses(firstChild, body); - int conditionWriteCount = countWritingAccesses(firstChild, condition); - int updateWriteCount = countWritingAccesses(firstChild, update); - boolean onceWritableIterator = updateWriteCount == 1 && bodyWriteCount + conditionWriteCount == 0; - - final IElementType operationTokenType = condition != null && condition instanceof PsiBinaryExpression ? - ((PsiBinaryExpression) condition).getOperationTokenType() : null; - if ( - initialization != null && - initialization instanceof PsiDeclarationStatement - && initialization.getFirstChild() == initialization.getLastChild() - && condition != null - && update != null - && update.getChildren().length == 1 - && isPlusPlusExpression(update.getChildren()[0]) - && operationTokenType != null - && (operationTokenType == JavaTokenType.LT || operationTokenType == JavaTokenType.LE) - && initialization.getFirstChild() != null - && initialization.getFirstChild() instanceof PsiLocalVariable - && firstChild != null - && firstChild.getNameIdentifier() != null - && onceWritableIterator - ) { - final Expression end = getConverter().expressionToExpression(((PsiBinaryExpression) condition).getROperand()); - final Expression endExpression = operationTokenType == JavaTokenType.LT ? - new BinaryExpression(end, new Identifier("1"), "-") : - end; - myResult = new ForeachWithRangeStatement( - new org.jetbrains.jet.j2k.ast.Identifier(firstChild.getName()), - getConverter().expressionToExpression(firstChild.getInitializer()), - endExpression, - getConverter().statementToStatement(body) - ); - } - else { // common case: while loop instead of for loop - List forStatements = new LinkedList(); - forStatements.add(getConverter().statementToStatement(initialization)); - forStatements.add(new WhileStatement( - getConverter().expressionToExpression(condition), - new Block( - Arrays.asList(getConverter().statementToStatement(body), - new Block(Arrays.asList(getConverter().statementToStatement(update)), false)), false))); - myResult = new Block(forStatements, false); - } - } - - private static boolean isPlusPlusExpression(@NotNull PsiElement psiElement) { - return (psiElement instanceof PsiPostfixExpression && ((PsiPostfixExpression) psiElement).getOperationTokenType() == JavaTokenType.PLUSPLUS) - || (psiElement instanceof PsiPrefixExpression && ((PsiPrefixExpression) psiElement).getOperationTokenType() == JavaTokenType.PLUSPLUS); - } - - @Override - public void visitForeachStatement(@NotNull PsiForeachStatement statement) { - super.visitForeachStatement(statement); - myResult = new ForeachStatement( - getConverter().parameterToParameter(statement.getIterationParameter()), - getConverter().expressionToExpression(statement.getIteratedValue()), - getConverter().statementToStatement(statement.getBody()) - ); - } - - @Override - public void visitIfStatement(@NotNull PsiIfStatement statement) { - super.visitIfStatement(statement); - PsiExpression condition = statement.getCondition(); - @SuppressWarnings("ConstantConditions") - Expression expression = getConverter().expressionToExpression(condition, PsiType.BOOLEAN); - myResult = new IfStatement( - expression, - getConverter().statementToStatement(statement.getThenBranch()), - getConverter().statementToStatement(statement.getElseBranch()) - ); - } - - @Override - public void visitLabeledStatement(@NotNull PsiLabeledStatement statement) { - super.visitLabeledStatement(statement); - myResult = new LabelStatement( - Converter.$classobj.identifierToIdentifier(statement.getLabelIdentifier()), - getConverter().statementToStatement(statement.getStatement()) - ); - } - - @Override - public void visitSwitchLabelStatement(@NotNull PsiSwitchLabelStatement statement) { - super.visitSwitchLabelStatement(statement); - myResult = statement.isDefaultCase() ? - new DefaultSwitchLabelStatement() : - new SwitchLabelStatement(getConverter().expressionToExpression(statement.getCaseValue())); - } - - @Override - public void visitSwitchStatement(@NotNull PsiSwitchStatement statement) { - super.visitSwitchStatement(statement); - myResult = new SwitchContainer( - getConverter().expressionToExpression(statement.getExpression()), - switchBodyToCases(statement.getBody()) - ); - } - - @NotNull - private List switchBodyToCases(@Nullable final PsiCodeBlock body) { - final List> cases = splitToCases(body); - final List allSwitchStatements = body != null - ? Arrays.asList(body.getStatements()) - : Collections.emptyList(); - - List result = new LinkedList(); - List pendingLabels = new LinkedList(); - int i = 0; - for (List ls : cases) { - assert ls.size() > 0; - PsiStatement label = ls.get(0); - assert label instanceof PsiSwitchLabelStatement; - - assert allSwitchStatements.get(i) == label : "not a right index"; - - if (ls.size() > 1) { - pendingLabels.add(getConverter().statementToStatement(label)); - List slice = ls.subList(1, ls.size()); - - if (!containsBreak(slice)) { - List statements = getConverter().statementsToStatementList(slice); - statements.addAll( - getConverter().statementsToStatementList(getAllToNextBreak(allSwitchStatements, i + ls.size())) - ); - result.add(new CaseContainer(pendingLabels, statements)); - pendingLabels = new LinkedList(); - } - else { - result.add(new CaseContainer(pendingLabels, getConverter().statementsToStatementList(slice))); - pendingLabels = new LinkedList(); - } - } - else // ls.size() == 1 - { - pendingLabels.add(getConverter().statementToStatement(label)); - } - i += ls.size(); - } - return result; - } - - private static boolean containsBreak(@NotNull final List slice) { - for (PsiStatement s : slice) - if (s instanceof PsiBreakStatement) { - return true; - } - return false; - } - - @NotNull - private static List getAllToNextBreak(@NotNull final List allStatements, final int start) { - List result = new LinkedList(); - for (int i = start; i < allStatements.size(); i++) { - PsiStatement s = allStatements.get(i); - if (s instanceof PsiBreakStatement || s instanceof PsiReturnStatement) { - return result; - } - if (!(s instanceof PsiSwitchLabelStatement)) { - result.add(s); - } - } - return result; - } - - @NotNull - private static List> splitToCases(@Nullable final PsiCodeBlock body) { - List> cases = new LinkedList>(); - List currentCaseStatements = new LinkedList(); - boolean isFirst = true; - if (body != null) { - for (PsiStatement s : body.getStatements()) { - if (s instanceof PsiSwitchLabelStatement) { - if (isFirst) { - isFirst = false; - } - else { - cases.add(currentCaseStatements); - currentCaseStatements = new LinkedList(); - } - } - currentCaseStatements.add(s); - } - cases.add(currentCaseStatements); - } - return cases; - } - - @Override - public void visitSynchronizedStatement(@NotNull PsiSynchronizedStatement statement) { - super.visitSynchronizedStatement(statement); - myResult = new SynchronizedStatement( - getConverter().expressionToExpression(statement.getLockExpression()), - getConverter().blockToBlock(statement.getBody()) - ); - } - - @Override - public void visitThrowStatement(@NotNull PsiThrowStatement statement) { - super.visitThrowStatement(statement); - myResult = new ThrowStatement( - getConverter().expressionToExpression(statement.getException()) - ); - } - - @Override - public void visitTryStatement(@NotNull PsiTryStatement statement) { - super.visitTryStatement(statement); - - List catches = new LinkedList(); - for (int i = 0; i < statement.getCatchBlocks().length; i++) { - catches.add(new CatchStatement( - getConverter().parameterToParameter(statement.getCatchBlockParameters()[i]), - getConverter().blockToBlock(statement.getCatchBlocks()[i], true) - )); - } - - myResult = new TryStatement( - getConverter().blockToBlock(statement.getTryBlock(), true), - catches, - getConverter().blockToBlock(statement.getFinallyBlock(), true) - ); - } - - @Override - public void visitWhileStatement(@NotNull PsiWhileStatement statement) { - super.visitWhileStatement(statement); - PsiExpression condition = statement.getCondition(); - @SuppressWarnings("ConstantConditions") - Expression expression = condition != null && condition.getType() != null ? - this.getConverter().expressionToExpression(condition, condition.getType()) : - getConverter().expressionToExpression(condition); - myResult = new WhileStatement( - expression, - getConverter().statementToStatement(statement.getBody()) - ); - } - - @Override - public void visitReturnStatement(@NotNull PsiReturnStatement statement) { - super.visitReturnStatement(statement); - PsiExpression returnValue = statement.getReturnValue(); - PsiType methodReturnType = getConverter().getMethodReturnType(); - Expression expression = returnValue != null && methodReturnType != null ? - this.getConverter().expressionToExpression(returnValue, methodReturnType) : - getConverter().expressionToExpression(returnValue); - myResult = new ReturnStatement( - expression - ); - } -} diff --git a/src/org/jetbrains/jet/j2k/visitors/StatementVisitor.kt b/src/org/jetbrains/jet/j2k/visitors/StatementVisitor.kt new file mode 100644 index 00000000000..2b489a58743 --- /dev/null +++ b/src/org/jetbrains/jet/j2k/visitors/StatementVisitor.kt @@ -0,0 +1,278 @@ +package org.jetbrains.jet.j2k.visitors + +import com.intellij.psi.* +import com.intellij.psi.tree.IElementType +import org.jetbrains.annotations.Nullable +import org.jetbrains.jet.j2k.Converter +import org.jetbrains.jet.j2k.ast.* +import java.util.Arrays +import java.util.Collections +import java.util.LinkedList +import java.util.List +import org.jetbrains.jet.j2k.ConverterUtil.countWritingAccesses + +public open class StatementVisitor(converter: Converter): ElementVisitor(converter) { + private var myResult: Statement = Statement.EMPTY_STATEMENT + public override fun getResult(): Statement { + return myResult + } + + public override fun visitAssertStatement(statement: PsiAssertStatement?): Unit { + myResult = AssertStatement(getConverter().expressionToExpression(statement?.getAssertCondition()), + getConverter().expressionToExpression(statement?.getAssertDescription())) + } + + public override fun visitBlockStatement(statement: PsiBlockStatement?): Unit { + myResult = Block(getConverter().statementsToStatementList(statement?.getCodeBlock()?.getStatements().requireNoNulls()), true) + } + + public override fun visitBreakStatement(statement: PsiBreakStatement?): Unit { + if (statement?.getLabelIdentifier() == null) { + myResult = BreakStatement(Identifier.EMPTY_IDENTIFIER) + } + else + { + myResult = BreakStatement(Converter.identifierToIdentifier(statement?.getLabelIdentifier())) + } + } + + public override fun visitContinueStatement(statement: PsiContinueStatement?): Unit { + if (statement?.getLabelIdentifier() == null) + { + myResult = ContinueStatement(Identifier.EMPTY_IDENTIFIER) + } + else + { + myResult = ContinueStatement(Converter.identifierToIdentifier(statement?.getLabelIdentifier())) + } + } + + public override fun visitDeclarationStatement(statement: PsiDeclarationStatement?): Unit { + myResult = DeclarationStatement(getConverter().elementsToElementList(statement?.getDeclaredElements()!!)) + } + + public override fun visitDoWhileStatement(statement: PsiDoWhileStatement?): Unit { + val condition: PsiExpression? = statement?.getCondition() + val expression: Expression = (if (condition != null && condition.getType() != null) + getConverter().expressionToExpression(condition, condition.getType()) + else + getConverter().expressionToExpression(condition)) + myResult = DoWhileStatement(expression, getConverter().statementToStatement(statement?.getBody())) + } + + public override fun visitExpressionStatement(statement: PsiExpressionStatement?): Unit { + myResult = getConverter().expressionToExpression(statement?.getExpression()) + } + + public override fun visitExpressionListStatement(statement: PsiExpressionListStatement?): Unit { + myResult = ExpressionListStatement(getConverter().expressionsToExpressionList( + statement?.getExpressionList()?.getExpressions()!!)) + } + + public override fun visitForStatement(statement: PsiForStatement?): Unit { + val initialization: PsiStatement? = statement?.getInitialization() + val update: PsiStatement? = statement?.getUpdate() + val condition: PsiExpression? = statement?.getCondition() + val body: PsiStatement? = statement?.getBody() + val firstChild: PsiLocalVariable? = (if (initialization != null && (initialization.getFirstChild() is PsiLocalVariable)) + (initialization.getFirstChild() as PsiLocalVariable) + else + null) + var bodyWriteCount: Int = countWritingAccesses(firstChild, body) + var conditionWriteCount: Int = countWritingAccesses(firstChild, condition) + var updateWriteCount: Int = countWritingAccesses(firstChild, update) + val onceWritableIterator: Boolean = updateWriteCount == 1 && bodyWriteCount + conditionWriteCount == 0 + val operationTokenType: IElementType? = (if (condition is PsiBinaryExpression) + condition.getOperationTokenType() + else + null) + if (initialization is PsiDeclarationStatement && initialization.getFirstChild() == initialization.getLastChild() && + condition != null && update != null && update.getChildren().size == 1 && + (isPlusPlusExpression(update.getChildren()[0]!!)) && (operationTokenType == JavaTokenType.LT || operationTokenType == JavaTokenType.LE) && + initialization.getFirstChild() != null && (initialization.getFirstChild() is PsiLocalVariable) && + firstChild != null && firstChild.getNameIdentifier() != null && onceWritableIterator) { + val end: Expression = getConverter().expressionToExpression((condition as PsiBinaryExpression).getROperand()) + val endExpression: Expression = (if (operationTokenType == JavaTokenType.LT) + BinaryExpression(end, Identifier("1"), "-") + else + end) + myResult = ForeachWithRangeStatement(Identifier(firstChild.getName()), + getConverter().expressionToExpression(firstChild.getInitializer()), + endExpression, + getConverter().statementToStatement(body)) + } + else { + var forStatements: List = arrayList() + forStatements.add(getConverter().statementToStatement(initialization)) + forStatements.add(WhileStatement(getConverter().expressionToExpression(condition), + Block(arrayList(getConverter().statementToStatement(body), + Block(arrayList(getConverter().statementToStatement(update)), false)), false))) + myResult = Block(forStatements, false) + } + } + + public override fun visitForeachStatement(statement: PsiForeachStatement?): Unit { + myResult = ForeachStatement(getConverter().parameterToParameter(statement?.getIterationParameter()!!), + getConverter().expressionToExpression(statement?.getIteratedValue()), + getConverter().statementToStatement(statement?.getBody())) + } + + public override fun visitIfStatement(statement: PsiIfStatement?): Unit { + val condition: PsiExpression? = statement?.getCondition() + val expression: Expression = getConverter().expressionToExpression(condition, PsiType.BOOLEAN) + myResult = IfStatement(expression, + getConverter().statementToStatement(statement?.getThenBranch()), + getConverter().statementToStatement(statement?.getElseBranch())) + } + + public override fun visitLabeledStatement(statement: PsiLabeledStatement?): Unit { + myResult = LabelStatement(Converter.identifierToIdentifier(statement?.getLabelIdentifier()), + getConverter().statementToStatement(statement?.getStatement())) + } + + public override fun visitSwitchLabelStatement(statement: PsiSwitchLabelStatement?): Unit { + myResult = (if (statement?.isDefaultCase().sure()) + DefaultSwitchLabelStatement() + else + SwitchLabelStatement(getConverter().expressionToExpression(statement?.getCaseValue()))) + } + + public override fun visitSwitchStatement(statement: PsiSwitchStatement?): Unit { + myResult = SwitchContainer(getConverter().expressionToExpression(statement?.getExpression()), + switchBodyToCases(statement?.getBody())) + } + + private open fun switchBodyToCases(body: PsiCodeBlock?): List { + val cases: List> = splitToCases(body) + val allSwitchStatements: List = arrayList() + if (body != null) { + // TODO Arrays.asList() + for(s in body.getStatements()) allSwitchStatements.add(s) + } + val result: List = arrayList() + var pendingLabels: List = arrayList() + var i: Int = 0 + for (ls : List in cases) { + // TODO assert {(ls?.size()).sure() > 0} + var label: PsiStatement? = ls[0] + // TODO assert {(label is PsiSwitchLabelStatement?)} + // TODO assert("not a right index") {allSwitchStatements?.get(i) == label} + if (ls.size() > 1) { + pendingLabels.add(getConverter().statementToStatement(label)) + val slice: List = ls.subList(1, (ls.size())) + if (!containsBreak(slice)) { + val statements = getConverter().statementsToStatementList(slice) + statements.addAll(getConverter().statementsToStatementList(getAllToNextBreak(allSwitchStatements, i + ls.size()))) + result.add(CaseContainer(pendingLabels, statements)) + pendingLabels = arrayList() + } + else { + result.add(CaseContainer(pendingLabels, getConverter().statementsToStatementList(slice))) + pendingLabels = arrayList() + } + } + else { + pendingLabels.add(getConverter().statementToStatement(label)) + } + i += ls.size() + } + return result + } + + public override fun visitSynchronizedStatement(statement: PsiSynchronizedStatement?): Unit { + myResult = SynchronizedStatement(getConverter().expressionToExpression(statement?.getLockExpression()), + getConverter().blockToBlock(statement?.getBody())) + } + + public override fun visitThrowStatement(statement: PsiThrowStatement?): Unit { + myResult = ThrowStatement(getConverter().expressionToExpression(statement?.getException())) + } + + public override fun visitTryStatement(statement: PsiTryStatement?): Unit { + val catches: List = arrayList() + val catchBlocks = statement?.getCatchBlocks()!! + val catchBlockParameters = statement?.getCatchBlockParameters()!! + for (i in 0..catchBlocks.size - 1) { + catches.add(CatchStatement(getConverter().parameterToParameter(catchBlockParameters[i]!!), + getConverter().blockToBlock(catchBlocks[i], true))) + } + myResult = TryStatement(getConverter().blockToBlock(statement?.getTryBlock(), true), + catches, getConverter().blockToBlock(statement?.getFinallyBlock(), true)) + } + + public override fun visitWhileStatement(statement: PsiWhileStatement?): Unit { + var condition: PsiExpression? = statement?.getCondition() + val expression: Expression = (if (condition != null && condition?.getType() != null) + this.getConverter().expressionToExpression(condition, condition?.getType()) + else + getConverter().expressionToExpression(condition)) + myResult = WhileStatement(expression, getConverter().statementToStatement(statement?.getBody())) + } + + public override fun visitReturnStatement(statement: PsiReturnStatement?): Unit { + val returnValue: PsiExpression? = statement?.getReturnValue() + val methodReturnType: PsiType? = getConverter().getMethodReturnType() + val expression: Expression = (if (returnValue != null && methodReturnType != null) + this.getConverter().expressionToExpression(returnValue, methodReturnType) + else + getConverter().expressionToExpression(returnValue)) + myResult = ReturnStatement(expression) + } + + class object { + private open fun isPlusPlusExpression(psiElement: PsiElement): Boolean { + return (psiElement is PsiPostfixExpression && psiElement.getOperationTokenType() == JavaTokenType.PLUSPLUS) || + (psiElement is PsiPrefixExpression && psiElement.getOperationTokenType() == JavaTokenType.PLUSPLUS) + } + + private open fun containsBreak(slice: List): Boolean { + for (s : PsiStatement? in slice) + if ((s is PsiBreakStatement?)) + { + return true + } + + return false + } + + private open fun getAllToNextBreak(allStatements: List, start: Int): List { + var result: List = LinkedList() + for (i in start..allStatements.size() - 1) { + var s: PsiStatement? = allStatements.get(i) + if (s is PsiBreakStatement || s is PsiReturnStatement) { + return result + } + + if (!(s is PsiSwitchLabelStatement)) { + result.add(s) + } + + } + return result + } + + private open fun splitToCases(body: PsiCodeBlock?): List> { + val cases: List> = arrayList() + var currentCaseStatements: List = arrayList() + var isFirst: Boolean = true + if (body != null) { + for (s : PsiStatement? in body.getStatements()) { + if ((s is PsiSwitchLabelStatement?)) { + if (isFirst) { + isFirst = false + } + else { + cases.add(currentCaseStatements) + currentCaseStatements = LinkedList() + } + } + + currentCaseStatements.add(s) + } + cases.add(currentCaseStatements) + } + + return cases + } + } +} diff --git a/src/org/jetbrains/jet/j2k/visitors/TypeVisitor.kt b/src/org/jetbrains/jet/j2k/visitors/TypeVisitor.kt index 2af718eb647..d3732e9fc53 100644 --- a/src/org/jetbrains/jet/j2k/visitors/TypeVisitor.kt +++ b/src/org/jetbrains/jet/j2k/visitors/TypeVisitor.kt @@ -46,7 +46,7 @@ public open class TypeVisitor(private val myConverter : Converter) : PsiTypeVisi myResult = ClassType(identifier, resolvedClassTypeParams, true) } else { - myResult = ClassType(identifier, myConverter.typesToTypeList(classType.getParameters()).requireNoNulls(), true) + myResult = ClassType(identifier, myConverter.typesToTypeList(classType.getParameters()), true) } return myResult } @@ -89,7 +89,7 @@ public open class TypeVisitor(private val myConverter : Converter) : PsiTypeVisi val superTypes = p!!.getSuperTypes() val boundType : Type = (if (superTypes.size > 0) ClassType(Identifier(getClassTypeName(superTypes[0]!!)), - myConverter.typesToTypeList(superTypes[0]!!.getParameters()).requireNoNulls(), + myConverter.typesToTypeList(superTypes[0]!!.getParameters()), true) else StarProjectionType())