@Nullable
 private static PsiType getTypeFromMapAccess(@NotNull GrReferenceExpression ref) {
   // map access
   GrExpression qualifier = ref.getQualifierExpression();
   if (qualifier instanceof GrReferenceExpression) {
     if (((GrReferenceExpression) qualifier).resolve() instanceof PsiClass) return null;
   }
   if (qualifier != null) {
     PsiType qType = qualifier.getType();
     if (qType instanceof PsiClassType) {
       PsiClassType.ClassResolveResult qResult = ((PsiClassType) qType).resolveGenerics();
       PsiClass clazz = qResult.getElement();
       if (clazz != null) {
         PsiClass mapClass =
             JavaPsiFacade.getInstance(ref.getProject())
                 .findClass(CommonClassNames.JAVA_UTIL_MAP, ref.getResolveScope());
         if (mapClass != null && mapClass.getTypeParameters().length == 2) {
           PsiSubstitutor substitutor =
               TypeConversionUtil.getClassSubstitutor(mapClass, clazz, qResult.getSubstitutor());
           if (substitutor != null) {
             PsiType substituted = substitutor.substitute(mapClass.getTypeParameters()[1]);
             if (substituted != null) {
               return PsiImplUtil.normalizeWildcardTypeByPosition(substituted, ref);
             }
           }
         }
       }
     }
   }
   return null;
 }
  public static PsiType eliminateWildcards(PsiType type, final boolean eliminateInTypeArguments) {
    if (eliminateInTypeArguments && type instanceof PsiClassType) {
      PsiClassType classType = (PsiClassType) type;
      JavaResolveResult resolveResult = classType.resolveGenerics();
      PsiClass aClass = (PsiClass) resolveResult.getElement();
      if (aClass != null) {
        PsiManager manager = aClass.getManager();
        PsiTypeParameter[] typeParams = aClass.getTypeParameters();
        Map<PsiTypeParameter, PsiType> map = new HashMap<PsiTypeParameter, PsiType>();
        for (PsiTypeParameter typeParam : typeParams) {
          PsiType substituted = resolveResult.getSubstitutor().substitute(typeParam);
          if (substituted instanceof PsiWildcardType) {
            substituted = ((PsiWildcardType) substituted).getBound();
            if (substituted == null)
              substituted = TypeConversionUtil.typeParameterErasure(typeParam);
          }
          map.put(typeParam, substituted);
        }

        PsiElementFactory factory =
            JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
        PsiSubstitutor substitutor = factory.createSubstitutor(map);
        type = factory.createType(aClass, substitutor);
      }
    } else if (type instanceof PsiArrayType) {
      return eliminateWildcards(((PsiArrayType) type).getComponentType(), false).createArrayType();
    } else if (type instanceof PsiWildcardType) {
      final PsiType bound = ((PsiWildcardType) type).getBound();
      return bound != null ? bound : ((PsiWildcardType) type).getExtendsBound(); // object
    } else if (type instanceof PsiCapturedWildcardType && !eliminateInTypeArguments) {
      return eliminateWildcards(
          ((PsiCapturedWildcardType) type).getWildcard(), eliminateInTypeArguments);
    }
    return type;
  }
  @Nullable
  public static PsiType getExpectedClosureReturnType(GrClosableBlock closure) {
    final Set<PsiType> expectedTypes = getDefaultExpectedTypes(closure);

    List<PsiType> expectedReturnTypes = new ArrayList<PsiType>();
    for (PsiType expectedType : expectedTypes) {
      if (!(expectedType instanceof PsiClassType)) return null;

      final PsiClassType.ClassResolveResult resolveResult =
          ((PsiClassType) expectedType).resolveGenerics();
      final PsiClass resolved = resolveResult.getElement();
      if (resolved == null
          || !(GroovyCommonClassNames.GROOVY_LANG_CLOSURE.equals(resolved.getQualifiedName())))
        return null;

      final PsiTypeParameter[] typeParameters = resolved.getTypeParameters();
      if (typeParameters.length != 1) return null;

      final PsiTypeParameter expected = typeParameters[0];
      final PsiType expectedReturnType = resolveResult.getSubstitutor().substitute(expected);
      if (expectedReturnType == PsiType.VOID || expectedReturnType == null) return null;

      expectedReturnTypes.add(expectedReturnType);
    }

    return TypesUtil.getLeastUpperBoundNullable(expectedReturnTypes, closure.getManager());
  }
  private void markTypeParameterUsages(
      final PsiClass psiClass,
      PsiClassType migrationType,
      PsiReferenceParameterList referenceParameterList,
      final Map<PsiElement, Pair<PsiReference[], PsiType>> roots) {

    final PsiSubstitutor[] fullHierarchySubstitutor = {
      migrationType.resolveGenerics().getSubstitutor()
    };
    RefactoringHierarchyUtil.processSuperTypes(
        migrationType,
        new RefactoringHierarchyUtil.SuperTypeVisitor() {
          @Override
          public void visitType(PsiType aType) {
            fullHierarchySubstitutor[0] =
                fullHierarchySubstitutor[0].putAll(
                    ((PsiClassType) aType).resolveGenerics().getSubstitutor());
          }

          @Override
          public void visitClass(PsiClass aClass) {
            // do nothing
          }
        });

    final PsiClass resolvedClass =
        (PsiClass) ((PsiJavaCodeReferenceElement) referenceParameterList.getParent()).resolve();
    ;
    LOG.assertTrue(resolvedClass != null);
    final Set<PsiClass> superClasses = new HashSet<PsiClass>();
    superClasses.add(resolvedClass);
    InheritanceUtil.getSuperClasses(resolvedClass, superClasses, true);
    for (PsiClass superSuperClass : superClasses) {
      final TypeParameterSearcher parameterSearcher =
          new TypeParameterSearcher(superSuperClass.getTypeParameters());
      superSuperClass.accept(
          new JavaRecursiveElementVisitor() {
            @Override
            public void visitMethod(final PsiMethod method) {
              super.visitMethod(method);
              processMemberType(
                  method, parameterSearcher, psiClass, fullHierarchySubstitutor[0], roots);
              for (PsiParameter parameter : method.getParameterList().getParameters()) {
                processMemberType(
                    parameter, parameterSearcher, psiClass, fullHierarchySubstitutor[0], roots);
              }
            }

            @Override
            public void visitField(final PsiField field) {
              super.visitField(field);
              processMemberType(
                  field, parameterSearcher, psiClass, fullHierarchySubstitutor[0], roots);
            }
          });
    }
  }
