| /* |
| * Copyright 2000-2014 JetBrains s.r.o. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.jetbrains.plugins.groovy.intentions.style; |
| |
| import com.intellij.codeInsight.generation.OverrideImplementExploreUtil; |
| import com.intellij.openapi.editor.Editor; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.openapi.util.Pair; |
| import com.intellij.psi.*; |
| import com.intellij.psi.codeStyle.JavaCodeStyleManager; |
| import com.intellij.psi.infos.CandidateInfo; |
| import com.intellij.util.IncorrectOperationException; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| import org.jetbrains.plugins.groovy.config.GroovyConfigUtils; |
| import org.jetbrains.plugins.groovy.intentions.base.Intention; |
| import org.jetbrains.plugins.groovy.intentions.base.PsiElementPredicate; |
| import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; |
| import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; |
| import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock; |
| import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; |
| import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrNewExpression; |
| import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousClassDefinition; |
| import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinitionBody; |
| import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; |
| import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement; |
| import org.jetbrains.plugins.groovy.refactoring.DefaultGroovyVariableNameValidator; |
| import org.jetbrains.plugins.groovy.refactoring.GroovyNameSuggestionUtil; |
| |
| import java.util.*; |
| |
| /** |
| * @author Maxim.Medvedev |
| */ |
| public class ReplaceAbstractClassInstanceByMapIntention extends Intention { |
| @NotNull |
| @Override |
| protected PsiElementPredicate getElementPredicate() { |
| return new MyPredicate(); |
| } |
| |
| @Override |
| protected void processIntention(@NotNull PsiElement psiElement, Project project, Editor editor) throws IncorrectOperationException { |
| PsiDocumentManager.getInstance(project).commitAllDocuments(); |
| |
| GrCodeReferenceElement ref = (GrCodeReferenceElement)psiElement; |
| final GrAnonymousClassDefinition anonymous = (GrAnonymousClassDefinition)ref.getParent(); |
| final GrNewExpression newExpr = (GrNewExpression)anonymous.getParent(); |
| |
| final PsiElement resolved = ref.resolve(); |
| assert resolved instanceof PsiClass;// && ((PsiClass)resolved).isInterface(); |
| |
| GrTypeDefinitionBody body = anonymous.getBody(); |
| assert body != null; |
| |
| List<Pair<PsiMethod, GrOpenBlock>> methods = new ArrayList<Pair<PsiMethod, GrOpenBlock>>(); |
| for (GrMethod method : body.getMethods()) { |
| methods.add(new Pair<PsiMethod, GrOpenBlock>(method, method.getBlock())); |
| } |
| |
| final PsiClass iface = (PsiClass)resolved; |
| final Collection<CandidateInfo> collection = OverrideImplementExploreUtil.getMethodsToOverrideImplement(anonymous, true); |
| for (CandidateInfo info : collection) { |
| methods.add(new Pair<PsiMethod, GrOpenBlock>((PsiMethod)info.getElement(), null)); |
| } |
| |
| StringBuilder buffer = new StringBuilder(); |
| if (methods.size() == 1) { |
| final Pair<PsiMethod, GrOpenBlock> pair = methods.get(0); |
| appendClosureTextByMethod(pair.getFirst(), buffer, pair.getSecond(), newExpr); |
| if (!GroovyConfigUtils.getInstance().isVersionAtLeast(psiElement, GroovyConfigUtils.GROOVY2_2)) { |
| buffer.append(" as ").append(iface.getQualifiedName()); |
| } |
| } |
| else { |
| buffer.append("["); |
| buffer.append("\n"); |
| for (Pair<PsiMethod, GrOpenBlock> pair : methods) { |
| final PsiMethod method = pair.getFirst(); |
| final GrOpenBlock block = pair.getSecond(); |
| buffer.append(method.getName()).append(": "); |
| appendClosureTextByMethod(method, buffer, block, newExpr); |
| buffer.append(",\n"); |
| } |
| if (!methods.isEmpty()) { |
| buffer.delete(buffer.length() - 2, buffer.length()); |
| buffer.append('\n'); |
| } |
| buffer.append("]"); |
| buffer.append(" as ").append(iface.getQualifiedName()); |
| } |
| |
| createAndAdjustNewExpression(project, newExpr, buffer); |
| } |
| |
| private static void createAndAdjustNewExpression(final Project project, |
| final GrNewExpression newExpression, |
| final StringBuilder buffer) throws IncorrectOperationException { |
| final GrExpression expr = GroovyPsiElementFactory.getInstance(project).createExpressionFromText(buffer.toString()); |
| final GrExpression safeTypeExpr = newExpression.replaceWithExpression(expr, false); |
| JavaCodeStyleManager.getInstance(project).shortenClassReferences(safeTypeExpr); |
| } |
| |
| private static void appendClosureTextByMethod(final PsiMethod method, |
| final StringBuilder buffer, |
| @Nullable GrOpenBlock block, |
| GroovyPsiElement context) { |
| final PsiParameterList list = method.getParameterList(); |
| buffer.append("{ "); |
| final PsiParameter[] parameters = list.getParameters(); |
| Set<String> generatedNames = new HashSet<String>(); |
| if (parameters.length > 0) { |
| final PsiParameter first = parameters[0]; |
| final PsiType type = first.getType(); |
| buffer.append(type.getCanonicalText()).append(" "); |
| buffer.append(createName(generatedNames, first, type, context)); |
| } |
| for (int i = 1; i < parameters.length; i++) { |
| buffer.append(", "); |
| final PsiParameter param = parameters[i]; |
| final PsiType type = param.getType(); |
| buffer.append(type.getCanonicalText()).append(" "); |
| String name = createName(generatedNames, param, type, context); |
| buffer.append(name); |
| } |
| if (parameters.length > 0) { |
| buffer.append(" ->"); |
| } |
| |
| if (block != null) { |
| final PsiElement lBrace = block.getLBrace(); |
| final PsiElement rBrace = block.getRBrace(); |
| for (PsiElement child = lBrace != null ? lBrace.getNextSibling() : block.getFirstChild(); |
| child != null && child != rBrace; |
| child = child.getNextSibling()) { |
| buffer.append(child.getText()); |
| } |
| } |
| buffer.append(" }"); |
| } |
| |
| private static String createName(final Set<String> generatedNames, final PsiParameter param, final PsiType type, GroovyPsiElement context) { |
| String name = param.getName(); |
| if (name == null) { |
| name = GroovyNameSuggestionUtil.suggestVariableNameByType(type, new DefaultGroovyVariableNameValidator(context, generatedNames))[0]; |
| assert name != null; |
| } |
| generatedNames.add(name); |
| return name; |
| } |
| |
| static class MyPredicate implements PsiElementPredicate { |
| @Override |
| public boolean satisfiedBy(PsiElement element) { |
| if (element instanceof GrCodeReferenceElement && element.getParent() instanceof GrAnonymousClassDefinition) { |
| final GrAnonymousClassDefinition anonymous = ((GrAnonymousClassDefinition)element.getParent()); |
| GrNewExpression newExpression = (GrNewExpression)anonymous.getParent(); |
| if (newExpression.getQualifier() == null && anonymous.getFields().length == 0) { |
| return true; |
| } |
| } |
| return false; |
| } |
| } |
| } |
| |
| |