convert the converter
This commit is contained in:
committed by
Pavel V. Talanov
parent
2cd137b0ae
commit
ae4404cdc4
@@ -1,791 +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;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
import com.intellij.psi.*;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.jetbrains.jet.j2k.ast.*;
|
|
||||||
import org.jetbrains.jet.j2k.ast.Class;
|
|
||||||
import org.jetbrains.jet.j2k.ast.Enum;
|
|
||||||
import org.jetbrains.jet.j2k.ast.types.ClassType;
|
|
||||||
import org.jetbrains.jet.j2k.ast.types.EmptyType;
|
|
||||||
import org.jetbrains.jet.j2k.ast.types.Type;
|
|
||||||
import org.jetbrains.jet.j2k.util.AstUtil;
|
|
||||||
import org.jetbrains.jet.j2k.visitors.*;
|
|
||||||
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import static org.jetbrains.jet.j2k.ConverterUtil.countWritingAccesses;
|
|
||||||
import static org.jetbrains.jet.j2k.ConverterUtil.createMainFunction;
|
|
||||||
import static com.intellij.psi.CommonClassNames.*;
|
|
||||||
import static org.jetbrains.jet.lang.types.expressions.OperatorConventions.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ignatov
|
|
||||||
*/
|
|
||||||
public class Converter {
|
|
||||||
@NotNull
|
|
||||||
public static final Set<String> NOT_NULL_ANNOTATIONS = ImmutableSet.of(
|
|
||||||
"org.jetbrains.annotations.NotNull",
|
|
||||||
"com.sun.istack.internal.NotNull",
|
|
||||||
"javax.annotation.Nonnull"
|
|
||||||
);
|
|
||||||
|
|
||||||
private static final Map<String, String> PRIMITIVE_TYPE_CONVERSIONS = ImmutableMap.<String, String>builder()
|
|
||||||
.put("byte", BYTE)
|
|
||||||
.put("short", SHORT)
|
|
||||||
.put("int", INT)
|
|
||||||
.put("long", LONG)
|
|
||||||
.put("float", FLOAT)
|
|
||||||
.put("double", DOUBLE)
|
|
||||||
.put("char", CHAR)
|
|
||||||
|
|
||||||
.put(JAVA_LANG_BYTE, BYTE)
|
|
||||||
.put(JAVA_LANG_SHORT, SHORT)
|
|
||||||
.put(JAVA_LANG_INTEGER, INT)
|
|
||||||
.put(JAVA_LANG_LONG, LONG)
|
|
||||||
.put(JAVA_LANG_FLOAT, FLOAT)
|
|
||||||
.put(JAVA_LANG_DOUBLE, DOUBLE)
|
|
||||||
.put(JAVA_LANG_CHARACTER, CHAR)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private Set<String> classIdentifiers = Sets.newHashSet();
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private final Dispatcher dispatcher = new Dispatcher(this);
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private PsiType methodReturnType = null;
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private final Set<J2KConverterFlags> flags = Sets.newHashSet();
|
|
||||||
|
|
||||||
public Converter() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean addFlag(@NotNull J2KConverterFlags flag) {
|
|
||||||
return flags.add(flag);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasFlag(@NotNull J2KConverterFlags flag) {
|
|
||||||
return flags.contains(flag);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setClassIdentifiers(@NotNull Set<String> identifiers) {
|
|
||||||
classIdentifiers = identifiers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public Set<String> getClassIdentifiers() {
|
|
||||||
return Collections.unmodifiableSet(classIdentifiers);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public PsiType getMethodReturnType() {
|
|
||||||
return methodReturnType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clearClassIdentifiers() {
|
|
||||||
classIdentifiers.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public String elementToKotlin(@NotNull PsiElement element) {
|
|
||||||
if (element instanceof PsiJavaFile) {
|
|
||||||
return fileToFile((PsiJavaFile) element).toKotlin();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (element instanceof PsiClass) {
|
|
||||||
return classToClass((PsiClass) element).toKotlin();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (element instanceof PsiMethod) {
|
|
||||||
return methodToFunction((PsiMethod) element).toKotlin();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (element instanceof PsiField) {
|
|
||||||
PsiField field = (PsiField) element;
|
|
||||||
return fieldToField(field, field.getContainingClass()).toKotlin();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (element instanceof PsiStatement) {
|
|
||||||
return statementToStatement((PsiStatement) element).toKotlin();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (element instanceof PsiExpression) {
|
|
||||||
return expressionToExpression((PsiExpression) element).toKotlin();
|
|
||||||
}
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public File fileToFile(@NotNull PsiJavaFile javaFile) {
|
|
||||||
return fileToFile(javaFile, Collections.<String>emptyList());
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public File fileToFileWithCompatibilityImport(@NotNull PsiJavaFile javaFile) {
|
|
||||||
return fileToFile(javaFile, Collections.singletonList("kotlin.compatibility.*"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private File fileToFile(PsiJavaFile javaFile, List<String> additionalImports) {
|
|
||||||
final PsiImportList importList = javaFile.getImportList();
|
|
||||||
List<Import> imports = importList == null
|
|
||||||
? Collections.<Import>emptyList()
|
|
||||||
: importsToImportList(importList.getAllImportStatements());
|
|
||||||
for (String i : additionalImports)
|
|
||||||
imports.add(new Import(i));
|
|
||||||
return new File(quoteKeywords(javaFile.getPackageName()), imports, classesToClassList(javaFile.getClasses()), createMainFunction(javaFile));
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private static String quoteKeywords(@NotNull String packageName) {
|
|
||||||
List<String> result = new LinkedList<String>();
|
|
||||||
for (String part : packageName.split("\\."))
|
|
||||||
result.add(new IdentifierImpl(part).toKotlin());
|
|
||||||
return AstUtil.join(result, ".");
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private List<Class> classesToClassList(@NotNull PsiClass[] classes) {
|
|
||||||
List<Class> result = new LinkedList<Class>();
|
|
||||||
for (PsiClass t : classes) result.add(classToClass(t));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public AnonymousClass anonymousClassToAnonymousClass(@NotNull PsiAnonymousClass anonymousClass) {
|
|
||||||
return new AnonymousClass(this, getMembers(anonymousClass));
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private List<Member> getMembers(@NotNull PsiClass psiClass) {
|
|
||||||
List<Member> members = new LinkedList<Member>();
|
|
||||||
for (PsiElement e : psiClass.getChildren()) {
|
|
||||||
if (e instanceof PsiMethod) {
|
|
||||||
members.add(methodToFunction((PsiMethod) e, true));
|
|
||||||
}
|
|
||||||
else if (e instanceof PsiField) {
|
|
||||||
members.add(fieldToField((PsiField) e, psiClass));
|
|
||||||
}
|
|
||||||
else if (e instanceof PsiClass) {
|
|
||||||
members.add(classToClass((PsiClass) e));
|
|
||||||
}
|
|
||||||
else if (e instanceof PsiClassInitializer) {
|
|
||||||
members.add(initializerToInitializer((PsiClassInitializer) e));
|
|
||||||
}
|
|
||||||
else if (e instanceof PsiMember) System.out.println(e.getClass() + " " + e.getText());
|
|
||||||
}
|
|
||||||
return members;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private static List<Field> getFinalOrWithEmptyInitializer(@NotNull List<? extends Field> fields) {
|
|
||||||
List<Field> result = new LinkedList<Field>();
|
|
||||||
for (Field f : fields)
|
|
||||||
if (f.isVal() || f.getInitializer().toKotlin().isEmpty()) {
|
|
||||||
result.add(f);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private static List<Parameter> createParametersFromFields(@NotNull List<? extends Field> fields) {
|
|
||||||
List<Parameter> result = new LinkedList<Parameter>();
|
|
||||||
for (Field f : fields)
|
|
||||||
result.add(new Parameter(new IdentifierImpl("_" + f.getIdentifier().getName()), f.getType(), true));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private static List<Statement> createInitStatementsFromFields(@NotNull List<? extends Field> fields) {
|
|
||||||
List<Statement> result = new LinkedList<Statement>();
|
|
||||||
for (Field f : fields) {
|
|
||||||
final String identifierToKotlin = f.getIdentifier().toKotlin();
|
|
||||||
result.add(new DummyStringExpression(identifierToKotlin + " = " + "_" + identifierToKotlin));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private static String createPrimaryConstructorInvocation(@NotNull String s, @NotNull List<? extends Field> fields, @NotNull Map<String, String> initializers) {
|
|
||||||
List<String> result = new LinkedList<String>();
|
|
||||||
for (Field f : fields) {
|
|
||||||
final String id = f.getIdentifier().toKotlin();
|
|
||||||
result.add(initializers.get(id));
|
|
||||||
}
|
|
||||||
return s + "(" + AstUtil.join(result, ", ") + ")";
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private Class classToClass(@NotNull PsiClass psiClass) {
|
|
||||||
final Set<String> modifiers = modifiersListToModifiersSet(psiClass.getModifierList());
|
|
||||||
final List<Field> fields = fieldsToFieldList(psiClass.getFields(), psiClass);
|
|
||||||
final List<Element> typeParameters = elementsToElementList(psiClass.getTypeParameters());
|
|
||||||
final List<Type> implementsTypes = typesToNotNullableTypeList(psiClass.getImplementsListTypes());
|
|
||||||
final List<Type> extendsTypes = typesToNotNullableTypeList(psiClass.getExtendsListTypes());
|
|
||||||
final IdentifierImpl name = new IdentifierImpl(psiClass.getName());
|
|
||||||
final List<Expression> baseClassParams = new LinkedList<Expression>();
|
|
||||||
|
|
||||||
List<Member> members = getMembers(psiClass);
|
|
||||||
|
|
||||||
// we try to find super() call and generate class declaration like that: class A(name: String, i : Int) : Base(name)
|
|
||||||
final SuperVisitor visitor = new SuperVisitor();
|
|
||||||
psiClass.accept(visitor);
|
|
||||||
final HashSet<PsiExpressionList> resolvedSuperCallParameters = visitor.getResolvedSuperCallParameters();
|
|
||||||
if (resolvedSuperCallParameters.size() == 1) {
|
|
||||||
baseClassParams.addAll(
|
|
||||||
expressionsToExpressionList(
|
|
||||||
resolvedSuperCallParameters.toArray(new PsiExpressionList[1])[0].getExpressions()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// we create primary constructor from all non final fields and fields without initializers
|
|
||||||
if (!psiClass.isEnum() && !psiClass.isInterface() && psiClass.getConstructors().length > 1 && getPrimaryConstructorForThisCase(psiClass) == null) {
|
|
||||||
final List<Field> finalOrWithEmptyInitializer = getFinalOrWithEmptyInitializer(fields);
|
|
||||||
final Map<String, String> initializers = new HashMap<String, String>();
|
|
||||||
|
|
||||||
for (final Member m : members) {
|
|
||||||
// and modify secondaries
|
|
||||||
if (m.getKind() == INode.Kind.CONSTRUCTOR) {
|
|
||||||
Function f = (Function) m;
|
|
||||||
if (!((Constructor) f).getIsPrimary()) {
|
|
||||||
for (Field fo : finalOrWithEmptyInitializer) {
|
|
||||||
String init = getDefaultInitializer(fo);
|
|
||||||
initializers.put(fo.getIdentifier().toKotlin(), init);
|
|
||||||
}
|
|
||||||
|
|
||||||
final List<Statement> newStatements = new LinkedList<Statement>();
|
|
||||||
|
|
||||||
for (Statement s : f.getBlock().getStatements()) {
|
|
||||||
boolean isRemoved = false;
|
|
||||||
|
|
||||||
if (s.getKind() == INode.Kind.ASSIGNMENT_EXPRESSION) {
|
|
||||||
final AssignmentExpression assignmentExpression = (AssignmentExpression) s;
|
|
||||||
if (assignmentExpression.getLeft().getKind() == INode.Kind.CALL_CHAIN) {
|
|
||||||
for (Field fo : finalOrWithEmptyInitializer) {
|
|
||||||
final String id = fo.getIdentifier().toKotlin();
|
|
||||||
if (((CallChainExpression) assignmentExpression.getLeft()).getIdentifier().toKotlin().endsWith("." + id)) {
|
|
||||||
initializers.put(id, assignmentExpression.getRight().toKotlin());
|
|
||||||
isRemoved = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!isRemoved) {
|
|
||||||
newStatements.add(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
newStatements.add(
|
|
||||||
0,
|
|
||||||
new DummyStringExpression(
|
|
||||||
"val __ = " + createPrimaryConstructorInvocation(
|
|
||||||
name.toKotlin(),
|
|
||||||
finalOrWithEmptyInitializer,
|
|
||||||
initializers)));
|
|
||||||
|
|
||||||
f.setBlock(new Block(newStatements));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
members.add(
|
|
||||||
new Constructor(
|
|
||||||
Identifier.EMPTY_IDENTIFIER,
|
|
||||||
Collections.<String>emptySet(),
|
|
||||||
new ClassType(name, Collections.<Element>emptyList(), false),
|
|
||||||
Collections.<Element>emptyList(),
|
|
||||||
new ParameterList(createParametersFromFields(finalOrWithEmptyInitializer)),
|
|
||||||
new Block(createInitStatementsFromFields(finalOrWithEmptyInitializer)),
|
|
||||||
true
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (psiClass.isInterface()) {
|
|
||||||
return new Trait(this, name, modifiers, typeParameters, extendsTypes, Collections.<Expression>emptyList(), implementsTypes, members);
|
|
||||||
}
|
|
||||||
if (psiClass.isEnum()) {
|
|
||||||
return new Enum(this, name, modifiers, typeParameters, Collections.<Type>emptyList(), Collections.<Expression>emptyList(), implementsTypes, members);
|
|
||||||
}
|
|
||||||
return new Class(this, name, modifiers, typeParameters, extendsTypes, baseClassParams, implementsTypes, members);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private Initializer initializerToInitializer(@NotNull PsiClassInitializer i) {
|
|
||||||
return new Initializer(
|
|
||||||
blockToBlock(i.getBody(), true),
|
|
||||||
modifiersListToModifiersSet(i.getModifierList())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static String getDefaultInitializer(@NotNull Field f) {
|
|
||||||
if (f.getType().getNullable()) {
|
|
||||||
return "null";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
final String typeToKotlin = f.getType().toKotlin();
|
|
||||||
if (typeToKotlin.equals("Boolean")) return "false";
|
|
||||||
if (typeToKotlin.equals("Char")) return "' '";
|
|
||||||
if (typeToKotlin.equals("Double")) return "0." + OperatorConventions.DOUBLE + "()";
|
|
||||||
if (typeToKotlin.equals("Float")) return "0." + OperatorConventions.FLOAT + "()";
|
|
||||||
return "0";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private List<Field> fieldsToFieldList(@NotNull PsiField[] fields, PsiClass psiClass) {
|
|
||||||
List<Field> result = new LinkedList<Field>();
|
|
||||||
for (PsiField f : fields) result.add(fieldToField(f, psiClass));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private Field fieldToField(@NotNull PsiField field, PsiClass psiClass) {
|
|
||||||
Set<String> modifiers = modifiersListToModifiersSet(field.getModifierList());
|
|
||||||
if (field instanceof PsiEnumConstant) // TODO: remove instanceof
|
|
||||||
{
|
|
||||||
return new EnumConstant(
|
|
||||||
new IdentifierImpl(field.getName()), // TODO
|
|
||||||
modifiers,
|
|
||||||
typeToType(field.getType()),
|
|
||||||
elementToElement(((PsiEnumConstant) field).getArgumentList())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return new Field(
|
|
||||||
new IdentifierImpl(field.getName()), // TODO
|
|
||||||
modifiers,
|
|
||||||
typeToType(field.getType()),
|
|
||||||
expressionToExpression(field.getInitializer(), field.getType()), // TODO: add modifiers
|
|
||||||
countWritingAccesses(field, psiClass)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private static PsiMethod getPrimaryConstructorForThisCase(@NotNull PsiClass psiClass) {
|
|
||||||
ThisVisitor tv = new ThisVisitor();
|
|
||||||
psiClass.accept(tv);
|
|
||||||
return tv.getPrimaryConstructor();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isConstructorPrimary(@NotNull PsiMethod constructor) {
|
|
||||||
if (constructor.getParent() instanceof PsiClass) {
|
|
||||||
final PsiClass parent = (PsiClass) constructor.getParent();
|
|
||||||
if (parent.getConstructors().length == 1) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
PsiMethod c = getPrimaryConstructorForThisCase(parent); // TODO: move up to classToClass() method
|
|
||||||
if (c != null && c.hashCode() == constructor.hashCode()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private static List<Statement> removeEmpty(@NotNull List<Statement> statements) {
|
|
||||||
List<Statement> result = new LinkedList<Statement>();
|
|
||||||
for (Statement s : statements)
|
|
||||||
if (s != Statement.EMPTY_STATEMENT && s != Expression.EMPTY_EXPRESSION) {
|
|
||||||
result.add(s);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private Function methodToFunction(@NotNull PsiMethod method) {
|
|
||||||
return methodToFunction(method, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private Function methodToFunction(@NotNull PsiMethod method, boolean notEmpty) {
|
|
||||||
if (isOverrideObjectDirect(method)) {
|
|
||||||
dispatcher.setExpressionVisitor(new ExpressionVisitorForDirectObjectInheritors(this));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
dispatcher.setExpressionVisitor(new ExpressionVisitor(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
methodReturnType = method.getReturnType();
|
|
||||||
|
|
||||||
final IdentifierImpl identifier = new IdentifierImpl(method.getName());
|
|
||||||
final Type returnType = typeToType(method.getReturnType(), ConverterUtil.isAnnotatedAsNotNull(method.getModifierList()));
|
|
||||||
final Block body = hasFlag(J2KConverterFlags.SKIP_BODIES)
|
|
||||||
? Block.EMPTY_BLOCK
|
|
||||||
: blockToBlock(method.getBody(), notEmpty); // #TODO
|
|
||||||
final Element params = createFunctionParameters(method);
|
|
||||||
final List<Element> typeParameters = elementsToElementList(method.getTypeParameters());
|
|
||||||
|
|
||||||
final Set<String> modifiers = modifiersListToModifiersSet(method.getModifierList());
|
|
||||||
if (isOverrideAnyMethodExceptMethodsFromObject(method)) {
|
|
||||||
modifiers.add(Modifier.OVERRIDE);
|
|
||||||
}
|
|
||||||
if (method.getParent() instanceof PsiClass && ((PsiClass) method.getParent()).isInterface()) {
|
|
||||||
modifiers.remove(Modifier.ABSTRACT);
|
|
||||||
}
|
|
||||||
if (isNotOpenMethod(method)) {
|
|
||||||
modifiers.add(Modifier.NOT_OPEN);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (method.isConstructor()) { // TODO: simplify
|
|
||||||
boolean isPrimary = isConstructorPrimary(method);
|
|
||||||
return new Constructor(
|
|
||||||
identifier,
|
|
||||||
modifiers,
|
|
||||||
returnType,
|
|
||||||
typeParameters,
|
|
||||||
params,
|
|
||||||
new Block(removeEmpty(body.getStatements()), false),
|
|
||||||
isPrimary
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return new Function(
|
|
||||||
identifier,
|
|
||||||
modifiers,
|
|
||||||
returnType,
|
|
||||||
typeParameters,
|
|
||||||
params,
|
|
||||||
body
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private ParameterList createFunctionParameters(@NotNull PsiMethod method) {
|
|
||||||
List<Parameter> result = new LinkedList<Parameter>();
|
|
||||||
for (PsiParameter parameter : method.getParameterList().getParameters()) {
|
|
||||||
result.add(new Parameter(
|
|
||||||
new IdentifierImpl(parameter.getName()),
|
|
||||||
typeToType(parameter.getType(), ConverterUtil.isAnnotatedAsNotNull(parameter.getModifierList())),
|
|
||||||
ConverterUtil.isReadOnly(parameter, method.getBody())
|
|
||||||
));
|
|
||||||
}
|
|
||||||
return new ParameterList(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isNotOpenMethod(@NotNull final PsiMethod method) {
|
|
||||||
if (method.getParent() instanceof PsiClass) {
|
|
||||||
final PsiModifierList parentModifierList = ((PsiClass) method.getParent()).getModifierList();
|
|
||||||
if ((parentModifierList != null && parentModifierList.hasExplicitModifier(Modifier.FINAL)) || ((PsiClass) method.getParent()).isEnum()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isOverrideAnyMethodExceptMethodsFromObject(@NotNull PsiMethod method) {
|
|
||||||
boolean counter = normalCase(method);
|
|
||||||
if (counter) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (isInheritFromObject(method)) {
|
|
||||||
return caseForObject(method);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean caseForObject(@NotNull PsiMethod method) {
|
|
||||||
PsiClass containing = method.getContainingClass();
|
|
||||||
if (containing != null) {
|
|
||||||
for (PsiClassType s : containing.getSuperTypes()) {
|
|
||||||
String canonicalText = s.getCanonicalText();
|
|
||||||
if (!canonicalText.equals(JAVA_LANG_OBJECT) && !getClassIdentifiers().contains(canonicalText)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean normalCase(@NotNull PsiMethod method) {
|
|
||||||
int counter = 0;
|
|
||||||
for (HierarchicalMethodSignature s : method.getHierarchicalMethodSignature().getSuperSignatures()) {
|
|
||||||
PsiClass containingClass = s.getMethod().getContainingClass();
|
|
||||||
String qualifiedName = containingClass != null ? containingClass.getQualifiedName() : "";
|
|
||||||
if (qualifiedName != null && !qualifiedName.equals(JAVA_LANG_OBJECT)) {
|
|
||||||
counter++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return counter > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isInheritFromObject(@NotNull PsiMethod method) {
|
|
||||||
List<HierarchicalMethodSignature> superSignatures = method.getHierarchicalMethodSignature().getSuperSignatures();
|
|
||||||
for (HierarchicalMethodSignature s : superSignatures) {
|
|
||||||
PsiClass containingClass = s.getMethod().getContainingClass();
|
|
||||||
String qualifiedName = containingClass != null ? containingClass.getQualifiedName() : "";
|
|
||||||
if (qualifiedName != null && qualifiedName.equals(JAVA_LANG_OBJECT)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isOverrideObjectDirect(@NotNull final PsiMethod method) {
|
|
||||||
List<HierarchicalMethodSignature> superSignatures = method.getHierarchicalMethodSignature().getSuperSignatures();
|
|
||||||
if (superSignatures.size() == 1) {
|
|
||||||
final PsiClass containingClass = superSignatures.get(0).getMethod().getContainingClass();
|
|
||||||
final String qualifiedName = containingClass != null ? containingClass.getQualifiedName() : "";
|
|
||||||
if (qualifiedName != null && qualifiedName.equals(JAVA_LANG_OBJECT)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public Block blockToBlock(@Nullable PsiCodeBlock block, boolean notEmpty) {
|
|
||||||
if (block == null) return Block.EMPTY_BLOCK;
|
|
||||||
return new Block(statementsToStatementList(block.getStatements()), notEmpty);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public Block blockToBlock(@Nullable PsiCodeBlock block) {
|
|
||||||
return blockToBlock(block, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public List<Statement> statementsToStatementList(@NotNull PsiStatement[] statements) {
|
|
||||||
List<Statement> result = new LinkedList<Statement>();
|
|
||||||
for (PsiStatement t : statements) result.add(statementToStatement(t));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public List<Statement> statementsToStatementList(@NotNull List<PsiStatement> statements) {
|
|
||||||
List<Statement> result = new LinkedList<Statement>();
|
|
||||||
for (PsiStatement t : statements) result.add(statementToStatement(t));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public Statement statementToStatement(@Nullable PsiStatement s) {
|
|
||||||
if (s == null) return Statement.EMPTY_STATEMENT;
|
|
||||||
final StatementVisitor statementVisitor = new StatementVisitor(this);
|
|
||||||
s.accept(statementVisitor);
|
|
||||||
return statementVisitor.getResult();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public List<Expression> expressionsToExpressionList(@NotNull PsiExpression[] expressions) {
|
|
||||||
List<Expression> result = new LinkedList<Expression>();
|
|
||||||
for (PsiExpression e : expressions) result.add(expressionToExpression(e));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public Expression expressionToExpression(@Nullable PsiExpression e) {
|
|
||||||
if (e == null) return Expression.EMPTY_EXPRESSION;
|
|
||||||
final ExpressionVisitor expressionVisitor = dispatcher.getExpressionVisitor();
|
|
||||||
e.accept(expressionVisitor);
|
|
||||||
return expressionVisitor.getResult();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public Element elementToElement(@Nullable PsiElement e) {
|
|
||||||
if (e == null) return Element.EMPTY_ELEMENT;
|
|
||||||
final ElementVisitor elementVisitor = new ElementVisitor(this);
|
|
||||||
e.accept(elementVisitor);
|
|
||||||
return elementVisitor.getResult();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public List<Element> elementsToElementList(@NotNull PsiElement[] elements) {
|
|
||||||
List<Element> result = new LinkedList<Element>();
|
|
||||||
for (PsiElement e : elements) result.add(elementToElement(e));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public Type typeToType(@Nullable PsiType type) {
|
|
||||||
if (type == null) return new EmptyType();
|
|
||||||
TypeVisitor typeVisitor = new TypeVisitor(this);
|
|
||||||
type.accept(typeVisitor);
|
|
||||||
return typeVisitor.getResult();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public List<Type> typesToTypeList(@NotNull PsiType[] types) {
|
|
||||||
List<Type> result = new LinkedList<Type>();
|
|
||||||
for (PsiType t : types) result.add(typeToType(t));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public Type typeToType(PsiType type, boolean notNull) {
|
|
||||||
Type result = typeToType(type);
|
|
||||||
if (notNull) {
|
|
||||||
return result.convertedToNotNull();
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private List<Type> typesToNotNullableTypeList(@NotNull PsiType[] types) {
|
|
||||||
List<Type> result = new ArrayList<Type>();
|
|
||||||
for (PsiType type : types) {
|
|
||||||
result.add(typeToType(type).convertedToNotNull());
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private static List<Import> importsToImportList(@NotNull PsiImportStatementBase[] imports) {
|
|
||||||
List<Import> result = new LinkedList<Import>();
|
|
||||||
for (PsiImportStatementBase i : imports) {
|
|
||||||
Import anImport = importToImport(i);
|
|
||||||
String name = anImport.getName();
|
|
||||||
if (!name.isEmpty() && !NOT_NULL_ANNOTATIONS.contains(name)) {
|
|
||||||
result.add(anImport);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private static Import importToImport(@NotNull PsiImportStatementBase i) {
|
|
||||||
final PsiJavaCodeReferenceElement reference = i.getImportReference();
|
|
||||||
if (reference != null) {
|
|
||||||
return new Import(quoteKeywords(reference.getQualifiedName()) + (i.isOnDemand() ? ".*" : ""));
|
|
||||||
}
|
|
||||||
return new Import("");
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public List<Parameter> parametersToParameterList(@NotNull PsiParameter[] parameters) {
|
|
||||||
List<Parameter> result = new LinkedList<Parameter>();
|
|
||||||
for (PsiParameter t : parameters) result.add(parameterToParameter(t));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public Parameter parameterToParameter(@NotNull PsiParameter parameter) {
|
|
||||||
return new Parameter(
|
|
||||||
new IdentifierImpl(parameter.getName()),
|
|
||||||
typeToType(parameter.getType(), ConverterUtil.isAnnotatedAsNotNull(parameter.getModifierList())),
|
|
||||||
true
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static Identifier identifierToIdentifier(@Nullable PsiIdentifier identifier) {
|
|
||||||
if (identifier == null) return Identifier.EMPTY_IDENTIFIER;
|
|
||||||
return new IdentifierImpl(identifier.getText());
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static Set<String> modifiersListToModifiersSet(@Nullable PsiModifierList modifierList) {
|
|
||||||
HashSet<String> modifiersSet = new HashSet<String>();
|
|
||||||
if (modifierList != null) {
|
|
||||||
if (modifierList.hasExplicitModifier(PsiModifier.ABSTRACT)) modifiersSet.add(Modifier.ABSTRACT);
|
|
||||||
if (modifierList.hasModifierProperty(PsiModifier.FINAL)) modifiersSet.add(Modifier.FINAL);
|
|
||||||
if (modifierList.hasModifierProperty(PsiModifier.STATIC)) modifiersSet.add(Modifier.STATIC);
|
|
||||||
if (modifierList.hasExplicitModifier(PsiModifier.PUBLIC)) modifiersSet.add(Modifier.PUBLIC);
|
|
||||||
if (modifierList.hasExplicitModifier(PsiModifier.PROTECTED)) modifiersSet.add(Modifier.PROTECTED);
|
|
||||||
if (modifierList.hasExplicitModifier(PsiModifier.PACKAGE_LOCAL)) modifiersSet.add(Modifier.INTERNAL);
|
|
||||||
if (modifierList.hasExplicitModifier(PsiModifier.PRIVATE)) modifiersSet.add(Modifier.PRIVATE);
|
|
||||||
}
|
|
||||||
return modifiersSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Expression> argumentsToExpressionList(@NotNull PsiCallExpression expression) {
|
|
||||||
PsiExpressionList argumentList = expression.getArgumentList();
|
|
||||||
PsiExpression[] arguments = argumentList != null ? argumentList.getExpressions() : PsiExpression.EMPTY_ARRAY;
|
|
||||||
List<Expression> result = new ArrayList<Expression>();
|
|
||||||
|
|
||||||
PsiMethod resolved = expression.resolveMethod();
|
|
||||||
List<PsiType> expectedTypes = new ArrayList<PsiType>();
|
|
||||||
if (resolved != null) {
|
|
||||||
for (PsiParameter p : resolved.getParameterList().getParameters())
|
|
||||||
expectedTypes.add(p.getType());
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO handle varargs correctly
|
|
||||||
if (arguments.length == expectedTypes.size()) {
|
|
||||||
for (int i = 0; i < expectedTypes.size(); i++)
|
|
||||||
result.add(expressionToExpression(arguments[i], expectedTypes.get(i)));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for (PsiExpression argument : arguments) {
|
|
||||||
result.add(expressionToExpression(argument));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Expression expressionToExpression(PsiExpression argument, PsiType expectedType) {
|
|
||||||
if (argument == null) return (IdentifierImpl) Identifier.EMPTY_IDENTIFIER;
|
|
||||||
Expression expression = expressionToExpression(argument);
|
|
||||||
PsiType actualType = argument.getType();
|
|
||||||
boolean isPrimitiveTypeOrNull = actualType == null || actualType instanceof PsiPrimitiveType;
|
|
||||||
boolean isRef = (argument instanceof PsiReferenceExpression && ((PsiReferenceExpression) argument).isQualified() || argument instanceof PsiMethodCallExpression);
|
|
||||||
|
|
||||||
if (isPrimitiveTypeOrNull && isRef && expression.isNullable()) {
|
|
||||||
expression = new BangBangExpression(expression);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (actualType != null) {
|
|
||||||
if (isConversionNeeded(actualType, expectedType) && !(expression instanceof LiteralExpression)) {
|
|
||||||
String conversion = PRIMITIVE_TYPE_CONVERSIONS.get(expectedType.getCanonicalText());
|
|
||||||
if (conversion != null) {
|
|
||||||
expression = new DummyMethodCallExpression(expression, conversion, (IdentifierImpl) Identifier.EMPTY_IDENTIFIER);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return expression;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isConversionNeeded(@Nullable final PsiType actual, @Nullable final PsiType expected) {
|
|
||||||
if (actual == null || expected == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Map<String, String> typeMap = new HashMap<String, String>();
|
|
||||||
typeMap.put(JAVA_LANG_BYTE, "byte");
|
|
||||||
typeMap.put(JAVA_LANG_SHORT, "short");
|
|
||||||
typeMap.put(JAVA_LANG_INTEGER, "int");
|
|
||||||
typeMap.put(JAVA_LANG_LONG, "long");
|
|
||||||
typeMap.put(JAVA_LANG_FLOAT, "float");
|
|
||||||
typeMap.put(JAVA_LANG_DOUBLE, "double");
|
|
||||||
typeMap.put(JAVA_LANG_CHARACTER, "char");
|
|
||||||
String expectedStr = expected.getCanonicalText();
|
|
||||||
String actualStr = actual.getCanonicalText();
|
|
||||||
boolean o1 = AstUtil.getOrElse(typeMap, actualStr, "").equals(expectedStr);
|
|
||||||
boolean o2 = AstUtil.getOrElse(typeMap, expectedStr, "").equals(actualStr);
|
|
||||||
return !actualStr.equals(expectedStr) && (!(o1 ^ o2));
|
|
||||||
}
|
|
||||||
|
|
||||||
// @NotNull
|
|
||||||
// private static String applyConversion(Expression expression, String conversion) {
|
|
||||||
// if (conversion.isEmpty())
|
|
||||||
// return expression.toKotlin();
|
|
||||||
// return "(" + expression.toKotlin() + ")" + conversion;
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,681 @@
|
|||||||
|
package org.jetbrains.jet.j2k
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap
|
||||||
|
import com.google.common.collect.ImmutableSet
|
||||||
|
import com.google.common.collect.Sets
|
||||||
|
import com.intellij.psi.*
|
||||||
|
import org.jetbrains.annotations.Nullable
|
||||||
|
import org.jetbrains.jet.j2k.ast.*
|
||||||
|
import org.jetbrains.jet.j2k.ast.Class
|
||||||
|
import org.jetbrains.jet.j2k.ast.Enum
|
||||||
|
import org.jetbrains.jet.j2k.ast.types.ClassType
|
||||||
|
import org.jetbrains.jet.j2k.ast.types.EmptyType
|
||||||
|
import org.jetbrains.jet.j2k.ast.types.Type
|
||||||
|
import org.jetbrains.jet.j2k.util.AstUtil
|
||||||
|
import org.jetbrains.jet.j2k.visitors.*
|
||||||
|
import org.jetbrains.jet.lang.types.expressions.OperatorConventions
|
||||||
|
import java.util.*
|
||||||
|
import org.jetbrains.jet.j2k.ConverterUtil.countWritingAccesses
|
||||||
|
import org.jetbrains.jet.j2k.ConverterUtil.createMainFunction
|
||||||
|
import com.intellij.psi.CommonClassNames.*
|
||||||
|
import org.jetbrains.jet.lang.types.expressions.OperatorConventions.*
|
||||||
|
|
||||||
|
public open class Converter() {
|
||||||
|
private var classIdentifiers: Set<String> = hashSet()
|
||||||
|
private val dispatcher: Dispatcher = Dispatcher(this)
|
||||||
|
private var methodReturnType: PsiType? = null
|
||||||
|
private val flags: Set<J2KConverterFlags?>? = Sets.newHashSet()
|
||||||
|
public open fun addFlag(flag: J2KConverterFlags): Boolean {
|
||||||
|
return flags?.add(flag)!!
|
||||||
|
}
|
||||||
|
public open fun hasFlag(flag: J2KConverterFlags): Boolean {
|
||||||
|
return flags?.contains(flag)!!
|
||||||
|
}
|
||||||
|
|
||||||
|
public open fun setClassIdentifiers(identifiers: Set<String>) {
|
||||||
|
classIdentifiers = identifiers
|
||||||
|
}
|
||||||
|
|
||||||
|
public open fun getClassIdentifiers(): Set<String> {
|
||||||
|
return Collections.unmodifiableSet(classIdentifiers)!!
|
||||||
|
}
|
||||||
|
|
||||||
|
public open fun getMethodReturnType(): PsiType? {
|
||||||
|
return methodReturnType
|
||||||
|
}
|
||||||
|
|
||||||
|
public open fun clearClassIdentifiers(): Unit {
|
||||||
|
classIdentifiers.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
public open fun elementToKotlin(element: PsiElement): String =
|
||||||
|
when(element) {
|
||||||
|
is PsiJavaFile -> fileToFile(element).toKotlin()
|
||||||
|
is PsiClass -> classToClass(element).toKotlin()
|
||||||
|
is PsiMethod -> methodToFunction(element).toKotlin()
|
||||||
|
is PsiField -> fieldToField(element, element.getContainingClass()).toKotlin()
|
||||||
|
is PsiStatement -> statementToStatement(element).toKotlin()
|
||||||
|
is PsiExpression -> expressionToExpression(element).toKotlin()
|
||||||
|
else -> ""
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public open fun fileToFile(javaFile: PsiJavaFile): File {
|
||||||
|
return fileToFile(javaFile, Collections.emptyList<String>()!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
public open fun fileToFileWithCompatibilityImport(javaFile: PsiJavaFile): File {
|
||||||
|
return fileToFile(javaFile, Collections.singletonList("kotlin.compatibility.*")!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun fileToFile(javaFile: PsiJavaFile, additionalImports: List<String>): File {
|
||||||
|
val importList: PsiImportList? = javaFile.getImportList()
|
||||||
|
val imports: List<Import> = (if (importList == null)
|
||||||
|
arrayList()
|
||||||
|
else
|
||||||
|
importsToImportList(importList.getAllImportStatements()))
|
||||||
|
for (i : String in additionalImports)
|
||||||
|
imports.add(Import(i))
|
||||||
|
return File(quoteKeywords(javaFile.getPackageName()), imports, classesToClassList(javaFile.getClasses()), createMainFunction(javaFile))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun classesToClassList(classes: Array<PsiClass?>): List<Class> = classes.map { classToClass(it!!) }
|
||||||
|
|
||||||
|
public open fun anonymousClassToAnonymousClass(anonymousClass: PsiAnonymousClass): AnonymousClass {
|
||||||
|
return AnonymousClass(this, getMembers(anonymousClass))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getMembers(psiClass: PsiClass): List<Member> {
|
||||||
|
val members: List<Member> = arrayList()
|
||||||
|
for (e : PsiElement? in psiClass.getChildren()) {
|
||||||
|
val converted = memberToMember(e, psiClass)
|
||||||
|
if (converted != null) members.add(converted)
|
||||||
|
}
|
||||||
|
return members
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun memberToMember(e: PsiElement?, containingClass: PsiClass): Member? = when(e) {
|
||||||
|
is PsiMethod -> methodToFunction(e, true)
|
||||||
|
is PsiField -> fieldToField(e, containingClass)
|
||||||
|
is PsiClass -> classToClass(e)
|
||||||
|
is PsiClassInitializer -> initializerToInitializer(e)
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun classToClass(psiClass: PsiClass): Class {
|
||||||
|
val modifiers: Set<String> = modifiersListToModifiersSet(psiClass.getModifierList())
|
||||||
|
val fields: List<Field> = fieldsToFieldList(psiClass.getFields(), psiClass)
|
||||||
|
val typeParameters: List<Element> = elementsToElementList(psiClass.getTypeParameters())
|
||||||
|
val implementsTypes: List<Type> = typesToNotNullableTypeList(psiClass.getImplementsListTypes())
|
||||||
|
val extendsTypes: List<Type> = typesToNotNullableTypeList(psiClass.getExtendsListTypes())
|
||||||
|
val name: IdentifierImpl = IdentifierImpl(psiClass.getName())
|
||||||
|
val baseClassParams: List<Expression> = arrayList()
|
||||||
|
val members: List<Member> = getMembers(psiClass)
|
||||||
|
val visitor: SuperVisitor = SuperVisitor()
|
||||||
|
psiClass.accept(visitor)
|
||||||
|
val resolvedSuperCallParameters = visitor.resolvedSuperCallParameters
|
||||||
|
if (resolvedSuperCallParameters.size() == 1) {
|
||||||
|
val psiExpressionList = resolvedSuperCallParameters.iterator().next()
|
||||||
|
baseClassParams.addAll(expressionsToExpressionList(psiExpressionList.getExpressions()))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!psiClass.isEnum() && !psiClass.isInterface() && psiClass.getConstructors().size > 1 &&
|
||||||
|
getPrimaryConstructorForThisCase(psiClass) == null) {
|
||||||
|
val finalOrWithEmptyInitializer: List<Field> = getFinalOrWithEmptyInitializer(fields)
|
||||||
|
val initializers: Map<String, String> = HashMap<String, String>()
|
||||||
|
for (m in members) {
|
||||||
|
if (m is Constructor) {
|
||||||
|
if (!m.isPrimary) {
|
||||||
|
for (fo in finalOrWithEmptyInitializer){
|
||||||
|
val init: String = getDefaultInitializer(fo)
|
||||||
|
initializers.put(fo.identifier.toKotlin(), init)
|
||||||
|
}
|
||||||
|
val newStatements: List<Statement> = arrayList()
|
||||||
|
for (s : Statement? in m.block!!.statements) {
|
||||||
|
var isRemoved: Boolean = false
|
||||||
|
if (s is AssignmentExpression) {
|
||||||
|
if (s.left.getKind() == INode.Kind.CALL_CHAIN) {
|
||||||
|
for (fo : Field in finalOrWithEmptyInitializer) {
|
||||||
|
val id: String = fo.identifier.toKotlin()
|
||||||
|
if ((s.left as CallChainExpression).identifier.toKotlin().endsWith("." + id)) {
|
||||||
|
initializers.put(id, s.right.toKotlin())
|
||||||
|
isRemoved = true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isRemoved) {
|
||||||
|
newStatements.add(s!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
newStatements.add(0, DummyStringExpression("val __ = " + createPrimaryConstructorInvocation(name.toKotlin(), finalOrWithEmptyInitializer, initializers)))
|
||||||
|
m.block = Block(newStatements)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
members.add(Constructor(Identifier.EMPTY_IDENTIFIER, Collections.emptySet<String>()!!,
|
||||||
|
ClassType(name, Collections.emptyList<Element>()!!, false),
|
||||||
|
Collections.emptyList<Element>()!!,
|
||||||
|
ParameterList(createParametersFromFields(finalOrWithEmptyInitializer)),
|
||||||
|
Block(createInitStatementsFromFields(finalOrWithEmptyInitializer)),
|
||||||
|
true))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (psiClass.isInterface()) {
|
||||||
|
return Trait(this, name, modifiers, typeParameters, extendsTypes, Collections.emptyList<Expression>()!!, implementsTypes, members)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (psiClass.isEnum()) {
|
||||||
|
return Enum(this, name, modifiers, typeParameters, Collections.emptyList<Type>()!!, Collections.emptyList<Expression>()!!, implementsTypes, members)
|
||||||
|
}
|
||||||
|
|
||||||
|
return Class(this, name, modifiers, typeParameters, extendsTypes, baseClassParams, implementsTypes, members)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initializerToInitializer(i: PsiClassInitializer): Initializer {
|
||||||
|
return Initializer(blockToBlock(i.getBody(), true), modifiersListToModifiersSet(i.getModifierList()))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun fieldsToFieldList(fields: Array<PsiField?>, psiClass: PsiClass): List<Field> {
|
||||||
|
return fields.map { fieldToField(it!!, psiClass) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun fieldToField(field: PsiField, psiClass: PsiClass?): Field {
|
||||||
|
val modifiers: Set<String> = modifiersListToModifiersSet(field.getModifierList())
|
||||||
|
if (field is PsiEnumConstant?) {
|
||||||
|
return EnumConstant(IdentifierImpl(field.getName()), modifiers, typeToType(field.getType()), elementToElement(field.getArgumentList()))
|
||||||
|
}
|
||||||
|
|
||||||
|
return Field(IdentifierImpl(field.getName()),
|
||||||
|
modifiers,
|
||||||
|
typeToType(field.getType()),
|
||||||
|
expressionToExpression(field.getInitializer(), field.getType()),
|
||||||
|
countWritingAccesses(field, psiClass))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun methodToFunction(method: PsiMethod): Function {
|
||||||
|
return methodToFunction(method, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun methodToFunction(method: PsiMethod, notEmpty: Boolean): Function {
|
||||||
|
if (isOverrideObjectDirect(method)) {
|
||||||
|
dispatcher.expressionVisitor = ExpressionVisitorForDirectObjectInheritors(this)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dispatcher.expressionVisitor = ExpressionVisitor(this)
|
||||||
|
}
|
||||||
|
methodReturnType = method.getReturnType()
|
||||||
|
val identifier: IdentifierImpl = IdentifierImpl(method.getName())
|
||||||
|
val returnType: Type = typeToType(method.getReturnType(), ConverterUtil.isAnnotatedAsNotNull(method.getModifierList()))
|
||||||
|
val body: Block = (if (hasFlag(J2KConverterFlags.SKIP_BODIES))
|
||||||
|
Block.EMPTY_BLOCK
|
||||||
|
else
|
||||||
|
blockToBlock(method.getBody(), notEmpty))
|
||||||
|
|
||||||
|
val params: Element = createFunctionParameters(method)
|
||||||
|
val typeParameters: List<Element> = elementsToElementList(method.getTypeParameters())
|
||||||
|
val modifiers: Set<String> = modifiersListToModifiersSet(method.getModifierList())
|
||||||
|
if (isOverrideAnyMethodExceptMethodsFromObject(method)) {
|
||||||
|
modifiers.add(Modifier.OVERRIDE)
|
||||||
|
}
|
||||||
|
|
||||||
|
val containingClass = method.getContainingClass()
|
||||||
|
if (containingClass != null && containingClass.isInterface()) {
|
||||||
|
modifiers.remove(Modifier.ABSTRACT)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNotOpenMethod(method)) {
|
||||||
|
modifiers.add(Modifier.NOT_OPEN)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (method.isConstructor()) {
|
||||||
|
val isPrimary: Boolean = isConstructorPrimary(method)
|
||||||
|
return Constructor(identifier, modifiers, returnType, typeParameters, params, Block(removeEmpty(body.statements), false), isPrimary)
|
||||||
|
}
|
||||||
|
|
||||||
|
return Function(identifier, modifiers, returnType, typeParameters, params, body)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createFunctionParameters(method: PsiMethod): ParameterList {
|
||||||
|
val result: List<Parameter> = arrayList()
|
||||||
|
for (parameter : PsiParameter? in method.getParameterList().getParameters())
|
||||||
|
{
|
||||||
|
result.add(Parameter(IdentifierImpl(parameter?.getName()),
|
||||||
|
typeToType(parameter?.getType(),
|
||||||
|
ConverterUtil.isAnnotatedAsNotNull(parameter?.getModifierList())),
|
||||||
|
ConverterUtil.isReadOnly(parameter, method.getBody())))
|
||||||
|
}
|
||||||
|
return ParameterList(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isOverrideAnyMethodExceptMethodsFromObject(method: PsiMethod): Boolean {
|
||||||
|
var counter: Boolean = normalCase(method)
|
||||||
|
if (counter)
|
||||||
|
{
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isInheritFromObject(method))
|
||||||
|
{
|
||||||
|
return caseForObject(method)
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun caseForObject(method: PsiMethod): Boolean {
|
||||||
|
var containing: PsiClass? = method.getContainingClass()
|
||||||
|
if (containing != null) {
|
||||||
|
for (s : PsiClassType? in containing?.getSuperTypes()) {
|
||||||
|
val canonicalText: String? = s?.getCanonicalText()
|
||||||
|
if (canonicalText != JAVA_LANG_OBJECT && !getClassIdentifiers().contains(canonicalText)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
public open fun blockToBlock(block: PsiCodeBlock?, notEmpty: Boolean): Block {
|
||||||
|
if (block == null)
|
||||||
|
return Block.EMPTY_BLOCK
|
||||||
|
|
||||||
|
return Block(statementsToStatementList(block.getStatements()), notEmpty)
|
||||||
|
}
|
||||||
|
|
||||||
|
public open fun blockToBlock(block: PsiCodeBlock?): Block {
|
||||||
|
return blockToBlock(block, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
public open fun statementsToStatementList(statements: Array<PsiStatement?>): List<Statement> {
|
||||||
|
return statements.map { statementToStatement(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
public open fun statementsToStatementList(statements: List<PsiStatement?>): List<Statement> {
|
||||||
|
return statements.map { statementToStatement(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
public open fun statementToStatement(s: PsiStatement?): Statement {
|
||||||
|
if (s == null)
|
||||||
|
return Statement.EMPTY_STATEMENT
|
||||||
|
|
||||||
|
val statementVisitor: StatementVisitor = StatementVisitor(this)
|
||||||
|
s.accept(statementVisitor)
|
||||||
|
return statementVisitor.getResult()
|
||||||
|
}
|
||||||
|
|
||||||
|
public open fun expressionsToExpressionList(expressions: Array<PsiExpression?>): List<Expression> {
|
||||||
|
val result: List<Expression> = arrayList()
|
||||||
|
for (e : PsiExpression? in expressions)
|
||||||
|
result.add(expressionToExpression(e))
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
public open fun expressionToExpression(e: PsiExpression?): Expression {
|
||||||
|
if (e == null)
|
||||||
|
return Expression.EMPTY_EXPRESSION
|
||||||
|
|
||||||
|
val expressionVisitor: ExpressionVisitor = dispatcher.expressionVisitor
|
||||||
|
e.accept(expressionVisitor)
|
||||||
|
return expressionVisitor.getResult()
|
||||||
|
}
|
||||||
|
|
||||||
|
public open fun elementToElement(e: PsiElement?): Element {
|
||||||
|
if (e == null)
|
||||||
|
return Element.EMPTY_ELEMENT
|
||||||
|
|
||||||
|
val elementVisitor: ElementVisitor = ElementVisitor(this)
|
||||||
|
e.accept(elementVisitor)
|
||||||
|
return elementVisitor.getResult()
|
||||||
|
}
|
||||||
|
|
||||||
|
public open fun elementsToElementList(elements: Array<out PsiElement?>): List<Element> {
|
||||||
|
val result: List<Element> = arrayList()
|
||||||
|
for(element in elements) {
|
||||||
|
result.add(elementToElement(element))
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
public open fun typeToType(`type`: PsiType?): Type {
|
||||||
|
if (`type` == null)
|
||||||
|
return EmptyType()
|
||||||
|
|
||||||
|
val typeVisitor: TypeVisitor = TypeVisitor(this)
|
||||||
|
`type`.accept<Type>(typeVisitor)
|
||||||
|
return typeVisitor.getResult()
|
||||||
|
}
|
||||||
|
|
||||||
|
public open fun typesToTypeList(types: Array<PsiType?>): List<Type?> {
|
||||||
|
return types.map { typeToType(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
public open fun typeToType(`type`: PsiType?, notNull: Boolean): Type {
|
||||||
|
val result: Type = typeToType(`type`)
|
||||||
|
if (notNull) {
|
||||||
|
return result.convertedToNotNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun typesToNotNullableTypeList(types: Array<out PsiType?>): List<Type> {
|
||||||
|
val result: List<Type> = arrayList()
|
||||||
|
for(aType in types) {
|
||||||
|
result.add(typeToType(aType).convertedToNotNull())
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
public open fun parametersToParameterList(parameters: Array<PsiParameter?>): List<Parameter?> {
|
||||||
|
return parameters.map { parameterToParameter(it!!) }
|
||||||
|
}
|
||||||
|
|
||||||
|
public open fun parameterToParameter(parameter: PsiParameter): Parameter {
|
||||||
|
return Parameter(IdentifierImpl(parameter.getName()),
|
||||||
|
typeToType(parameter.getType(),
|
||||||
|
ConverterUtil.isAnnotatedAsNotNull(parameter.getModifierList())), true)
|
||||||
|
}
|
||||||
|
|
||||||
|
public open fun argumentsToExpressionList(expression: PsiCallExpression): List<Expression> {
|
||||||
|
val argumentList: PsiExpressionList? = expression.getArgumentList()
|
||||||
|
val arguments: Array<PsiExpression?> = (if (argumentList != null)
|
||||||
|
argumentList.getExpressions()
|
||||||
|
else
|
||||||
|
PsiExpression.EMPTY_ARRAY)
|
||||||
|
val result: List<Expression> = ArrayList<Expression>()
|
||||||
|
val resolved: PsiMethod? = expression.resolveMethod()
|
||||||
|
val expectedTypes: List<PsiType?> = ArrayList<PsiType?>()
|
||||||
|
if (resolved != null) {
|
||||||
|
for (p : PsiParameter? in resolved.getParameterList().getParameters())
|
||||||
|
expectedTypes.add(p?.getType())
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arguments.size == expectedTypes.size()) {
|
||||||
|
for (i in 0..expectedTypes.size() - 1) result.add(expressionToExpression(arguments[i], expectedTypes.get(i)))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (argument : PsiExpression? in arguments) {
|
||||||
|
result.add(expressionToExpression(argument))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
public open fun expressionToExpression(argument: PsiExpression?, expectedType: PsiType?): Expression {
|
||||||
|
if (argument == null)
|
||||||
|
return (Identifier.EMPTY_IDENTIFIER as IdentifierImpl)
|
||||||
|
|
||||||
|
var expression: Expression = expressionToExpression(argument)
|
||||||
|
val actualType: PsiType? = argument.getType()
|
||||||
|
val isPrimitiveTypeOrNull: Boolean = actualType == null || actualType is PsiPrimitiveType
|
||||||
|
var isRef: Boolean = ((argument is PsiReferenceExpression && argument.isQualified()) || argument is PsiMethodCallExpression)
|
||||||
|
if (isPrimitiveTypeOrNull && isRef && expression.isNullable()) {
|
||||||
|
expression = BangBangExpression(expression)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actualType != null) {
|
||||||
|
if (isConversionNeeded(actualType, expectedType) && !(expression is LiteralExpression))
|
||||||
|
{
|
||||||
|
var conversion: String? = PRIMITIVE_TYPE_CONVERSIONS?.get(expectedType?.getCanonicalText())
|
||||||
|
if (conversion != null)
|
||||||
|
{
|
||||||
|
expression = DummyMethodCallExpression(expression, conversion, (Identifier.EMPTY_IDENTIFIER as IdentifierImpl?))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return expression
|
||||||
|
}
|
||||||
|
|
||||||
|
class object {
|
||||||
|
public val NOT_NULL_ANNOTATIONS: Set<String> = ImmutableSet.of<String>("org.jetbrains.annotations.NotNull", "com.sun.istack.internal.NotNull", "javax.annotation.Nonnull")!!
|
||||||
|
private val PRIMITIVE_TYPE_CONVERSIONS: Map<String, String> = ImmutableMap.builder<String, String>()
|
||||||
|
?.put("byte", BYTE)
|
||||||
|
?.put("short", SHORT)
|
||||||
|
?.put("int", INT)
|
||||||
|
?.put("long", LONG)
|
||||||
|
?.put("float", FLOAT)
|
||||||
|
?.put("double", DOUBLE)
|
||||||
|
?.put("char", CHAR)
|
||||||
|
?.put(JAVA_LANG_BYTE, BYTE)
|
||||||
|
?.put(JAVA_LANG_SHORT, SHORT)
|
||||||
|
?.put(JAVA_LANG_INTEGER, INT)
|
||||||
|
?.put(JAVA_LANG_LONG, LONG)
|
||||||
|
?.put(JAVA_LANG_FLOAT, FLOAT)
|
||||||
|
?.put(JAVA_LANG_DOUBLE, DOUBLE)
|
||||||
|
?.put(JAVA_LANG_CHARACTER, CHAR)
|
||||||
|
?.build()!!
|
||||||
|
|
||||||
|
private fun quoteKeywords(packageName: String): String {
|
||||||
|
return packageName.split("\\.").map { IdentifierImpl(it).toKotlin() }.makeString(".")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getFinalOrWithEmptyInitializer(fields: List<out Field>): List<Field> {
|
||||||
|
val result: List<Field> = arrayList()
|
||||||
|
for (f : Field in fields)
|
||||||
|
if (f.isVal() || f.initializer.toKotlin().isEmpty()) {
|
||||||
|
result.add(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createParametersFromFields(fields: List<Field>): List<Parameter> {
|
||||||
|
return fields.map { Parameter(IdentifierImpl("_" + it.identifier.getName()), it.`type`, true) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createInitStatementsFromFields(fields: List<out Field>): List<Statement> {
|
||||||
|
val result: List<Statement> = arrayList()
|
||||||
|
for (f : Field in fields) {
|
||||||
|
val identifierToKotlin: String? = f.identifier.toKotlin()
|
||||||
|
result.add(DummyStringExpression(identifierToKotlin + " = " + "_" + identifierToKotlin))
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createPrimaryConstructorInvocation(s: String, fields: List<Field>, initializers: Map<String, String>): String {
|
||||||
|
return s + "(" + fields.map { initializers[it.identifier.toKotlin()] }.makeString(", ") + ")"
|
||||||
|
}
|
||||||
|
|
||||||
|
public open fun getDefaultInitializer(f: Field): String {
|
||||||
|
if (f.`type`.nullable) {
|
||||||
|
return "null"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
val typeToKotlin: String = f.`type`.toKotlin()
|
||||||
|
if (typeToKotlin.equals("Boolean"))
|
||||||
|
return "false"
|
||||||
|
|
||||||
|
if (typeToKotlin.equals("Char"))
|
||||||
|
return "' '"
|
||||||
|
|
||||||
|
if (typeToKotlin.equals("Double"))
|
||||||
|
return "0." + OperatorConventions.DOUBLE + "()"
|
||||||
|
|
||||||
|
if (typeToKotlin.equals("Float"))
|
||||||
|
return "0." + OperatorConventions.FLOAT + "()"
|
||||||
|
|
||||||
|
return "0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getPrimaryConstructorForThisCase(psiClass: PsiClass): PsiMethod? {
|
||||||
|
val tv = ThisVisitor()
|
||||||
|
psiClass.accept(tv)
|
||||||
|
return tv.getPrimaryConstructor()
|
||||||
|
}
|
||||||
|
|
||||||
|
public open fun isConstructorPrimary(constructor: PsiMethod): Boolean {
|
||||||
|
val parent = constructor.getParent()
|
||||||
|
if (parent is PsiClass) {
|
||||||
|
if (parent.getConstructors().size == 1) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
val c: PsiMethod? = getPrimaryConstructorForThisCase(parent)
|
||||||
|
if (c != null && c.hashCode() == constructor.hashCode()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
private fun removeEmpty(statements: List<Statement>): List<Statement> {
|
||||||
|
return statements.filterNot { it == Statement.EMPTY_STATEMENT || it == Expression.EMPTY_EXPRESSION }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isNotOpenMethod(method: PsiMethod): Boolean {
|
||||||
|
val parent = method.getParent()
|
||||||
|
if (parent is PsiClass) {
|
||||||
|
val parentModifierList: PsiModifierList? = parent.getModifierList()
|
||||||
|
if ((parentModifierList != null && parentModifierList.hasExplicitModifier(Modifier.FINAL)) || parent.isEnum()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun normalCase(method: PsiMethod): Boolean {
|
||||||
|
var counter: Int = 0
|
||||||
|
for (s : HierarchicalMethodSignature? in method.getHierarchicalMethodSignature()?.getSuperSignatures())
|
||||||
|
{
|
||||||
|
var containingClass: PsiClass? = s?.getMethod()?.getContainingClass()
|
||||||
|
var qualifiedName: String? = (if (containingClass != null)
|
||||||
|
containingClass?.getQualifiedName()
|
||||||
|
else
|
||||||
|
"")
|
||||||
|
if (qualifiedName != null && !qualifiedName.equals(JAVA_LANG_OBJECT))
|
||||||
|
{
|
||||||
|
counter++
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return counter > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isInheritFromObject(method: PsiMethod): Boolean {
|
||||||
|
var superSignatures: List<HierarchicalMethodSignature?>? = method.getHierarchicalMethodSignature().getSuperSignatures()
|
||||||
|
for (s : HierarchicalMethodSignature? in superSignatures) {
|
||||||
|
var containingClass: PsiClass? = s?.getMethod()?.getContainingClass()
|
||||||
|
var qualifiedName: String? = (if (containingClass != null)
|
||||||
|
containingClass?.getQualifiedName()
|
||||||
|
else
|
||||||
|
"")
|
||||||
|
if (qualifiedName == JAVA_LANG_OBJECT) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isOverrideObjectDirect(method: PsiMethod): Boolean {
|
||||||
|
var superSignatures: List<HierarchicalMethodSignature?>? = method?.getHierarchicalMethodSignature()?.getSuperSignatures()
|
||||||
|
if (superSignatures?.size()!! == 1)
|
||||||
|
{
|
||||||
|
val containingClass: PsiClass? = superSignatures?.get(0)?.getMethod()?.getContainingClass()
|
||||||
|
val qualifiedName: String? = (if (containingClass != null)
|
||||||
|
containingClass?.getQualifiedName()
|
||||||
|
else
|
||||||
|
"")
|
||||||
|
if (qualifiedName != null && qualifiedName?.equals(JAVA_LANG_OBJECT)!!)
|
||||||
|
{
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
private fun importsToImportList(imports: Array<PsiImportStatementBase?>): List<Import> {
|
||||||
|
val result: List<Import> = arrayList()
|
||||||
|
for (i : PsiImportStatementBase? in imports) {
|
||||||
|
if (i == null) continue
|
||||||
|
val anImport: Import = importToImport(i)
|
||||||
|
val name: String = anImport.name
|
||||||
|
if (!name.isEmpty() && !NOT_NULL_ANNOTATIONS.contains(name)) {
|
||||||
|
result.add(anImport)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun importToImport(i: PsiImportStatementBase): Import {
|
||||||
|
val reference: PsiJavaCodeReferenceElement? = i.getImportReference()
|
||||||
|
if (reference != null) {
|
||||||
|
return Import(quoteKeywords(reference.getQualifiedName()!!) + ((if (i.isOnDemand())
|
||||||
|
".*"
|
||||||
|
else
|
||||||
|
"")))
|
||||||
|
}
|
||||||
|
|
||||||
|
return Import("")
|
||||||
|
}
|
||||||
|
|
||||||
|
public open fun identifierToIdentifier(identifier: PsiIdentifier?): Identifier {
|
||||||
|
if (identifier == null)
|
||||||
|
return Identifier.EMPTY_IDENTIFIER
|
||||||
|
|
||||||
|
return IdentifierImpl(identifier?.getText())
|
||||||
|
}
|
||||||
|
|
||||||
|
public open fun modifiersListToModifiersSet(modifierList: PsiModifierList?): Set<String> {
|
||||||
|
val modifiersSet: HashSet<String> = hashSet()
|
||||||
|
if (modifierList != null) {
|
||||||
|
if (modifierList.hasExplicitModifier(PsiModifier.ABSTRACT))
|
||||||
|
modifiersSet.add(Modifier.ABSTRACT)
|
||||||
|
|
||||||
|
if (modifierList.hasModifierProperty(PsiModifier.FINAL))
|
||||||
|
modifiersSet.add(Modifier.FINAL)
|
||||||
|
|
||||||
|
if (modifierList.hasModifierProperty(PsiModifier.STATIC))
|
||||||
|
modifiersSet.add(Modifier.STATIC)
|
||||||
|
|
||||||
|
if (modifierList.hasExplicitModifier(PsiModifier.PUBLIC))
|
||||||
|
modifiersSet.add(Modifier.PUBLIC)
|
||||||
|
|
||||||
|
if (modifierList.hasExplicitModifier(PsiModifier.PROTECTED))
|
||||||
|
modifiersSet.add(Modifier.PROTECTED)
|
||||||
|
|
||||||
|
if (modifierList.hasExplicitModifier(PsiModifier.PACKAGE_LOCAL))
|
||||||
|
modifiersSet.add(Modifier.INTERNAL)
|
||||||
|
|
||||||
|
if (modifierList.hasExplicitModifier(PsiModifier.PRIVATE))
|
||||||
|
modifiersSet.add(Modifier.PRIVATE)
|
||||||
|
}
|
||||||
|
|
||||||
|
return modifiersSet
|
||||||
|
}
|
||||||
|
private fun isConversionNeeded(actual: PsiType?, expected: PsiType?): Boolean {
|
||||||
|
if (actual == null || expected == null) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
var typeMap: Map<String?, String?> = HashMap<String?, String?>()
|
||||||
|
typeMap?.put(JAVA_LANG_BYTE, "byte")
|
||||||
|
typeMap?.put(JAVA_LANG_SHORT, "short")
|
||||||
|
typeMap?.put(JAVA_LANG_INTEGER, "int")
|
||||||
|
typeMap?.put(JAVA_LANG_LONG, "long")
|
||||||
|
typeMap?.put(JAVA_LANG_FLOAT, "float")
|
||||||
|
typeMap?.put(JAVA_LANG_DOUBLE, "double")
|
||||||
|
typeMap?.put(JAVA_LANG_CHARACTER, "char")
|
||||||
|
var expectedStr: String? = expected.getCanonicalText()
|
||||||
|
var actualStr: String? = actual.getCanonicalText()
|
||||||
|
var o1: Boolean = AstUtil.getOrElse(typeMap, actualStr, "")?.equals(expectedStr)!!
|
||||||
|
var o2: Boolean = AstUtil.getOrElse(typeMap, expectedStr, "")?.equals(actualStr)!!
|
||||||
|
return actualStr != expectedStr && (!(o1 xor o2))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -26,8 +26,6 @@ import java.text.MessageFormat;
|
|||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.jetbrains.jet.j2k.Converter.NOT_NULL_ANNOTATIONS;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ignatov
|
* @author ignatov
|
||||||
*/
|
*/
|
||||||
@@ -101,7 +99,7 @@ public class ConverterUtil {
|
|||||||
return counter;
|
return counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean isReadOnly(PsiElement element, PsiElement container) {
|
public static boolean isReadOnly(PsiElement element, PsiElement container) {
|
||||||
return countWritingAccesses(element, container) == 0;
|
return countWritingAccesses(element, container) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,7 +108,7 @@ public class ConverterUtil {
|
|||||||
PsiAnnotation[] annotations = modifierList.getAnnotations();
|
PsiAnnotation[] annotations = modifierList.getAnnotations();
|
||||||
for (PsiAnnotation a : annotations) {
|
for (PsiAnnotation a : annotations) {
|
||||||
String qualifiedName = a.getQualifiedName();
|
String qualifiedName = a.getQualifiedName();
|
||||||
if (qualifiedName != null && NOT_NULL_ANNOTATIONS.contains(qualifiedName)) {
|
if (qualifiedName != null && Converter.$classobj.NOT_NULL_ANNOTATIONS.contains(qualifiedName)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,68 +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.jet.j2k.util.AstUtil;
|
|
||||||
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ignatov
|
|
||||||
*/
|
|
||||||
public class Block extends Statement {
|
|
||||||
@NotNull
|
|
||||||
public final static Block EMPTY_BLOCK = new Block();
|
|
||||||
|
|
||||||
private List<Statement> myStatements;
|
|
||||||
private boolean myNotEmpty = false;
|
|
||||||
|
|
||||||
private Block() {
|
|
||||||
myStatements = new LinkedList<Statement>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Block(List<Statement> statements) {
|
|
||||||
myStatements = new LinkedList<Statement>();
|
|
||||||
myStatements = statements;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Block(List<Statement> statements, boolean notEmpty) {
|
|
||||||
myStatements = new LinkedList<Statement>();
|
|
||||||
myStatements = statements;
|
|
||||||
myNotEmpty = notEmpty;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isEmpty() {
|
|
||||||
return !myNotEmpty && myStatements.size() == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Statement> getStatements() {
|
|
||||||
return myStatements;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public String toKotlin() {
|
|
||||||
if (!isEmpty()) {
|
|
||||||
return "{" + N +
|
|
||||||
AstUtil.joinNodes(myStatements, N) + N +
|
|
||||||
"}";
|
|
||||||
}
|
|
||||||
return EMPTY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package org.jetbrains.jet.j2k.ast
|
||||||
|
|
||||||
|
import org.jetbrains.jet.j2k.util.AstUtil
|
||||||
|
import java.util.LinkedList
|
||||||
|
import java.util.List
|
||||||
|
|
||||||
|
public open class Block(val statements: List<Statement>, val notEmpty: Boolean = false): Statement() {
|
||||||
|
public override fun isEmpty(): Boolean {
|
||||||
|
return !notEmpty && statements.size() == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
public override fun toKotlin(): String {
|
||||||
|
if (!isEmpty()) {
|
||||||
|
return "{\n" + AstUtil.joinNodes(statements, "\n") + "\n}"
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
class object {
|
||||||
|
public val EMPTY_BLOCK: Block = Block(arrayList())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -36,7 +36,7 @@ public class CaseContainer extends Statement {
|
|||||||
if (s.getKind() != Kind.BREAK && s.getKind() != Kind.CONTINUE) {
|
if (s.getKind() != Kind.BREAK && s.getKind() != Kind.CONTINUE) {
|
||||||
newStatements.add(s);
|
newStatements.add(s);
|
||||||
}
|
}
|
||||||
myBlock = new Block(newStatements);
|
myBlock = new Block(newStatements, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ public open class Class(converter : Converter,
|
|||||||
private fun constructorToInit(f: Function): Function {
|
private fun constructorToInit(f: Function): Function {
|
||||||
val modifiers : Set<String> = HashSet<String>(f.getModifiers())
|
val modifiers : Set<String> = HashSet<String>(f.getModifiers())
|
||||||
modifiers.add(Modifier.STATIC)
|
modifiers.add(Modifier.STATIC)
|
||||||
val statements : List<Statement?> = f.block?.getStatements() ?: arrayList()
|
val statements : List<Statement> = f.block?.statements ?: arrayList()
|
||||||
statements.add(ReturnStatement(IdentifierImpl("__")))
|
statements.add(ReturnStatement(IdentifierImpl("__")))
|
||||||
val block : Block = Block(statements)
|
val block : Block = Block(statements)
|
||||||
val constructorTypeParameters : List<Element> = arrayList()
|
val constructorTypeParameters : List<Element> = arrayList()
|
||||||
|
|||||||
@@ -1,44 +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.jet.j2k.ast.types.Type;
|
|
||||||
import org.jetbrains.jet.j2k.util.AstUtil;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ignatov
|
|
||||||
*/
|
|
||||||
public class ExpressionList extends Expression {
|
|
||||||
private final List<Expression> myExpressions;
|
|
||||||
|
|
||||||
public ExpressionList(List<Expression> expressions, List<Type> types) {
|
|
||||||
myExpressions = expressions;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ExpressionList(List<Expression> expressions) {
|
|
||||||
myExpressions = expressions;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public String toKotlin() {
|
|
||||||
return AstUtil.joinNodes(myExpressions, COMMA_WITH_SPACE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package org.jetbrains.jet.j2k.ast
|
||||||
|
|
||||||
|
import org.jetbrains.jet.j2k.ast.types.Type
|
||||||
|
import org.jetbrains.jet.j2k.util.AstUtil
|
||||||
|
import java.util.List
|
||||||
|
|
||||||
|
public open class ExpressionList(val expressions: List<Expression>): Expression() {
|
||||||
|
public override fun toKotlin(): String = expressions.map { it.toKotlin() }.makeString(", ")
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@ import org.jetbrains.jet.j2k.util.AstUtil
|
|||||||
import java.util.LinkedList
|
import java.util.LinkedList
|
||||||
import java.util.List
|
import java.util.List
|
||||||
import java.util.Set
|
import java.util.Set
|
||||||
import org.jetbrains.jet.j2k.Converter.getDefaultInitializer
|
import org.jetbrains.jet.j2k.Converter
|
||||||
|
|
||||||
public open class Field(val identifier : Identifier,
|
public open class Field(val identifier : Identifier,
|
||||||
modifiers : Set<String>,
|
modifiers : Set<String>,
|
||||||
@@ -43,7 +43,7 @@ public open class Field(val identifier : Identifier,
|
|||||||
return declaration + ((if (isVal() && !isStatic() && writingAccesses == 1)
|
return declaration + ((if (isVal() && !isStatic() && writingAccesses == 1)
|
||||||
""
|
""
|
||||||
else
|
else
|
||||||
" = " + getDefaultInitializer(this)))
|
" = " + Converter.getDefaultInitializer(this)))
|
||||||
}
|
}
|
||||||
|
|
||||||
return declaration + " = " + initializer.toKotlin()
|
return declaration + " = " + initializer.toKotlin()
|
||||||
|
|||||||
@@ -1,50 +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.jet.j2k.util.AstUtil;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ignatov
|
|
||||||
*/
|
|
||||||
public class File extends Node {
|
|
||||||
private final String myPackageName;
|
|
||||||
private final List<Import> myImports;
|
|
||||||
private final List<Class> myClasses;
|
|
||||||
private final String myMainFunction;
|
|
||||||
|
|
||||||
public File(String packageName, List<Import> imports, List<Class> classes, String mainFunction) {
|
|
||||||
myPackageName = packageName;
|
|
||||||
myImports = imports;
|
|
||||||
myClasses = classes;
|
|
||||||
myMainFunction = mainFunction;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public String toKotlin() {
|
|
||||||
final String common = AstUtil.joinNodes(myImports, N) + N2 + AstUtil.joinNodes(myClasses, N) + N + myMainFunction;
|
|
||||||
if (myPackageName.isEmpty()) {
|
|
||||||
return common;
|
|
||||||
}
|
|
||||||
return "package" + SPACE + myPackageName + N +
|
|
||||||
common;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package org.jetbrains.jet.j2k.ast
|
||||||
|
|
||||||
|
import org.jetbrains.jet.j2k.util.AstUtil
|
||||||
|
import java.util.List
|
||||||
|
|
||||||
|
public open class File(val packageName: String,
|
||||||
|
val imports: List<Import>,
|
||||||
|
val classes: List<Class>,
|
||||||
|
val mainFunction: String): Node() {
|
||||||
|
|
||||||
|
public override fun toKotlin(): String {
|
||||||
|
val common: String = AstUtil.joinNodes(imports, "\n") + "\n\n" + AstUtil.joinNodes(classes, "\n") + "\n" + mainFunction
|
||||||
|
if (packageName.isEmpty()) {
|
||||||
|
return common
|
||||||
|
}
|
||||||
|
|
||||||
|
return "package " + packageName + "\n" + common
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,40 +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 Import extends Node {
|
|
||||||
private final String myName;
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return myName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Import(String name) {
|
|
||||||
myName = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public String toKotlin() {
|
|
||||||
return "import" + SPACE + myName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package org.jetbrains.jet.j2k.ast
|
||||||
|
|
||||||
|
|
||||||
|
public open class Import(val name: String): Node() {
|
||||||
|
public override fun toKotlin() = "import " + name
|
||||||
|
}
|
||||||
@@ -1,54 +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.jet.j2k.ast.types.Type;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ignatov
|
|
||||||
*/
|
|
||||||
public class LocalVariable extends Expression {
|
|
||||||
private final Identifier myIdentifier;
|
|
||||||
private final Set<String> myModifiersSet;
|
|
||||||
private final Type myType;
|
|
||||||
private final Expression myInitializer;
|
|
||||||
|
|
||||||
public LocalVariable(Identifier identifier, Set<String> modifiersSet, Type type, Expression initializer) {
|
|
||||||
myIdentifier = identifier;
|
|
||||||
myModifiersSet = modifiersSet;
|
|
||||||
myType = type;
|
|
||||||
myInitializer = initializer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasModifier(String modifier) {
|
|
||||||
return myModifiersSet.contains(modifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public String toKotlin() {
|
|
||||||
if (myInitializer.isEmpty()) {
|
|
||||||
return myIdentifier.toKotlin() + SPACE + COLON + SPACE + myType.toKotlin();
|
|
||||||
}
|
|
||||||
|
|
||||||
return myIdentifier.toKotlin() + SPACE + COLON + SPACE + myType.toKotlin() + SPACE +
|
|
||||||
EQUAL + SPACE + myInitializer.toKotlin();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package org.jetbrains.jet.j2k.ast
|
||||||
|
|
||||||
|
import org.jetbrains.jet.j2k.ast.types.Type
|
||||||
|
import java.util.Set
|
||||||
|
|
||||||
|
public open class LocalVariable(val identifier: Identifier,
|
||||||
|
val modifiersSet: Set<String>,
|
||||||
|
val `type`: Type,
|
||||||
|
val initializer: Expression): Expression() {
|
||||||
|
|
||||||
|
public open fun hasModifier(modifier: String): Boolean {
|
||||||
|
return modifiersSet.contains(modifier)
|
||||||
|
}
|
||||||
|
|
||||||
|
public override fun toKotlin(): String {
|
||||||
|
if (initializer.isEmpty()) {
|
||||||
|
return identifier.toKotlin() + " : " + `type`.toKotlin()
|
||||||
|
}
|
||||||
|
|
||||||
|
return identifier.toKotlin() + " : " + `type`.toKotlin() + " = " + initializer.toKotlin()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,39 +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 org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.jet.j2k.Converter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ignatov
|
|
||||||
*/
|
|
||||||
public class Dispatcher {
|
|
||||||
private ExpressionVisitor myExpressionVisitor;
|
|
||||||
|
|
||||||
public void setExpressionVisitor(final ExpressionVisitor expressionVisitor) {
|
|
||||||
this.myExpressionVisitor = expressionVisitor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Dispatcher(@NotNull Converter converter) {
|
|
||||||
myExpressionVisitor = new ExpressionVisitor(converter);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ExpressionVisitor getExpressionVisitor() {
|
|
||||||
return myExpressionVisitor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package org.jetbrains.jet.j2k.visitors
|
||||||
|
|
||||||
|
import org.jetbrains.jet.j2k.Converter
|
||||||
|
|
||||||
|
public open class Dispatcher(converter: Converter) {
|
||||||
|
public var expressionVisitor: ExpressionVisitor = ExpressionVisitor(converter)
|
||||||
|
}
|
||||||
@@ -5,7 +5,6 @@ import org.jetbrains.jet.j2k.Converter
|
|||||||
import org.jetbrains.jet.j2k.ast.*
|
import org.jetbrains.jet.j2k.ast.*
|
||||||
import org.jetbrains.jet.j2k.ast.types.Type
|
import org.jetbrains.jet.j2k.ast.types.Type
|
||||||
import java.util.List
|
import java.util.List
|
||||||
import org.jetbrains.jet.j2k.Converter.modifiersListToModifiersSet
|
|
||||||
import org.jetbrains.jet.j2k.ConverterUtil.isAnnotatedAsNotNull
|
import org.jetbrains.jet.j2k.ConverterUtil.isAnnotatedAsNotNull
|
||||||
|
|
||||||
public open class ElementVisitor(val myConverter : Converter) : JavaElementVisitor(), J2KVisitor {
|
public open class ElementVisitor(val myConverter : Converter) : JavaElementVisitor(), J2KVisitor {
|
||||||
@@ -22,14 +21,13 @@ public open class ElementVisitor(val myConverter : Converter) : JavaElementVisit
|
|||||||
public override fun visitLocalVariable(variable : PsiLocalVariable?) : Unit {
|
public override fun visitLocalVariable(variable : PsiLocalVariable?) : Unit {
|
||||||
val theVariable = variable!!
|
val theVariable = variable!!
|
||||||
myResult = LocalVariable(IdentifierImpl(theVariable.getName()),
|
myResult = LocalVariable(IdentifierImpl(theVariable.getName()),
|
||||||
modifiersListToModifiersSet(theVariable.getModifierList()),
|
Converter.modifiersListToModifiersSet(theVariable.getModifierList()),
|
||||||
myConverter.typeToType(theVariable.getType(), isAnnotatedAsNotNull(theVariable.getModifierList())),
|
myConverter.typeToType(theVariable.getType(), isAnnotatedAsNotNull(theVariable.getModifierList())),
|
||||||
myConverter.expressionToExpression(theVariable.getInitializer(), theVariable.getType()))
|
myConverter.expressionToExpression(theVariable.getInitializer(), theVariable.getType()))
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun visitExpressionList(list : PsiExpressionList?) : Unit {
|
public override fun visitExpressionList(list : PsiExpressionList?) : Unit {
|
||||||
myResult = ExpressionList(myConverter.expressionsToExpressionList(list!!.getExpressions()),
|
myResult = ExpressionList(myConverter.expressionsToExpressionList(list!!.getExpressions()))
|
||||||
myConverter.typesToTypeList(list!!.getExpressionTypes()))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun visitReferenceElement(reference : PsiJavaCodeReferenceElement?) : Unit {
|
public override fun visitReferenceElement(reference : PsiJavaCodeReferenceElement?) : Unit {
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.jetbrains.jet.j2k.Converter.isConstructorPrimary;
|
|
||||||
import static com.intellij.psi.CommonClassNames.*;
|
import static com.intellij.psi.CommonClassNames.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -236,7 +235,7 @@ public class ExpressionVisitor extends StatementVisitor {
|
|||||||
@Override
|
@Override
|
||||||
public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) {
|
public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) {
|
||||||
super.visitMethodCallExpression(expression);
|
super.visitMethodCallExpression(expression);
|
||||||
if (!SuperVisitor.isSuper(expression.getMethodExpression()) || !isInsidePrimaryConstructor(expression)) {
|
if (!SuperVisitor.$classobj.isSuper(expression.getMethodExpression()) || !isInsidePrimaryConstructor(expression)) {
|
||||||
myResult = // TODO: not resolved
|
myResult = // TODO: not resolved
|
||||||
new MethodCallExpression(
|
new MethodCallExpression(
|
||||||
getConverter().expressionToExpression(expression.getMethodExpression()),
|
getConverter().expressionToExpression(expression.getMethodExpression()),
|
||||||
@@ -274,7 +273,7 @@ public class ExpressionVisitor extends StatementVisitor {
|
|||||||
final boolean isNotConvertedClass = classReference != null && !getConverter().getClassIdentifiers().contains(classReference.getQualifiedName());
|
final boolean isNotConvertedClass = classReference != null && !getConverter().getClassIdentifiers().contains(classReference.getQualifiedName());
|
||||||
PsiExpressionList argumentList = expression.getArgumentList();
|
PsiExpressionList argumentList = expression.getArgumentList();
|
||||||
PsiExpression[] arguments = argumentList != null ? argumentList.getExpressions() : new PsiExpression[]{};
|
PsiExpression[] arguments = argumentList != null ? argumentList.getExpressions() : new PsiExpression[]{};
|
||||||
if (constructor == null || isConstructorPrimary(constructor) || isNotConvertedClass) {
|
if (constructor == null || Converter.$classobj.isConstructorPrimary(constructor) || isNotConvertedClass) {
|
||||||
return new NewClassExpression(
|
return new NewClassExpression(
|
||||||
getConverter().expressionToExpression(expression.getQualifier()),
|
getConverter().expressionToExpression(expression.getQualifier()),
|
||||||
getConverter().elementToElement(classReference),
|
getConverter().elementToElement(classReference),
|
||||||
@@ -419,7 +418,7 @@ public class ExpressionVisitor extends StatementVisitor {
|
|||||||
PsiElement context = expression.getContext();
|
PsiElement context = expression.getContext();
|
||||||
while (context != null) {
|
while (context != null) {
|
||||||
if (context instanceof PsiMethod && ((PsiMethod) context).isConstructor()) {
|
if (context instanceof PsiMethod && ((PsiMethod) context).isConstructor()) {
|
||||||
return !isConstructorPrimary((PsiMethod) context);
|
return !Converter.$classobj.isConstructorPrimary((PsiMethod) context);
|
||||||
}
|
}
|
||||||
context = context.getContext();
|
context = context.getContext();
|
||||||
}
|
}
|
||||||
@@ -430,7 +429,7 @@ public class ExpressionVisitor extends StatementVisitor {
|
|||||||
PsiElement context = expression.getContext();
|
PsiElement context = expression.getContext();
|
||||||
while (context != null) {
|
while (context != null) {
|
||||||
if (context instanceof PsiMethod && ((PsiMethod) context).isConstructor()) {
|
if (context instanceof PsiMethod && ((PsiMethod) context).isConstructor()) {
|
||||||
return isConstructorPrimary((PsiMethod) context);
|
return Converter.$classobj.isConstructorPrimary((PsiMethod) context);
|
||||||
}
|
}
|
||||||
context = context.getContext();
|
context = context.getContext();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import java.util.Collections;
|
|||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.jetbrains.jet.j2k.Converter.identifierToIdentifier;
|
|
||||||
import static org.jetbrains.jet.j2k.ConverterUtil.countWritingAccesses;
|
import static org.jetbrains.jet.j2k.ConverterUtil.countWritingAccesses;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -73,7 +72,7 @@ public class StatementVisitor extends ElementVisitor {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
myResult = new BreakStatement(
|
myResult = new BreakStatement(
|
||||||
identifierToIdentifier(statement.getLabelIdentifier())
|
Converter.$classobj.identifierToIdentifier(statement.getLabelIdentifier())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -86,7 +85,7 @@ public class StatementVisitor extends ElementVisitor {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
myResult = new ContinueStatement(
|
myResult = new ContinueStatement(
|
||||||
identifierToIdentifier(statement.getLabelIdentifier())
|
Converter.$classobj.identifierToIdentifier(statement.getLabelIdentifier())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -181,8 +180,8 @@ public class StatementVisitor extends ElementVisitor {
|
|||||||
getConverter().expressionToExpression(condition),
|
getConverter().expressionToExpression(condition),
|
||||||
new Block(
|
new Block(
|
||||||
Arrays.asList(getConverter().statementToStatement(body),
|
Arrays.asList(getConverter().statementToStatement(body),
|
||||||
new Block(Arrays.asList(getConverter().statementToStatement(update)))))));
|
new Block(Arrays.asList(getConverter().statementToStatement(update)), false)), false)));
|
||||||
myResult = new Block(forStatements);
|
myResult = new Block(forStatements, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,7 +219,7 @@ public class StatementVisitor extends ElementVisitor {
|
|||||||
public void visitLabeledStatement(@NotNull PsiLabeledStatement statement) {
|
public void visitLabeledStatement(@NotNull PsiLabeledStatement statement) {
|
||||||
super.visitLabeledStatement(statement);
|
super.visitLabeledStatement(statement);
|
||||||
myResult = new LabelStatement(
|
myResult = new LabelStatement(
|
||||||
identifierToIdentifier(statement.getLabelIdentifier()),
|
Converter.$classobj.identifierToIdentifier(statement.getLabelIdentifier()),
|
||||||
getConverter().statementToStatement(statement.getStatement())
|
getConverter().statementToStatement(statement.getStatement())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,58 +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 org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ignatov
|
|
||||||
*/
|
|
||||||
public class SuperVisitor extends JavaRecursiveElementVisitor {
|
|
||||||
@NotNull
|
|
||||||
private final HashSet<PsiExpressionList> myResolvedSuperCallParameters;
|
|
||||||
|
|
||||||
public SuperVisitor() {
|
|
||||||
myResolvedSuperCallParameters = new HashSet<PsiExpressionList>();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public HashSet<PsiExpressionList> getResolvedSuperCallParameters() {
|
|
||||||
return myResolvedSuperCallParameters;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) {
|
|
||||||
super.visitMethodCallExpression(expression);
|
|
||||||
if (isSuper(expression.getMethodExpression())) {
|
|
||||||
myResolvedSuperCallParameters.add(expression.getArgumentList());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static boolean isSuper(@NotNull PsiReference r) {
|
|
||||||
if (r.getCanonicalText().equals("super")) {
|
|
||||||
final PsiElement baseConstructor = r.resolve();
|
|
||||||
if (baseConstructor != null && baseConstructor instanceof PsiMethod && ((PsiMethod) baseConstructor).isConstructor()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package org.jetbrains.jet.j2k.visitors
|
||||||
|
|
||||||
|
import com.intellij.psi.*
|
||||||
|
import java.util.HashSet
|
||||||
|
|
||||||
|
public open class SuperVisitor(): JavaRecursiveElementVisitor() {
|
||||||
|
public val resolvedSuperCallParameters: HashSet<PsiExpressionList> = hashSet()
|
||||||
|
|
||||||
|
public override fun visitMethodCallExpression(expression: PsiMethodCallExpression?): Unit {
|
||||||
|
if (expression != null && isSuper(expression.getMethodExpression())) {
|
||||||
|
resolvedSuperCallParameters.add(expression.getArgumentList())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class object {
|
||||||
|
open fun isSuper(r: PsiReference): Boolean {
|
||||||
|
if (r.getCanonicalText().equals("super")) {
|
||||||
|
val baseConstructor: PsiElement? = r.resolve()
|
||||||
|
if (baseConstructor != null && baseConstructor is PsiMethod && baseConstructor.isConstructor()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,13 +10,13 @@ import org.jetbrains.jet.j2k.util.AstUtil
|
|||||||
import java.util.LinkedList
|
import java.util.LinkedList
|
||||||
import java.util.List
|
import java.util.List
|
||||||
|
|
||||||
public open class TypeVisitor(private val myConverter : Converter) : PsiTypeVisitor<Type?>(), J2KVisitor {
|
public open class TypeVisitor(private val myConverter : Converter) : PsiTypeVisitor<Type>(), J2KVisitor {
|
||||||
private var myResult : Type = EmptyType()
|
private var myResult : Type = EmptyType()
|
||||||
public open fun getResult() : Type {
|
public open fun getResult() : Type {
|
||||||
return myResult
|
return myResult
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun visitPrimitiveType(primitiveType: PsiPrimitiveType?) : Type? {
|
public override fun visitPrimitiveType(primitiveType: PsiPrimitiveType?) : Type {
|
||||||
val name : String = primitiveType?.getCanonicalText()!!
|
val name : String = primitiveType?.getCanonicalText()!!
|
||||||
val identifier : IdentifierImpl = IdentifierImpl(name)
|
val identifier : IdentifierImpl = IdentifierImpl(name)
|
||||||
if (name == "void") {
|
if (name == "void") {
|
||||||
@@ -28,19 +28,19 @@ public open class TypeVisitor(private val myConverter : Converter) : PsiTypeVisi
|
|||||||
else {
|
else {
|
||||||
myResult = PrimitiveType(identifier)
|
myResult = PrimitiveType(identifier)
|
||||||
}
|
}
|
||||||
return null
|
return myResult
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun visitArrayType(arrayType: PsiArrayType?) : Type? {
|
public override fun visitArrayType(arrayType: PsiArrayType?) : Type {
|
||||||
if (myResult is EmptyType) {
|
if (myResult is EmptyType) {
|
||||||
myResult = ArrayType(myConverter.typeToType(arrayType?.getComponentType()), true)
|
myResult = ArrayType(myConverter.typeToType(arrayType?.getComponentType()), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
return myResult
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun visitClassType(classType : PsiClassType?) : Type? {
|
public override fun visitClassType(classType : PsiClassType?) : Type {
|
||||||
if (classType == null) return null
|
if (classType == null) return myResult
|
||||||
val identifier : IdentifierImpl = constructClassTypeIdentifier(classType)
|
val identifier : IdentifierImpl = constructClassTypeIdentifier(classType)
|
||||||
val resolvedClassTypeParams : List<Type> = createRawTypesForResolvedReference(classType)
|
val resolvedClassTypeParams : List<Type> = createRawTypesForResolvedReference(classType)
|
||||||
if (classType.getParameterCount() == 0 && resolvedClassTypeParams.size() > 0) {
|
if (classType.getParameterCount() == 0 && resolvedClassTypeParams.size() > 0) {
|
||||||
@@ -49,7 +49,7 @@ public open class TypeVisitor(private val myConverter : Converter) : PsiTypeVisi
|
|||||||
else {
|
else {
|
||||||
myResult = ClassType(identifier, myConverter.typesToTypeList(classType.getParameters()).requireNoNulls(), true)
|
myResult = ClassType(identifier, myConverter.typesToTypeList(classType.getParameters()).requireNoNulls(), true)
|
||||||
}
|
}
|
||||||
return null
|
return myResult
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun constructClassTypeIdentifier(classType : PsiClassType) : IdentifierImpl {
|
private fun constructClassTypeIdentifier(classType : PsiClassType) : IdentifierImpl {
|
||||||
@@ -102,7 +102,7 @@ public open class TypeVisitor(private val myConverter : Converter) : PsiTypeVisi
|
|||||||
return typeParams
|
return typeParams
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun visitWildcardType(wildcardType : PsiWildcardType?) : Type? {
|
public override fun visitWildcardType(wildcardType : PsiWildcardType?) : Type {
|
||||||
if (wildcardType!!.isExtends()) {
|
if (wildcardType!!.isExtends()) {
|
||||||
myResult = OutProjectionType(myConverter.typeToType(wildcardType!!.getExtendsBound()))
|
myResult = OutProjectionType(myConverter.typeToType(wildcardType!!.getExtendsBound()))
|
||||||
}
|
}
|
||||||
@@ -113,12 +113,12 @@ public open class TypeVisitor(private val myConverter : Converter) : PsiTypeVisi
|
|||||||
else {
|
else {
|
||||||
myResult = StarProjectionType()
|
myResult = StarProjectionType()
|
||||||
}
|
}
|
||||||
return null
|
return myResult
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun visitEllipsisType(ellipsisType : PsiEllipsisType?) : Type? {
|
public override fun visitEllipsisType(ellipsisType : PsiEllipsisType?) : Type {
|
||||||
myResult = VarArg(myConverter.typeToType(ellipsisType?.getComponentType()))
|
myResult = VarArg(myConverter.typeToType(ellipsisType?.getComponentType()))
|
||||||
return null
|
return myResult
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun getConverter() : Converter = myConverter
|
public override fun getConverter() : Converter = myConverter
|
||||||
|
|||||||
Reference in New Issue
Block a user