@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> 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; }
@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 public static String getDefaultInitializer(@NotNull Field f) { if (f.getType().isNullable()) { return "null"; } else { 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 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); }