private void prepareParameters() {
    if (myParametersPrepared) {
      return;
    }
    final Set<Pair<String, Boolean>> withoutType = new HashSet<>();
    final Map<Pair<String, Boolean>, String> paramTypes = Maps.newHashMap();
    for (DocstringParam param : myAddedParams) {
      if (param.getType() == null) {
        withoutType.add(Pair.create(param.getName(), param.isReturnValue()));
      }
      else {
        // leave only the last type for parameter
        paramTypes.put(Pair.create(param.getName(), param.isReturnValue()), param.getType());
      }
    }

    // Sanitize parameters
    PySignature signature = null;
    if (myDocStringOwner instanceof PyAstFunction && myUseTypesFromDebuggerSignature) {
      signature = PySignatureCacheManager.getInstance(myDocStringOwner.getProject()).findSignature((PyAstFunction)myDocStringOwner);
    }
    final DocStringFormat format = myDocStringFormat;
    final ArrayList<DocstringParam> filtered = new ArrayList<>();
    final Set<Pair<String, Boolean>> processed = new HashSet<>();
    for (DocstringParam param : myAddedParams) {
      final Pair<String, Boolean> paramCoordinates = Pair.create(param.getName(), param.isReturnValue());
      if (processed.contains(paramCoordinates)) {
        continue;
      }
      if (param.getType() == null) {
        String type = paramTypes.get(paramCoordinates);
        if (type == null && PyCodeInsightSettings.getInstance().INSERT_TYPE_DOCSTUB) {
          if (signature != null) {
            type = StringUtil.notNullize(param.isReturnValue() ?
                                         signature.getReturnTypeQualifiedName() :
                                         signature.getArgTypeQualifiedName(param.getName()));
          }
          else {
            type = "";
          }
        }
        if (type != null) {
          // Google and Numpy docstring formats combine type and description in single declaration, thus
          // if both declaration with type and without it are requested, we should filter out duplicates
          if (format != DocStringFormat.GOOGLE && format != DocStringFormat.NUMPY) {
            // In reST and Epydoc for each parameter add two tags, e.g. in reST (Sphinx)
            // :param foo:
            // :type foo:
            filtered.add(param);
          }
          filtered.add(new DocstringParam(param.getName(), type, param.isReturnValue()));
        }
        else {
          // no type was given and it's not required by settings
          filtered.add(param);
        }
      }
      else if (!withoutType.contains(paramCoordinates)) {
        filtered.add(param);
      }
      processed.add(paramCoordinates);
    }
    myAddedParams.clear();
    myAddedParams.addAll(filtered);
    myParametersPrepared = true;
  }
private void prepareParameters()