@Override
  public <M1 extends PsiNamedElement, P1 extends ParameterInfo> ReadWriteAccessDetector.Access collectInternalUsages(Collection<? super FixableUsageInfo> usages,
                                                                                                                     PsiMethod overridingMethod,
                                                                                                                     IntroduceParameterObjectClassDescriptor<M1, P1> classDescriptor,
                                                                                                                     P1 parameterInfo,
                                                                                                                     String mergedParamName) {
    final LocalSearchScope localSearchScope = new LocalSearchScope(overridingMethod);
    final PsiParameter[] params = overridingMethod.getParameterList().getParameters();
    final PsiParameter parameter = params[parameterInfo.getOldIndex()];
    final ReadWriteAccessDetector detector = ReadWriteAccessDetector.findDetector(parameter);
    assert detector != null;
    
    final List<PsiReferenceExpression> readUsages = new ArrayList<>();
    final List<PsiReferenceExpression> readWriteUsages = new ArrayList<>();
    final List<PsiReferenceExpression> writeUsages = new ArrayList<>();
    
    ReferencesSearch.search(parameter, localSearchScope).forEach(reference -> {
         final PsiElement refElement = reference.getElement();
         if (refElement instanceof PsiReferenceExpression paramUsage) {
           List<PsiReferenceExpression> list = switch (detector.getExpressionAccess(refElement)) {
             case Read -> readUsages;
             case ReadWrite -> readWriteUsages;
             case Write -> writeUsages;
           };
           list.add(paramUsage);
         }
         return true;
       }
    );

    ReadWriteAccessDetector.Access access =
      readWriteUsages.isEmpty() && writeUsages.isEmpty() ? ReadWriteAccessDetector.Access.Read : ReadWriteAccessDetector.Access.Write;

    if (access == ReadWriteAccessDetector.Access.Read && readUsages.isEmpty()) {
      return null;
    }

    final String setter = classDescriptor.getSetterName(parameterInfo, overridingMethod);
    final String getter = classDescriptor.getGetterName(parameterInfo, overridingMethod, access);
    
    readUsages.stream()
      .map(paramUsage -> new ReplaceParameterReferenceWithCall(paramUsage, mergedParamName, getter)).forEach(usages::add);
    readWriteUsages.stream()
      .map(paramUsage -> new ReplaceParameterIncrementDecrement(paramUsage, mergedParamName, setter, getter))
      .forEach(usages::add);
    writeUsages.stream()
      .map(paramUsage -> new ReplaceParameterAssignmentWithCall(paramUsage, mergedParamName, setter, getter))
      .forEach(usages::add);

    return access;
  }
@Override
  public <M1 extends PsiNamedElement, P1 extends ParameterInfo> ReadWriteAccessDetector.Access collectInternalUsages(Collection<? super FixableUsageInfo> usages,
                                                                                                                     PsiMethod overridingMethod,
                                                                                                                     IntroduceParameterObjectClassDescriptor<M1, P1> classDescriptor,
                                                                                                                     P1 parameterInfo,
                                                                                                                     String mergedParamName)