Beispiel #5
0
  private static boolean changeClassTypeArgument(
      PsiMethod myMethod,
      Project project,
      PsiType superReturnType,
      PsiClass superClass,
      Editor editor,
      PsiType returnType) {
    if (superClass == null || !superClass.hasTypeParameters()) return true;
    final PsiClass superReturnTypeClass = PsiUtil.resolveClassInType(superReturnType);
    if (superReturnTypeClass == null
        || !(superReturnTypeClass instanceof PsiTypeParameter
            || superReturnTypeClass.hasTypeParameters())) return true;

    final PsiClass derivedClass = myMethod.getContainingClass();
    if (derivedClass == null) return true;

    final PsiReferenceParameterList referenceParameterList =
        findTypeArgumentsList(superClass, derivedClass);
    if (referenceParameterList == null) return true;

    final PsiElement resolve =
        ((PsiJavaCodeReferenceElement) referenceParameterList.getParent()).resolve();
    if (!(resolve instanceof PsiClass)) return true;
    final PsiClass baseClass = (PsiClass) resolve;

    if (returnType instanceof PsiPrimitiveType) {
      returnType = ((PsiPrimitiveType) returnType).getBoxedType(derivedClass);
    }

    final PsiSubstitutor superClassSubstitutor =
        TypeConversionUtil.getSuperClassSubstitutor(superClass, baseClass, PsiSubstitutor.EMPTY);
    final PsiType superReturnTypeInBaseClassType =
        superClassSubstitutor.substitute(superReturnType);
    final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(project).getResolveHelper();
    final PsiSubstitutor psiSubstitutor =
        resolveHelper.inferTypeArguments(
            PsiTypesUtil.filterUnusedTypeParameters(
                superReturnTypeInBaseClassType, baseClass.getTypeParameters()),
            new PsiType[] {superReturnTypeInBaseClassType},
            new PsiType[] {returnType},
            PsiUtil.getLanguageLevel(superClass));

    final TypeMigrationRules rules = new TypeMigrationRules();
    final PsiSubstitutor compoundSubstitutor =
        TypeConversionUtil.getSuperClassSubstitutor(superClass, derivedClass, PsiSubstitutor.EMPTY)
            .putAll(psiSubstitutor);
    rules.setBoundScope(new LocalSearchScope(derivedClass));
    TypeMigrationProcessor.runHighlightingTypeMigration(
        project,
        editor,
        rules,
        referenceParameterList,
        JavaPsiFacade.getElementFactory(project).createType(baseClass, compoundSubstitutor));

    return false;
  }
  private static boolean isPartiallySubstituted(PsiType type) {
    if (!(type instanceof PsiClassType)) return false;
    PsiType[] parameters = ((PsiClassType) type).getParameters();

    PsiClassType.ClassResolveResult classResolveResult = ((PsiClassType) type).resolveGenerics();
    PsiClass clazz = classResolveResult.getElement();
    if (clazz == null) return false;

    return clazz.getTypeParameters().length != parameters.length;
  }
 public ExtractClassProcessor(
     PsiClass sourceClass,
     List<PsiField> fields,
     List<PsiMethod> methods,
     List<PsiClass> classes,
     String packageName,
     MoveDestination moveDestination,
     String newClassName,
     String newVisibility,
     boolean generateAccessors,
     List<MemberInfo> enumConstants) {
   super(sourceClass.getProject());
   this.sourceClass = sourceClass;
   this.newPackageName = packageName;
   myMoveDestination = moveDestination;
   myNewVisibility = newVisibility;
   myGenerateAccessors = generateAccessors;
   this.enumConstants = new ArrayList<PsiField>();
   for (MemberInfo constant : enumConstants) {
     if (constant.isChecked()) {
       this.enumConstants.add((PsiField) constant.getMember());
     }
   }
   this.fields = new ArrayList<PsiField>(fields);
   this.methods = new ArrayList<PsiMethod>(methods);
   this.innerClasses = new ArrayList<PsiClass>(classes);
   this.newClassName = newClassName;
   delegateFieldName = calculateDelegateFieldName();
   requiresBackpointer =
       new BackpointerUsageVisitor(fields, innerClasses, methods, sourceClass)
           .backpointerRequired();
   if (requiresBackpointer) {
     ContainerUtil.addAll(typeParams, sourceClass.getTypeParameters());
   } else {
     final Set<PsiTypeParameter> typeParamSet = new HashSet<PsiTypeParameter>();
     final TypeParametersVisitor visitor = new TypeParametersVisitor(typeParamSet);
     for (PsiField field : fields) {
       field.accept(visitor);
     }
     for (PsiMethod method : methods) {
       method.accept(visitor);
       // do not include method's type parameters in class signature
       typeParamSet.removeAll(Arrays.asList(method.getTypeParameters()));
     }
     typeParams.addAll(typeParamSet);
   }
   myClass =
       new WriteCommandAction<PsiClass>(myProject, getCommandName()) {
         @Override
         protected void run(@NotNull Result<PsiClass> result) throws Throwable {
           result.setResult(buildClass());
         }
       }.execute().getResultObject();
   myExtractEnumProcessor = new ExtractEnumProcessor(myProject, this.enumConstants, myClass);
 }
