private static void processClassUsage(GrTypeDefinition psiClass, JavaChangeInfo changeInfo) {
    String name = psiClass.getName();

    GrMethod constructor =
        GroovyPsiElementFactory.getInstance(psiClass.getProject())
            .createConstructorFromText(
                name, ArrayUtil.EMPTY_STRING_ARRAY, ArrayUtil.EMPTY_STRING_ARRAY, "{}", null);

    GrModifierList list = constructor.getModifierList();
    if (psiClass.hasModifierProperty(PsiModifier.PRIVATE))
      list.setModifierProperty(PsiModifier.PRIVATE, true);
    if (psiClass.hasModifierProperty(PsiModifier.PROTECTED))
      list.setModifierProperty(PsiModifier.PROTECTED, true);
    if (!list.hasExplicitVisibilityModifiers()) {
      list.setModifierProperty(GrModifier.DEF, true);
    }

    constructor = (GrMethod) psiClass.add(constructor);
    processConstructor(constructor, changeInfo);
  }
  private static void startTemplate(
      GrTypeParameterList oldTypeParameterList,
      final Project project,
      final GrTypeDefinition psiClass,
      final GrTypeDefinition targetClass,
      boolean includeClassName) {
    PsiElementFactory jfactory = JavaPsiFacade.getElementFactory(project);
    final GroovyPsiElementFactory elementFactory = GroovyPsiElementFactory.getInstance(project);
    GrCodeReferenceElement ref = elementFactory.createCodeReferenceElementFromClass(psiClass);
    try {
      if (psiClass.isInterface()) {
        GrImplementsClause clause = targetClass.getImplementsClause();
        if (clause == null) {
          clause =
              (GrImplementsClause)
                  targetClass.addAfter(
                      elementFactory.createImplementsClause(),
                      targetClass.getNameIdentifierGroovy());
        }
        ref = (GrCodeReferenceElement) clause.add(ref);
      } else {
        GrExtendsClause clause = targetClass.getExtendsClause();
        if (clause == null) {
          clause =
              (GrExtendsClause)
                  targetClass.addAfter(
                      elementFactory.createExtendsClause(), targetClass.getNameIdentifierGroovy());
        }
        ref = (GrCodeReferenceElement) clause.add(ref);
      }
      if (psiClass.hasTypeParameters() || includeClassName) {
        final Editor editor =
            CodeInsightUtil.positionCursor(
                project, targetClass.getContainingFile(), targetClass.getLBrace());
        final TemplateBuilderImpl templateBuilder =
            editor == null || ApplicationManager.getApplication().isUnitTestMode()
                ? null
                : (TemplateBuilderImpl)
                    TemplateBuilderFactory.getInstance().createTemplateBuilder(targetClass);

        if (includeClassName && templateBuilder != null) {
          templateBuilder.replaceElement(targetClass.getNameIdentifier(), targetClass.getName());
        }

        if (oldTypeParameterList != null) {
          for (PsiTypeParameter parameter : oldTypeParameterList.getTypeParameters()) {
            final PsiElement param =
                ref.getTypeArgumentList()
                    .add(elementFactory.createTypeElement(jfactory.createType(parameter)));
            if (templateBuilder != null) {
              templateBuilder.replaceElement(param, param.getText());
            }
          }
        }

        final GrTypeParameterList typeParameterList = targetClass.getTypeParameterList();
        assert typeParameterList != null;
        typeParameterList.replace(oldTypeParameterList);

        if (templateBuilder != null) {
          templateBuilder.setEndVariableBefore(ref);
          final Template template = templateBuilder.buildTemplate();
          template.addEndVariable();

          final PsiFile containingFile = targetClass.getContainingFile();

          PsiDocumentManager.getInstance(project)
              .doPostponedOperationsAndUnblockDocument(editor.getDocument());

          final TextRange textRange = targetClass.getTextRange();
          final int startClassOffset = textRange.getStartOffset();
          editor.getDocument().deleteString(textRange.getStartOffset(), textRange.getEndOffset());
          CreateFromUsageBaseFix.startTemplate(
              editor,
              template,
              project,
              new TemplateEditingAdapter() {
                @Override
                public void templateFinished(Template template, boolean brokenOff) {
                  chooseAndImplement(
                      psiClass,
                      project,
                      PsiTreeUtil.getParentOfType(
                          containingFile.findElementAt(startClassOffset), GrTypeDefinition.class),
                      editor);
                }
              },
              getTitle(psiClass));
        }
      }
    } catch (IncorrectOperationException e) {
      LOG.error(e);
    }
  }
  @Override
  public void collectMethods(
      @NotNull GrTypeDefinition typeDefinition, Collection<PsiMethod> collector) {
    if (typeDefinition.getName() == null) return;

    PsiModifierList modifierList = typeDefinition.getModifierList();
    if (modifierList == null) return;

    final PsiAnnotation tupleConstructor =
        modifierList.findAnnotation(GroovyCommonClassNames.GROOVY_TRANSFORM_TUPLE_CONSTRUCTOR);
    final boolean immutable =
        modifierList.findAnnotation(IMMUTABLE) != null
            || modifierList.findAnnotation(GroovyCommonClassNames.GROOVY_TRANSFORM_IMMUTABLE)
                != null;
    final PsiAnnotation canonical =
        modifierList.findAnnotation(GroovyCommonClassNames.GROOVY_TRANSFORM_CANONICAL);
    if (!immutable && canonical == null && tupleConstructor == null) {
      return;
    }

    if (tupleConstructor != null
        && typeDefinition.getCodeConstructors().length > 0
        && !PsiUtil.getAnnoAttributeValue(tupleConstructor, "force", false)) {
      return;
    }

    final GrLightMethodBuilder fieldsConstructor =
        new GrLightMethodBuilder(typeDefinition.getManager(), typeDefinition.getName());
    fieldsConstructor.setConstructor(true).setNavigationElement(typeDefinition);

    Set<String> excludes = new HashSet<String>();
    if (tupleConstructor != null) {
      for (String s : PsiUtil.getAnnoAttributeValue(tupleConstructor, "excludes", "").split(",")) {
        final String name = s.trim();
        if (StringUtil.isNotEmpty(name)) {
          excludes.add(name);
        }
      }
    }

    if (tupleConstructor != null) {
      final boolean superFields =
          PsiUtil.getAnnoAttributeValue(tupleConstructor, "includeSuperFields", false);
      final boolean superProperties =
          PsiUtil.getAnnoAttributeValue(tupleConstructor, "includeSuperProperties", false);
      if (superFields || superProperties) {
        addParametersForSuper(
            typeDefinition,
            fieldsConstructor,
            superFields,
            superProperties,
            new HashSet<PsiClass>(),
            excludes);
      }
    }

    addParameters(
        typeDefinition,
        fieldsConstructor,
        tupleConstructor == null
            || PsiUtil.getAnnoAttributeValue(tupleConstructor, "includeProperties", true),
        tupleConstructor != null
            ? PsiUtil.getAnnoAttributeValue(tupleConstructor, "includeFields", false)
            : canonical == null,
        !immutable,
        excludes);

    collector.add(fieldsConstructor.setContainingClass(typeDefinition));

    collector.add(
        new GrLightMethodBuilder(typeDefinition.getManager(), typeDefinition.getName())
            .addParameter("args", CommonClassNames.JAVA_UTIL_MAP, false)
            .setConstructor(true)
            .setContainingClass(typeDefinition));
  }