convert the converter

This commit is contained in:
Dmitry Jemerov
2012-05-25 19:16:39 +02:00
committed by Pavel V. Talanov
parent 2cd137b0ae
commit ae4404cdc4
24 changed files with 822 additions and 1179 deletions
-791
View File
@@ -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;
// }
}
+681
View File
@@ -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))
}
}
}
+2 -4
View File
@@ -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;
}
}
-68
View File
@@ -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;
}
}
+23
View File
@@ -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
+1 -1
View File
@@ -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(", ")
}
+2 -2
View File
@@ -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()
-50
View File
@@ -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;
}
}
+19
View File
@@ -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
}
}
-40
View File
@@ -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;
}
}
+6
View File
@@ -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