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.List;
|
||||
|
||||
import static org.jetbrains.jet.j2k.Converter.NOT_NULL_ANNOTATIONS;
|
||||
|
||||
/**
|
||||
* @author ignatov
|
||||
*/
|
||||
@@ -101,7 +99,7 @@ public class ConverterUtil {
|
||||
return counter;
|
||||
}
|
||||
|
||||
static boolean isReadOnly(PsiElement element, PsiElement container) {
|
||||
public static boolean isReadOnly(PsiElement element, PsiElement container) {
|
||||
return countWritingAccesses(element, container) == 0;
|
||||
}
|
||||
|
||||
@@ -110,7 +108,7 @@ public class ConverterUtil {
|
||||
PsiAnnotation[] annotations = modifierList.getAnnotations();
|
||||
for (PsiAnnotation a : annotations) {
|
||||
String qualifiedName = a.getQualifiedName();
|
||||
if (qualifiedName != null && NOT_NULL_ANNOTATIONS.contains(qualifiedName)) {
|
||||
if (qualifiedName != null && Converter.$classobj.NOT_NULL_ANNOTATIONS.contains(qualifiedName)) {
|
||||
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) {
|
||||
newStatements.add(s);
|
||||
}
|
||||
myBlock = new Block(newStatements);
|
||||
myBlock = new Block(newStatements, false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -65,7 +65,7 @@ public open class Class(converter : Converter,
|
||||
private fun constructorToInit(f: Function): Function {
|
||||
val modifiers : Set<String> = HashSet<String>(f.getModifiers())
|
||||
modifiers.add(Modifier.STATIC)
|
||||
val statements : List<Statement?> = f.block?.getStatements() ?: arrayList()
|
||||
val statements : List<Statement> = f.block?.statements ?: arrayList()
|
||||
statements.add(ReturnStatement(IdentifierImpl("__")))
|
||||
val block : Block = Block(statements)
|
||||
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.List
|
||||
import java.util.Set
|
||||
import org.jetbrains.jet.j2k.Converter.getDefaultInitializer
|
||||
import org.jetbrains.jet.j2k.Converter
|
||||
|
||||
public open class Field(val identifier : Identifier,
|
||||
modifiers : Set<String>,
|
||||
@@ -43,7 +43,7 @@ public open class Field(val identifier : Identifier,
|
||||
return declaration + ((if (isVal() && !isStatic() && writingAccesses == 1)
|
||||
""
|
||||
else
|
||||
" = " + getDefaultInitializer(this)))
|
||||
" = " + Converter.getDefaultInitializer(this)))
|
||||
}
|
||||
|
||||
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.types.Type
|
||||
import java.util.List
|
||||
import org.jetbrains.jet.j2k.Converter.modifiersListToModifiersSet
|
||||
import org.jetbrains.jet.j2k.ConverterUtil.isAnnotatedAsNotNull
|
||||
|
||||
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 {
|
||||
val theVariable = variable!!
|
||||
myResult = LocalVariable(IdentifierImpl(theVariable.getName()),
|
||||
modifiersListToModifiersSet(theVariable.getModifierList()),
|
||||
Converter.modifiersListToModifiersSet(theVariable.getModifierList()),
|
||||
myConverter.typeToType(theVariable.getType(), isAnnotatedAsNotNull(theVariable.getModifierList())),
|
||||
myConverter.expressionToExpression(theVariable.getInitializer(), theVariable.getType()))
|
||||
}
|
||||
|
||||
public override fun visitExpressionList(list : PsiExpressionList?) : Unit {
|
||||
myResult = ExpressionList(myConverter.expressionsToExpressionList(list!!.getExpressions()),
|
||||
myConverter.typesToTypeList(list!!.getExpressionTypes()))
|
||||
myResult = ExpressionList(myConverter.expressionsToExpressionList(list!!.getExpressions()))
|
||||
}
|
||||
|
||||
public override fun visitReferenceElement(reference : PsiJavaCodeReferenceElement?) : Unit {
|
||||
|
||||
@@ -29,7 +29,6 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.jet.j2k.Converter.isConstructorPrimary;
|
||||
import static com.intellij.psi.CommonClassNames.*;
|
||||
|
||||
/**
|
||||
@@ -236,7 +235,7 @@ public class ExpressionVisitor extends StatementVisitor {
|
||||
@Override
|
||||
public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) {
|
||||
super.visitMethodCallExpression(expression);
|
||||
if (!SuperVisitor.isSuper(expression.getMethodExpression()) || !isInsidePrimaryConstructor(expression)) {
|
||||
if (!SuperVisitor.$classobj.isSuper(expression.getMethodExpression()) || !isInsidePrimaryConstructor(expression)) {
|
||||
myResult = // TODO: not resolved
|
||||
new MethodCallExpression(
|
||||
getConverter().expressionToExpression(expression.getMethodExpression()),
|
||||
@@ -274,7 +273,7 @@ public class ExpressionVisitor extends StatementVisitor {
|
||||
final boolean isNotConvertedClass = classReference != null && !getConverter().getClassIdentifiers().contains(classReference.getQualifiedName());
|
||||
PsiExpressionList argumentList = expression.getArgumentList();
|
||||
PsiExpression[] arguments = argumentList != null ? argumentList.getExpressions() : new PsiExpression[]{};
|
||||
if (constructor == null || isConstructorPrimary(constructor) || isNotConvertedClass) {
|
||||
if (constructor == null || Converter.$classobj.isConstructorPrimary(constructor) || isNotConvertedClass) {
|
||||
return new NewClassExpression(
|
||||
getConverter().expressionToExpression(expression.getQualifier()),
|
||||
getConverter().elementToElement(classReference),
|
||||
@@ -419,7 +418,7 @@ public class ExpressionVisitor extends StatementVisitor {
|
||||
PsiElement context = expression.getContext();
|
||||
while (context != null) {
|
||||
if (context instanceof PsiMethod && ((PsiMethod) context).isConstructor()) {
|
||||
return !isConstructorPrimary((PsiMethod) context);
|
||||
return !Converter.$classobj.isConstructorPrimary((PsiMethod) context);
|
||||
}
|
||||
context = context.getContext();
|
||||
}
|
||||
@@ -430,7 +429,7 @@ public class ExpressionVisitor extends StatementVisitor {
|
||||
PsiElement context = expression.getContext();
|
||||
while (context != null) {
|
||||
if (context instanceof PsiMethod && ((PsiMethod) context).isConstructor()) {
|
||||
return isConstructorPrimary((PsiMethod) context);
|
||||
return Converter.$classobj.isConstructorPrimary((PsiMethod) context);
|
||||
}
|
||||
context = context.getContext();
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.jet.j2k.Converter.identifierToIdentifier;
|
||||
import static org.jetbrains.jet.j2k.ConverterUtil.countWritingAccesses;
|
||||
|
||||
/**
|
||||
@@ -73,7 +72,7 @@ public class StatementVisitor extends ElementVisitor {
|
||||
}
|
||||
else {
|
||||
myResult = new BreakStatement(
|
||||
identifierToIdentifier(statement.getLabelIdentifier())
|
||||
Converter.$classobj.identifierToIdentifier(statement.getLabelIdentifier())
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -86,7 +85,7 @@ public class StatementVisitor extends ElementVisitor {
|
||||
}
|
||||
else {
|
||||
myResult = new ContinueStatement(
|
||||
identifierToIdentifier(statement.getLabelIdentifier())
|
||||
Converter.$classobj.identifierToIdentifier(statement.getLabelIdentifier())
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -181,8 +180,8 @@ public class StatementVisitor extends ElementVisitor {
|
||||
getConverter().expressionToExpression(condition),
|
||||
new Block(
|
||||
Arrays.asList(getConverter().statementToStatement(body),
|
||||
new Block(Arrays.asList(getConverter().statementToStatement(update)))))));
|
||||
myResult = new Block(forStatements);
|
||||
new Block(Arrays.asList(getConverter().statementToStatement(update)), false)), false)));
|
||||
myResult = new Block(forStatements, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,7 +219,7 @@ public class StatementVisitor extends ElementVisitor {
|
||||
public void visitLabeledStatement(@NotNull PsiLabeledStatement statement) {
|
||||
super.visitLabeledStatement(statement);
|
||||
myResult = new LabelStatement(
|
||||
identifierToIdentifier(statement.getLabelIdentifier()),
|
||||
Converter.$classobj.identifierToIdentifier(statement.getLabelIdentifier()),
|
||||
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.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()
|
||||
public open fun getResult() : Type {
|
||||
return myResult
|
||||
}
|
||||
|
||||
public override fun visitPrimitiveType(primitiveType: PsiPrimitiveType?) : Type? {
|
||||
public override fun visitPrimitiveType(primitiveType: PsiPrimitiveType?) : Type {
|
||||
val name : String = primitiveType?.getCanonicalText()!!
|
||||
val identifier : IdentifierImpl = IdentifierImpl(name)
|
||||
if (name == "void") {
|
||||
@@ -28,19 +28,19 @@ public open class TypeVisitor(private val myConverter : Converter) : PsiTypeVisi
|
||||
else {
|
||||
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) {
|
||||
myResult = ArrayType(myConverter.typeToType(arrayType?.getComponentType()), true)
|
||||
}
|
||||
|
||||
return null
|
||||
return myResult
|
||||
}
|
||||
|
||||
public override fun visitClassType(classType : PsiClassType?) : Type? {
|
||||
if (classType == null) return null
|
||||
public override fun visitClassType(classType : PsiClassType?) : Type {
|
||||
if (classType == null) return myResult
|
||||
val identifier : IdentifierImpl = constructClassTypeIdentifier(classType)
|
||||
val resolvedClassTypeParams : List<Type> = createRawTypesForResolvedReference(classType)
|
||||
if (classType.getParameterCount() == 0 && resolvedClassTypeParams.size() > 0) {
|
||||
@@ -49,7 +49,7 @@ public open class TypeVisitor(private val myConverter : Converter) : PsiTypeVisi
|
||||
else {
|
||||
myResult = ClassType(identifier, myConverter.typesToTypeList(classType.getParameters()).requireNoNulls(), true)
|
||||
}
|
||||
return null
|
||||
return myResult
|
||||
}
|
||||
|
||||
private fun constructClassTypeIdentifier(classType : PsiClassType) : IdentifierImpl {
|
||||
@@ -102,7 +102,7 @@ public open class TypeVisitor(private val myConverter : Converter) : PsiTypeVisi
|
||||
return typeParams
|
||||
}
|
||||
|
||||
public override fun visitWildcardType(wildcardType : PsiWildcardType?) : Type? {
|
||||
public override fun visitWildcardType(wildcardType : PsiWildcardType?) : Type {
|
||||
if (wildcardType!!.isExtends()) {
|
||||
myResult = OutProjectionType(myConverter.typeToType(wildcardType!!.getExtendsBound()))
|
||||
}
|
||||
@@ -113,12 +113,12 @@ public open class TypeVisitor(private val myConverter : Converter) : PsiTypeVisi
|
||||
else {
|
||||
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()))
|
||||
return null
|
||||
return myResult
|
||||
}
|
||||
|
||||
public override fun getConverter() : Converter = myConverter
|
||||
|
||||
Reference in New Issue
Block a user