@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())); return result; }
@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<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 static List<Statement> createInitStatementsFromFields( @NotNull List<? extends Field> fields) { List<Statement> result = new LinkedList<Statement>(); for (Field f : fields) { String identifierToKotlin = f.getIdentifier().toKotlin(); result.add(new DummyStringExpression(identifierToKotlin + " = " + "_" + identifierToKotlin)); } return result; }
private static boolean isOverrideObjectDirect(@NotNull PsiMethod method) { List<HierarchicalMethodSignature> superSignatures = method.getHierarchicalMethodSignature().getSuperSignatures(); if (superSignatures.size() == 1) { PsiClass containingClass = superSignatures.get(0).getMethod().getContainingClass(); String qualifiedName = containingClass != null ? containingClass.getQualifiedName() : ""; if (qualifiedName != null && qualifiedName.equals(JAVA_LANG_OBJECT)) { return true; } } return false; }
@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 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) { String id = f.getIdentifier().toKotlin(); result.add(initializers.get(id)); } return s + "(" + AstUtil.join(result, ", ") + ")"; }
@NotNull private File fileToFile(PsiJavaFile javaFile, List<String> additionalImports) { 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 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); }
@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 public List<String> createConversions( @NotNull PsiPolyadicExpression expression, PsiType expectedType) { PsiExpression[] arguments = expression.getOperands(); int length = arguments.length; List<String> conversions = new LinkedList<String>(); List<PsiType> expectedTypes = Collections.nCopies(length, expectedType); List<PsiType> actualTypes = new LinkedList<PsiType>(); for (PsiExpression e : arguments) actualTypes.add(e.getType()); assert actualTypes.size() == expectedTypes.size() : "The type list must have the same length"; for (int i = 0; i < actualTypes.size(); i++) conversions.add(i, createConversionForExpression(arguments[i], expectedTypes.get(i))); return conversions; }
@NotNull public List<String> createConversions(@NotNull PsiCallExpression expression) { PsiExpressionList argumentList = expression.getArgumentList(); PsiExpression[] arguments = argumentList != null ? argumentList.getExpressions() : new PsiExpression[] {}; List<String> conversions = new LinkedList<String>(); //noinspection UnusedDeclaration for (PsiExpression a : arguments) { conversions.add(""); } PsiMethod resolve = expression.resolveMethod(); if (resolve != null) { List<PsiType> expectedTypes = new LinkedList<PsiType>(); List<PsiType> actualTypes = new LinkedList<PsiType>(); for (PsiParameter p : resolve.getParameterList().getParameters()) expectedTypes.add(p.getType()); for (PsiExpression e : arguments) actualTypes.add(e.getType()); if (conversions.size() == actualTypes.size() && actualTypes.size() == expectedTypes.size()) { for (int i = 0; i < actualTypes.size(); i++) conversions.set(i, createConversionForExpression(arguments[i], expectedTypes.get(i))); } } return conversions; }
@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 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 List<Type> typesToTypeList(@NotNull PsiType[] types) { List<Type> result = new LinkedList<Type>(); for (PsiType t : types) result.add(typeToType(t)); return result; }
@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 List<Expression> expressionsToExpressionList(@NotNull PsiExpression[] expressions) { List<Expression> result = new LinkedList<Expression>(); for (PsiExpression e : expressions) result.add(expressionToExpression(e)); 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 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<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 public Class classToClass(@NotNull PsiClass psiClass) { Set<String> modifiers = modifiersListToModifiersSet(psiClass.getModifierList()); List<Field> fields = fieldsToFieldList(psiClass.getFields(), psiClass); List<Element> typeParameters = elementsToElementList(psiClass.getTypeParameters()); List<Type> implementsTypes = typesToNotNullableTypeList(psiClass.getImplementsListTypes()); List<Type> extendsTypes = typesToNotNullableTypeList(psiClass.getExtendsListTypes()); IdentifierImpl name = new IdentifierImpl(psiClass.getName()); 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) SuperVisitor visitor = new SuperVisitor(); psiClass.accept(visitor); Collection<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) { List<Field> finalOrWithEmptyInitializer = getFinalOrWithEmptyInitializer(fields); Map<String, String> initializers = new HashMap<String, String>(); for (Member m : members) { // and modify secondaries if (m.getKind() == INode.Kind.CONSTRUCTOR) { Function f = (Function) m; if (!((Constructor) f).isPrimary()) { for (Field fo : finalOrWithEmptyInitializer) { String init = getDefaultInitializer(fo); initializers.put(fo.getIdentifier().toKotlin(), init); } List<Statement> newStatements = new LinkedList<Statement>(); for (Statement s : f.getBlock().getStatements()) { boolean isRemoved = false; if (s.getKind() == INode.Kind.ASSIGNMENT_EXPRESSION) { AssignmentExpression assignmentExpression = (AssignmentExpression) s; if (assignmentExpression.getLeft().getKind() == INode.Kind.CALL_CHAIN) { for (Field fo : finalOrWithEmptyInitializer) { 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(), 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); }