void (final PsiElement element, final GrParameterListOwner owner, final Collection<PsiElement> occurrences, final boolean createNewFirstParam, @Nullable final String mapParamName, final boolean specifyMapType) { final GrParameter param = getAppropriateParameter(element); assert param != null; final String paramName = param.getName(); final String mapName = createNewFirstParam ? mapParamName : getFirstParameter(owner).getName(); final Project project = element.getProject(); final Runnable runnable = () -> { final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(project); final GrParameterList list = owner.getParameterList(); final int index = list.getParameterNumber(param); if (!createNewFirstParam && index <= 0) { // bad undo return; } //Remove old arguments from occurrences //final List<GrCall> calls = getCallOccurrences(occurrences); try { for (PsiElement occurrence : occurrences) { GrReferenceExpression refExpr = null; GroovyResolveResult resolveResult = null; boolean isExplicitGetterCall = false; if (occurrence instanceof GrReferenceExpression) { final PsiElement parent = occurrence.getParent(); if (parent instanceof GrCall) { refExpr = (GrReferenceExpression)occurrence; resolveResult = refExpr.advancedResolve(); final PsiElement resolved = resolveResult.getElement(); if (resolved instanceof PsiMethod && GroovyPropertyUtils.isSimplePropertyGetter(((PsiMethod)resolved)) && //check for explicit getter call ((PsiMethod)resolved).getName().equals(refExpr.getReferenceName())) { isExplicitGetterCall = true; } } else if (parent instanceof GrReferenceExpression) { resolveResult = ((GrReferenceExpression)parent).advancedResolve(); final PsiElement resolved = resolveResult.getElement(); if (resolved instanceof PsiMethod && "call".equals(((PsiMethod)resolved).getName())) { refExpr = (GrReferenceExpression)parent; } } } if (refExpr == null) continue; final GrSignature signature = generateSignature(owner, refExpr); if (signature == null) continue; GrCall call; if (isExplicitGetterCall) { PsiElement parent = refExpr.getParent(); LOG.assertTrue(parent instanceof GrCall); parent = parent.getParent(); if (parent instanceof GrReferenceExpression && "call".equals(((GrReferenceExpression)parent).getReferenceName())) { parent = parent.getParent(); } if (parent instanceof GrCall) { call = (GrCall)parent; } else { continue; } } else { call = (GrCall)refExpr.getParent(); } if (resolveResult.isInvokedOnProperty()) { final PsiElement parent = call.getParent(); if (parent instanceof GrCall) { call = (GrCall)parent; } else if (parent instanceof GrReferenceExpression && parent.getParent() instanceof GrCall) { final PsiElement resolved = ((GrReferenceExpression)parent).resolve(); if (resolved instanceof PsiMethod && "call".equals(((PsiMethod)resolved).getName())) { call = (GrCall)parent.getParent(); } else { continue; } } } final GrClosureSignatureUtil.ArgInfo<PsiElement>[] argInfos = GrClosureSignatureUtil.mapParametersToArguments(signature, call); if (argInfos == null) continue; final GrClosureSignatureUtil.ArgInfo<PsiElement> argInfo = argInfos[index]; final GrNamedArgument namedArg; if (argInfo.isMultiArg) { if (argInfo.args.isEmpty()) continue; String arg = "[" + StringUtil.join(ContainerUtil.map(argInfo.args, element1 -> element1.getText()), ", ") + "]"; for (PsiElement psiElement : argInfo.args) { psiElement.delete(); } namedArg = factory.createNamedArgument(paramName, factory.createExpressionFromText(arg)); } else { if (argInfo.args.isEmpty()) continue; final PsiElement argument = argInfo.args.iterator().next(); assert argument instanceof GrExpression; namedArg = factory.createNamedArgument(paramName, (GrExpression)argument); argument.delete(); } call.addNamedArgument(namedArg); } } catch (IncorrectOperationException e) { LOG.error(e); } //Replace of occurrences of old parameter in closure/method final Collection<PsiReference> references = ReferencesSearch.search(param).findAll(); for (PsiReference ref : references) { final PsiElement elt = ref.getElement(); if (elt instanceof GrReferenceExpression expr) { final GrExpression newExpr = factory.createExpressionFromText(mapName + "." + paramName); expr.replaceWithExpression(newExpr, true); } } //Add new map parameter to closure/method if it's necessary if (createNewFirstParam) { try { final GrParameter newParam = factory.createParameter(mapName, specifyMapType ? MAP_TYPE_TEXT : "", null); list.addAfter(newParam, null); } catch (IncorrectOperationException e) { LOG.error(e); } } //Eliminate obsolete parameter from parameter list param.delete(); }; CommandProcessor.getInstance().executeCommand(project, () -> ApplicationManager.getApplication().runWriteAction(runnable), GroovyBundle.message("convert.parameter.to.map.entry.title"), null); }