Beispiel #8
0
 private void getVariantsFromQualifier(@NotNull GrExpression qualifier) {
   Project project = qualifier.getProject();
   PsiType qualifierType = qualifier.getType();
   final ResolveState state = ResolveState.initial();
   if (qualifierType == null || qualifierType == PsiType.VOID) {
     if (qualifier instanceof GrReferenceExpression) {
       PsiElement resolved = ((GrReferenceExpression) qualifier).resolve();
       if (resolved instanceof PsiPackage || resolved instanceof PsiVariable) {
         resolved.processDeclarations(myProcessor, state, null, myRefExpr);
         return;
       }
     }
     getVariantsFromQualifierType(TypesUtil.getJavaLangObject(qualifier), project);
   } else if (qualifierType instanceof PsiIntersectionType) {
     for (PsiType conjunct : ((PsiIntersectionType) qualifierType).getConjuncts()) {
       getVariantsFromQualifierType(conjunct, project);
     }
   } else if (qualifierType instanceof GrTraitType) {
     GrTypeDefinition definition = ((GrTraitType) qualifierType).getMockTypeDefinition();
     if (definition != null) {
       PsiClassType classType = JavaPsiFacade.getElementFactory(project).createType(definition);
       getVariantsFromQualifierType(classType, project);
     } else {
       getVariantsFromQualifierType(((GrTraitType) qualifierType).getExprType(), project);
       for (PsiClassType traitType : ((GrTraitType) qualifierType).getTraitTypes()) {
         getVariantsFromQualifierType(traitType, project);
       }
     }
   } else {
     getVariantsFromQualifierType(qualifierType, project);
     if (qualifier instanceof GrReferenceExpression
         && !PsiUtil.isSuperReference(qualifier)
         && !PsiUtil.isInstanceThisRef(qualifier)) {
       PsiElement resolved = ((GrReferenceExpression) qualifier).resolve();
       if (resolved instanceof PsiClass) { // //omitted .class
         GlobalSearchScope scope = myRefExpr.getResolveScope();
         PsiClass javaLangClass = PsiUtil.getJavaLangClass(resolved, scope);
         if (javaLangClass != null) {
           PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
           PsiTypeParameter[] typeParameters = javaLangClass.getTypeParameters();
           if (typeParameters.length == 1) {
             substitutor = substitutor.put(typeParameters[0], qualifierType);
           }
           PsiType javaLangClassType =
               JavaPsiFacade.getElementFactory(myRefExpr.getProject())
                   .createType(javaLangClass, substitutor);
           ResolveUtil.processAllDeclarations(javaLangClassType, myProcessor, state, myRefExpr);
         }
       }
     }
   }
 }
  private void putAllInternal(@NotNull PsiClass parentClass, PsiType[] mappings) {
    final PsiTypeParameter[] params = parentClass.getTypeParameters();

    for (int i = 0; i < params.length; i++) {
      PsiTypeParameter param = params[i];
      assert param != null;
      if (mappings != null && mappings.length > i) {
        mySubstitutionMap.put(param, mappings[i]);
      } else {
        mySubstitutionMap.put(param, null);
      }
    }
  }
    private boolean processClass(
        PsiClass resolve,
        PsiSubstitutor originalSubstitutor,
        final Map<PsiTypeParameter, PsiType> substMap) {
      final PsiTypeParameter[] params = resolve.getTypeParameters();
      for (final PsiTypeParameter param : params) {
        final PsiType original = originalSubstitutor.substitute(param);
        if (original == null) {
          substMap.put(param, null);
        } else {
          final PsiType substituted = substituteInternal(original);
          if (substituted == null) return false;
          substMap.put(param, substituted);
        }
      }
      if (resolve.hasModifierProperty(PsiModifier.STATIC)) return true;

      final PsiClass containingClass = resolve.getContainingClass();
      return containingClass == null
          || processClass(containingClass, originalSubstitutor, substMap);
    }
  public static PsiSubstitutor substituteByParameterName(
      final PsiClass psiClass, final PsiSubstitutor parentSubstitutor) {

    final Map<PsiTypeParameter, PsiType> substitutionMap = parentSubstitutor.getSubstitutionMap();
    final List<PsiType> result = new ArrayList<PsiType>(substitutionMap.size());
    for (PsiTypeParameter typeParameter : psiClass.getTypeParameters()) {
      final String name = typeParameter.getName();
      final PsiTypeParameter key =
          ContainerUtil.find(
              substitutionMap.keySet(),
              new Condition<PsiTypeParameter>() {
                @Override
                public boolean value(final PsiTypeParameter psiTypeParameter) {
                  return name.equals(psiTypeParameter.getName());
                }
              });
      if (key != null) {
        result.add(substitutionMap.get(key));
      }
    }
    return PsiSubstitutor.EMPTY.putAll(
        psiClass, result.toArray(PsiType.createArray(result.size())));
  }
 private static PsiClassType getEnumSuperType(
     @NotNull PsiClass psiClass, @NotNull PsiElementFactory factory) {
   PsiClassType superType;
   final PsiManager manager = psiClass.getManager();
   final PsiClass enumClass =
       JavaPsiFacade.getInstance(manager.getProject())
           .findClass("java.lang.Enum", psiClass.getResolveScope());
   if (enumClass == null) {
     try {
       superType = (PsiClassType) factory.createTypeFromText("java.lang.Enum", null);
     } catch (IncorrectOperationException e) {
       superType = null;
     }
   } else {
     final PsiTypeParameter[] typeParameters = enumClass.getTypeParameters();
     PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
     if (typeParameters.length == 1) {
       substitutor = substitutor.put(typeParameters[0], factory.createType(psiClass));
     }
     superType = new PsiImmediateClassType(enumClass, substitutor);
   }
   return superType;
 }
  private static Map<MethodSignature, HierarchicalMethodSignature> buildMethodHierarchy(
      PsiClass aClass,
      PsiSubstitutor substitutor,
      final boolean includePrivates,
      final Set<PsiClass> visited,
      boolean isInRawContext) {
    Map<MethodSignature, HierarchicalMethodSignature> result =
        new LinkedHashMap<MethodSignature, HierarchicalMethodSignature>();
    final Map<MethodSignature, List<PsiMethod>> sameParameterErasureMethods =
        new THashMap<MethodSignature, List<PsiMethod>>(
            MethodSignatureUtil.METHOD_PARAMETERS_ERASURE_EQUALITY);

    Map<MethodSignature, HierarchicalMethodSignatureImpl> map =
        new THashMap<MethodSignature, HierarchicalMethodSignatureImpl>(
            new TObjectHashingStrategy<MethodSignature>() {
              @Override
              public int computeHashCode(MethodSignature signature) {
                return MethodSignatureUtil.METHOD_PARAMETERS_ERASURE_EQUALITY.computeHashCode(
                    signature);
              }

              @Override
              public boolean equals(MethodSignature o1, MethodSignature o2) {
                if (!MethodSignatureUtil.METHOD_PARAMETERS_ERASURE_EQUALITY.equals(o1, o2))
                  return false;
                List<PsiMethod> list = sameParameterErasureMethods.get(o1);
                boolean toCheckReturnType = list != null && list.size() > 1;
                if (!toCheckReturnType) return true;
                PsiType returnType1 =
                    ((MethodSignatureBackedByPsiMethod) o1).getMethod().getReturnType();
                PsiType returnType2 =
                    ((MethodSignatureBackedByPsiMethod) o2).getMethod().getReturnType();
                if (returnType1 == null && returnType2 == null) return true;
                if (returnType1 == null || returnType2 == null) return false;

                PsiType erasure1 =
                    TypeConversionUtil.erasure(o1.getSubstitutor().substitute(returnType1));
                PsiType erasure2 =
                    TypeConversionUtil.erasure(o2.getSubstitutor().substitute(returnType2));
                return erasure1.equals(erasure2);
              }
            });

    for (PsiMethod method : aClass.getMethods()) {
      if (!method.isValid()) {
        throw new PsiInvalidElementAccessException(
            method, "class.valid=" + aClass.isValid() + "; name=" + method.getName());
      }
      if (!includePrivates && method.hasModifierProperty(PsiModifier.PRIVATE)) continue;
      final MethodSignatureBackedByPsiMethod signature =
          MethodSignatureBackedByPsiMethod.create(method, substitutor, isInRawContext);
      HierarchicalMethodSignatureImpl newH = new HierarchicalMethodSignatureImpl(signature);

      List<PsiMethod> list = sameParameterErasureMethods.get(signature);
      if (list == null) {
        list = new SmartList<PsiMethod>();
        sameParameterErasureMethods.put(signature, list);
      }
      list.add(method);

      LOG.assertTrue(newH.getMethod().isValid());
      result.put(signature, newH);
      map.put(signature, newH);
    }

    for (PsiClassType superType : aClass.getSuperTypes()) {
      PsiClassType.ClassResolveResult superTypeResolveResult = superType.resolveGenerics();
      PsiClass superClass = superTypeResolveResult.getElement();
      if (superClass == null) continue;
      if (!visited.add(superClass)) continue; // cyclic inheritance
      final PsiSubstitutor superSubstitutor = superTypeResolveResult.getSubstitutor();
      PsiSubstitutor finalSubstitutor =
          obtainFinalSubstitutor(superClass, superSubstitutor, substitutor, isInRawContext);

      final boolean isInRawContextSuper =
          (isInRawContext || PsiUtil.isRawSubstitutor(superClass, superSubstitutor))
              && superClass.getTypeParameters().length != 0;
      Map<MethodSignature, HierarchicalMethodSignature> superResult =
          buildMethodHierarchy(superClass, finalSubstitutor, false, visited, isInRawContextSuper);
      visited.remove(superClass);

      List<Pair<MethodSignature, HierarchicalMethodSignature>> flattened =
          new ArrayList<Pair<MethodSignature, HierarchicalMethodSignature>>();
      for (Map.Entry<MethodSignature, HierarchicalMethodSignature> entry : superResult.entrySet()) {
        HierarchicalMethodSignature hms = entry.getValue();
        MethodSignature signature = entry.getKey();
        PsiClass containingClass = hms.getMethod().getContainingClass();
        List<HierarchicalMethodSignature> supers =
            new ArrayList<HierarchicalMethodSignature>(hms.getSuperSignatures());
        for (HierarchicalMethodSignature aSuper : supers) {
          PsiClass superContainingClass = aSuper.getMethod().getContainingClass();
          if (containingClass != null
              && superContainingClass != null
              && !containingClass.isInheritor(superContainingClass, true)) {
            // methods must be inherited from unrelated classes, so flatten hierarchy here
            // class C implements SAM1, SAM2 { void methodimpl() {} }
            // hms.getSuperSignatures().remove(aSuper);
            flattened.add(
                new Pair<MethodSignature, HierarchicalMethodSignature>(signature, aSuper));
          }
        }
        putInMap(aClass, result, map, hms, signature);
      }
      for (Pair<MethodSignature, HierarchicalMethodSignature> pair : flattened) {
        putInMap(aClass, result, map, pair.second, pair.first);
      }
    }

    for (Map.Entry<MethodSignature, HierarchicalMethodSignatureImpl> entry : map.entrySet()) {
      HierarchicalMethodSignatureImpl hierarchicalMethodSignature = entry.getValue();
      MethodSignature methodSignature = entry.getKey();
      if (result.get(methodSignature) == null
          && PsiUtil.isAccessible(
              aClass.getProject(), hierarchicalMethodSignature.getMethod(), aClass, aClass)) {
        LOG.assertTrue(hierarchicalMethodSignature.getMethod().isValid());
        result.put(methodSignature, hierarchicalMethodSignature);
      }
    }

    return result;
  }
Beispiel #14
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);
  }