public IntroduceParameterObjectProcessor(
      String className,
      String packageName,
      MoveDestination moveDestination,
      PsiMethod method,
      VariableData[] parameters,
      boolean keepMethodAsDelegate,
      final boolean useExistingClass,
      final boolean createInnerClass,
      String newVisibility,
      boolean generateAccessors) {
    super(method.getProject());
    myMoveDestination = moveDestination;
    this.method = method;
    this.className = className;
    this.packageName = packageName;
    this.keepMethodAsDelegate = keepMethodAsDelegate;
    myUseExistingClass = useExistingClass;
    myCreateInnerClass = createInnerClass;
    myNewVisibility = newVisibility;
    myGenerateAccessors = generateAccessors;
    this.parameters = new ArrayList<ParameterChunk>();
    for (VariableData parameter : parameters) {
      this.parameters.add(new ParameterChunk(parameter));
    }
    final PsiParameterList parameterList = method.getParameterList();
    final PsiParameter[] methodParams = parameterList.getParameters();
    paramsToMerge = new int[parameters.length];
    for (int p = 0; p < parameters.length; p++) {
      VariableData parameter = parameters[p];
      for (int i = 0; i < methodParams.length; i++) {
        final PsiParameter methodParam = methodParams[i];
        if (parameter.variable.equals(methodParam)) {
          paramsToMerge[p] = i;
          break;
        }
      }
    }
    final Set<PsiTypeParameter> typeParamSet = new HashSet<PsiTypeParameter>();
    final PsiTypeVisitor<Object> typeParametersVisitor =
        new PsiTypeVisitor<Object>() {
          @Override
          public Object visitClassType(PsiClassType classType) {
            final PsiClass referent = classType.resolve();
            if (referent instanceof PsiTypeParameter) {
              typeParamSet.add((PsiTypeParameter) referent);
            }
            return super.visitClassType(classType);
          }
        };
    for (VariableData parameter : parameters) {
      parameter.type.accept(typeParametersVisitor);
    }
    typeParams = new ArrayList<PsiTypeParameter>(typeParamSet);

    final String qualifiedName = StringUtil.getQualifiedName(packageName, className);
    final GlobalSearchScope scope = GlobalSearchScope.allScope(myProject);
    existingClass = JavaPsiFacade.getInstance(myProject).findClass(qualifiedName, scope);
  }
  private void fixJavadocForConstructor(PsiClass psiClass) {
    final PsiDocComment docComment = method.getDocComment();
    if (docComment != null) {
      final List<PsiDocTag> mergedTags = new ArrayList<PsiDocTag>();
      final PsiDocTag[] paramTags = docComment.findTagsByName("param");
      for (PsiDocTag paramTag : paramTags) {
        final PsiElement[] dataElements = paramTag.getDataElements();
        if (dataElements.length > 0) {
          if (dataElements[0] instanceof PsiDocParamRef) {
            final PsiReference reference = dataElements[0].getReference();
            if (reference != null) {
              final PsiElement resolve = reference.resolve();
              if (resolve instanceof PsiParameter) {
                final int parameterIndex =
                    method.getParameterList().getParameterIndex((PsiParameter) resolve);
                if (ArrayUtil.find(paramsToMerge, parameterIndex) < 0) continue;
              }
            }
          }
          mergedTags.add((PsiDocTag) paramTag.copy());
        }
      }

      PsiMethod compatibleParamObjectConstructor = null;
      if (myExistingClassCompatibleConstructor != null
          && myExistingClassCompatibleConstructor.getDocComment() == null) {
        compatibleParamObjectConstructor = myExistingClassCompatibleConstructor;
      } else if (!myUseExistingClass) {
        compatibleParamObjectConstructor = psiClass.getConstructors()[0];
      }

      if (compatibleParamObjectConstructor != null) {
        PsiDocComment psiDocComment =
            JavaPsiFacade.getElementFactory(myProject).createDocCommentFromText("/**\n*/");
        psiDocComment =
            (PsiDocComment)
                compatibleParamObjectConstructor.addBefore(
                    psiDocComment, compatibleParamObjectConstructor.getFirstChild());

        for (PsiDocTag tag : mergedTags) {
          psiDocComment.add(tag);
        }
      }
    }
  }