converted to kotlin; doesn't compile yet because of errors in frontend

This commit is contained in:
Dmitry Jemerov
2012-05-30 20:57:31 +02:00
committed by Pavel V. Talanov
parent c9499da055
commit b17effd3a3
11 changed files with 765 additions and 1002 deletions
+1 -1
View File
@@ -351,7 +351,7 @@ public open class Converter() {
return typeVisitor.getResult()
}
public open fun typesToTypeList(types: Array<PsiType?>): List<Type?> {
public open fun typesToTypeList(types: Array<PsiType?>): List<Type> {
return types.map { typeToType(it) }
}
@@ -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<Expression> myArguments;
private Expression myQualifier;
@Nullable
private AnonymousClass myAnonymousClass = null;
private NewClassExpression(Element name, List<Expression> arguments) {
myName = name;
myQualifier = EMPTY_EXPRESSION;
myArguments = arguments;
}
public NewClassExpression(@NotNull Element name, @NotNull List<Expression> 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 + ")";
}
}
@@ -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<Expression>,
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 + ")")
}
}
@@ -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()
}
@@ -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();
}
}
@@ -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<Type> = myConverter.typesToTypeList(theReference.getTypeParameters()).requireNoNulls()
val types : List<Type> = myConverter.typesToTypeList(theReference.getTypeParameters())
if (!theReference.isQualified()) {
myResult = ReferenceElement(Identifier(theReference.getReferenceName()), types)
}
@@ -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<Type> typeParameters = reference != null
? getConverter().typesToTypeList(reference.getTypeParameters())
: Collections.<Type>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<Expression> parameters = new ArrayList<Expression>();
for (PsiExpression operand : expression.getOperands()) {
parameters.add(getConverter().expressionToExpression(operand, expression.getType()));
}
myResult = new PolyadicExpression(
parameters,
getOperatorString(expression.getOperationTokenType())
);
}
}
@@ -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<PsiExpression?> = (if (argumentList != null)
argumentList?.getExpressions()!!
else
array<PsiExpression?>())
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<Type> = (if (reference != null)
getConverter().typesToTypeList(reference.getTypeParameters())
else
Collections.emptyList<Type>()!!)
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<Expression> = ArrayList<Expression>()
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
}
}
}
@@ -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<Statement> forStatements = new LinkedList<Statement>();
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<CaseContainer> switchBodyToCases(@Nullable final PsiCodeBlock body) {
final List<List<PsiStatement>> cases = splitToCases(body);
final List<PsiStatement> allSwitchStatements = body != null
? Arrays.asList(body.getStatements())
: Collections.<PsiStatement>emptyList();
List<CaseContainer> result = new LinkedList<CaseContainer>();
List<Statement> pendingLabels = new LinkedList<Statement>();
int i = 0;
for (List<PsiStatement> 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<PsiStatement> slice = ls.subList(1, ls.size());
if (!containsBreak(slice)) {
List<Statement> statements = getConverter().statementsToStatementList(slice);
statements.addAll(
getConverter().statementsToStatementList(getAllToNextBreak(allSwitchStatements, i + ls.size()))
);
result.add(new CaseContainer(pendingLabels, statements));
pendingLabels = new LinkedList<Statement>();
}
else {
result.add(new CaseContainer(pendingLabels, getConverter().statementsToStatementList(slice)));
pendingLabels = new LinkedList<Statement>();
}
}
else // ls.size() == 1
{
pendingLabels.add(getConverter().statementToStatement(label));
}
i += ls.size();
}
return result;
}
private static boolean containsBreak(@NotNull final List<PsiStatement> slice) {
for (PsiStatement s : slice)
if (s instanceof PsiBreakStatement) {
return true;
}
return false;
}
@NotNull
private static List<PsiStatement> getAllToNextBreak(@NotNull final List<PsiStatement> allStatements, final int start) {
List<PsiStatement> result = new LinkedList<PsiStatement>();
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<List<PsiStatement>> splitToCases(@Nullable final PsiCodeBlock body) {
List<List<PsiStatement>> cases = new LinkedList<List<PsiStatement>>();
List<PsiStatement> currentCaseStatements = new LinkedList<PsiStatement>();
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<PsiStatement>();
}
}
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<CatchStatement> catches = new LinkedList<CatchStatement>();
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
);
}
}
@@ -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<Statement> = 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<CaseContainer> {
val cases: List<List<PsiStatement?>> = splitToCases(body)
val allSwitchStatements: List<PsiStatement?> = arrayList()
if (body != null) {
// TODO Arrays.asList()
for(s in body.getStatements()) allSwitchStatements.add(s)
}
val result: List<CaseContainer> = arrayList()
var pendingLabels: List<Statement> = arrayList()
var i: Int = 0
for (ls : List<PsiStatement?> 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<PsiStatement?> = 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<CatchStatement> = 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<PsiStatement?>): Boolean {
for (s : PsiStatement? in slice)
if ((s is PsiBreakStatement?))
{
return true
}
return false
}
private open fun getAllToNextBreak(allStatements: List<PsiStatement?>, start: Int): List<PsiStatement?> {
var result: List<PsiStatement?> = LinkedList<PsiStatement?>()
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<List<PsiStatement?>> {
val cases: List<List<PsiStatement?>> = arrayList()
var currentCaseStatements: List<PsiStatement?> = 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<PsiStatement?>()
}
}
currentCaseStatements.add(s)
}
cases.add(currentCaseStatements)
}
return cases
}
}
}
@@ -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())