Merge branch 'upsource-master'
authorEvgeny Pasynkov <Evgeny.Pasynkov@jetbrains.com>
Wed, 4 Jul 2012 09:48:36 +0000 (11:48 +0200)
committerEvgeny Pasynkov <Evgeny.Pasynkov@jetbrains.com>
Wed, 4 Jul 2012 09:48:36 +0000 (11:48 +0200)
Conflicts:
java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementUtil.java
plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties
plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java

1  2 
java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementUtil.java

index 44b079c84a81c96e1502e3b1a2ce549b33acfb31,33fc5b5ef8d611de89f95645689786e1d49e28d9..c45adeebd78ad9bb65debeaba6e6c7c053acc363
- /*
-  * Copyright 2000-2011 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 com.intellij.codeInsight.generation;
- import com.intellij.codeInsight.AnnotationUtil;
- import com.intellij.codeInsight.CodeInsightActionHandler;
- import com.intellij.codeInsight.CodeInsightBundle;
- import com.intellij.codeInsight.MethodImplementor;
- import com.intellij.codeInsight.intention.AddAnnotationFix;
- import com.intellij.featureStatistics.FeatureUsageTracker;
- import com.intellij.featureStatistics.ProductivityFeatureNames;
- import com.intellij.icons.AllIcons;
- import com.intellij.ide.fileTemplates.FileTemplate;
- import com.intellij.ide.fileTemplates.FileTemplateManager;
- import com.intellij.ide.fileTemplates.FileTemplateUtil;
- import com.intellij.ide.fileTemplates.JavaTemplateUtil;
- import com.intellij.ide.util.MemberChooser;
- import com.intellij.ide.util.PropertiesComponent;
- import com.intellij.lang.java.JavaLanguage;
- import com.intellij.openapi.actionSystem.*;
- import com.intellij.openapi.application.ApplicationManager;
- import com.intellij.openapi.application.Result;
- import com.intellij.openapi.command.WriteCommandAction;
- import com.intellij.openapi.diagnostic.Logger;
- import com.intellij.openapi.editor.Editor;
- import com.intellij.openapi.editor.ScrollType;
- import com.intellij.openapi.extensions.Extensions;
- import com.intellij.openapi.fileEditor.FileEditorManager;
- import com.intellij.openapi.fileEditor.OpenFileDescriptor;
- import com.intellij.openapi.fileTypes.FileType;
- import com.intellij.openapi.fileTypes.FileTypeManager;
- import com.intellij.openapi.keymap.Keymap;
- import com.intellij.openapi.keymap.KeymapManager;
- import com.intellij.openapi.module.Module;
- import com.intellij.openapi.module.ModuleUtil;
- import com.intellij.openapi.project.Project;
- import com.intellij.openapi.ui.DialogWrapper;
- import com.intellij.openapi.ui.Messages;
- import com.intellij.openapi.util.Ref;
- import com.intellij.openapi.util.text.StringUtil;
- import com.intellij.psi.*;
- import com.intellij.psi.codeStyle.CodeStyleManager;
- import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
- import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
- import com.intellij.psi.codeStyle.JavaCodeStyleManager;
- import com.intellij.psi.impl.source.jsp.jspJava.JspClass;
- import com.intellij.psi.infos.CandidateInfo;
- import com.intellij.psi.javadoc.PsiDocComment;
- import com.intellij.psi.search.GlobalSearchScope;
- import com.intellij.psi.util.*;
- import com.intellij.util.ArrayUtil;
- import com.intellij.util.Function;
- import com.intellij.util.IncorrectOperationException;
- import com.intellij.util.containers.ContainerUtil;
- import org.jetbrains.annotations.NonNls;
- import org.jetbrains.annotations.NotNull;
- import org.jetbrains.annotations.Nullable;
- import javax.swing.*;
- import java.awt.event.ActionEvent;
- import java.awt.event.InputEvent;
- import java.awt.event.KeyEvent;
- import java.util.*;
- public class OverrideImplementUtil {
-   private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.generation.OverrideImplementUtil");
-   @NonNls private static final String PROP_COMBINED_OVERRIDE_IMPLEMENT = "OverrideImplement.combined";
-   private OverrideImplementUtil() {
-   }
-   @NotNull
-   public static Collection<CandidateInfo> getMethodsToOverrideImplement(PsiClass aClass, boolean toImplement) {
-     return getMapToOverrideImplement(aClass, toImplement).values();
-   }
-   @NotNull
-   public static Collection<MethodSignature> getMethodSignaturesToImplement(@NotNull PsiClass aClass) {
-     return getMapToOverrideImplement(aClass, true).keySet();
-   }
-   @NotNull
-   public static Collection<MethodSignature> getMethodSignaturesToOverride(@NotNull PsiClass aClass) {
-     return getMapToOverrideImplement(aClass, false).keySet();
-   }
-   @NotNull
-   private static Map<MethodSignature, CandidateInfo> getMapToOverrideImplement(PsiClass aClass, boolean toImplement) {
-     Map<MethodSignature, PsiMethod> abstracts = new LinkedHashMap<MethodSignature,PsiMethod>();
-     Map<MethodSignature, PsiMethod> finals = new LinkedHashMap<MethodSignature,PsiMethod>();
-     Map<MethodSignature, PsiMethod> concretes = new LinkedHashMap<MethodSignature,PsiMethod>();
-     LOG.assertTrue(aClass.isValid());
-     Collection<HierarchicalMethodSignature> allMethodSigs = aClass.getVisibleSignatures();
-     PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(aClass.getProject()).getResolveHelper();
-     for (HierarchicalMethodSignature signature : allMethodSigs) {
-       PsiMethod method = signature.getMethod();
-       LOG.assertTrue(method.isValid(), aClass);
-       if (method.hasModifierProperty(PsiModifier.STATIC) || !resolveHelper.isAccessible(method, aClass, aClass)) continue;
-       PsiClass hisClass = method.getContainingClass();
-       if (hisClass == null) continue;
-       // filter non-immediate super constructors
-       if (method.isConstructor() && (!aClass.isInheritor(hisClass, false) || aClass instanceof PsiAnonymousClass || aClass.isEnum())) {
-         continue;
-       }
-       // filter already implemented
-       if (MethodSignatureUtil.findMethodBySignature(aClass, signature, false) != null) {
-         continue;
-       }
-       if (method.hasModifierProperty(PsiModifier.FINAL)) {
-         finals.put(signature, method);
-         continue;
-       }
-       Map<MethodSignature, PsiMethod> map = hisClass.isInterface() || method.hasModifierProperty(PsiModifier.ABSTRACT) ? abstracts : concretes;
-       PsiMethod other = map.get(signature);
-       if (other == null || preferLeftForImplement(method, other)) {
-         map.put(signature, method);
-       }
-     }
-     final Map<MethodSignature, CandidateInfo> result = new TreeMap<MethodSignature,CandidateInfo>(new MethodSignatureComparator());
-     if (toImplement || aClass.isInterface()) {
-       collectMethodsToImplement(aClass, abstracts, finals, concretes, result);
-     }
-     else {
-       for (Map.Entry<MethodSignature, PsiMethod> entry : concretes.entrySet()) {
-         MethodSignature signature = entry.getKey();
-         PsiMethod concrete = entry.getValue();
-         if (finals.get(signature) == null) {
-           PsiMethod abstractOne = abstracts.get(signature);
-           if (abstractOne == null || !abstractOne.getContainingClass().isInheritor(concrete.getContainingClass(), true) ||
-               CommonClassNames.JAVA_LANG_OBJECT.equals(concrete.getContainingClass().getQualifiedName())) {
-             PsiSubstitutor subst = GenerateMembersUtil.correctSubstitutor(concrete, signature.getSubstitutor());
-             CandidateInfo info = new CandidateInfo(concrete, subst);
-             result.put(signature, info);
-           }
-         }
-       }
-     }
-     return result;
-   }
-   public static void collectMethodsToImplement(PsiClass aClass,
-                                                Map<MethodSignature, PsiMethod> abstracts,
-                                                Map<MethodSignature, PsiMethod> finals,
-                                                Map<MethodSignature, PsiMethod> concretes,
-                                                Map<MethodSignature, CandidateInfo> result) {
-     for (Map.Entry<MethodSignature, PsiMethod> entry : abstracts.entrySet()) {
-       MethodSignature signature = entry.getKey();
-       PsiMethod abstractOne = entry.getValue();
-       PsiMethod concrete = concretes.get(signature);
-       if (concrete == null
-           || PsiUtil.getAccessLevel(concrete.getModifierList()) < PsiUtil.getAccessLevel(abstractOne.getModifierList())
-           || !abstractOne.getContainingClass().isInterface() && abstractOne.getContainingClass().isInheritor(concrete.getContainingClass(), true)) {
-         if (finals.get(signature) == null) {
-           PsiSubstitutor subst = GenerateMembersUtil.correctSubstitutor(abstractOne, signature.getSubstitutor());
-           CandidateInfo info = new CandidateInfo(abstractOne, subst);
-           result.put(signature, info);
-         }
-       }
-     }
-     for (final MethodImplementor implementor : getImplementors()) {
-       for (final PsiMethod method : implementor.getMethodsToImplement(aClass)) {
-         MethodSignature signature = MethodSignatureUtil.createMethodSignature(method.getName(), method.getParameterList(),
-                                                                               method.getTypeParameterList(), PsiSubstitutor.EMPTY, method.isConstructor());
-         CandidateInfo info = new CandidateInfo(method, PsiSubstitutor.EMPTY);
-         result.put(signature, info);
-       }
-     }
-   }
-   private static boolean preferLeftForImplement(PsiMethod left, PsiMethod right) {
-     if (PsiUtil.getAccessLevel(left.getModifierList()) > PsiUtil.getAccessLevel(right.getModifierList())) return true;
-     if (!left.getContainingClass().isInterface()) return true;
-     if (!right.getContainingClass().isInterface()) return false;
-     // implement annotated method
-     PsiAnnotation[] leftAnnotations = left.getModifierList().getAnnotations();
-     PsiAnnotation[] rightAnnotations = right.getModifierList().getAnnotations();
-     return leftAnnotations.length > rightAnnotations.length;
-   }
-   private static MethodImplementor[] getImplementors() {
-     return Extensions.getExtensions(MethodImplementor.EXTENSION_POINT_NAME);
-   }
-   /**
-    * generate methods (with bodies) corresponding to given method declaration
-    *  there are maybe two method implementations for one declaration
-    * (e.g. EJB' create() -> ejbCreate(), ejbPostCreate() )
-    * @param aClass context for method implementations
-    * @param method method to override or implement
-    * @param toCopyJavaDoc true if copy JavaDoc from method declaration
-    * @return list of method prototypes
-    */
-   @NotNull
-   public static Collection<PsiMethod> overrideOrImplementMethod(PsiClass aClass, PsiMethod method, boolean toCopyJavaDoc) throws IncorrectOperationException {
-     final PsiClass containingClass = method.getContainingClass();
-     LOG.assertTrue(containingClass != null);
-     PsiSubstitutor substitutor = aClass.isInheritor(containingClass, true)
-                                  ? TypeConversionUtil.getSuperClassSubstitutor(containingClass, aClass, PsiSubstitutor.EMPTY)
-                                  : PsiSubstitutor.EMPTY;
-     return overrideOrImplementMethod(aClass, method, substitutor, toCopyJavaDoc, CodeStyleSettingsManager.getSettings(aClass.getProject()).INSERT_OVERRIDE_ANNOTATION);
-   }
-   public static boolean isInsertOverride(PsiMethod superMethod, PsiClass targetClass) {
-     if (!CodeStyleSettingsManager.getSettings(targetClass.getProject()).INSERT_OVERRIDE_ANNOTATION) {
-       return false;
-     }
-     return canInsertOverride(superMethod, targetClass);
-   }
-   public static boolean canInsertOverride(PsiMethod superMethod, PsiClass targetClass) {
-     if (superMethod.isConstructor() || superMethod.hasModifierProperty(PsiModifier.STATIC)) {
-       return false;
-     }
-     if (!PsiUtil.isLanguageLevel5OrHigher(targetClass)) {
-       return false;
-     }
-     if (PsiUtil.isLanguageLevel6OrHigher(targetClass)) return true;
-     if (targetClass.isInterface()) return true;
-     PsiClass superClass = superMethod.getContainingClass();
-     return !superClass.isInterface();
-   }
-   @NotNull
-   private static Collection<PsiMethod> overrideOrImplementMethod(PsiClass aClass,
-                                                        PsiMethod method,
-                                                        PsiSubstitutor substitutor,
-                                                        boolean toCopyJavaDoc,
-                                                        boolean insertOverrideIfPossible) throws IncorrectOperationException {
-     if (!method.isValid() || !substitutor.isValid()) return Collections.emptyList();
-     List<PsiMethod> results = new ArrayList<PsiMethod>();
-     for (final MethodImplementor implementor : getImplementors()) {
-       final PsiMethod[] prototypes = implementor.createImplementationPrototypes(aClass, method);
-       if (implementor.isBodyGenerated()) {
-         ContainerUtil.addAll(results, prototypes);
-       }
-       else {
-         for (PsiMethod prototype : prototypes) {
-           results.add(decorateMethod(aClass, method, toCopyJavaDoc, insertOverrideIfPossible, prototype));
-         }
-       }
-     }
-     if (results.isEmpty()) {
-       PsiMethod method1 = GenerateMembersUtil.substituteGenericMethod(method, substitutor, aClass);
-       
-       PsiElementFactory factory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory();
-       PsiMethod result = (PsiMethod)factory.createClass("Dummy").add(method1);
-       if (result instanceof PsiAnnotationMethod) {
-         PsiAnnotationMemberValue defaultValue = ((PsiAnnotationMethod)result).getDefaultValue();
-         if (defaultValue != null) {
-           PsiElement defaultKeyword = defaultValue;
-           while (!(defaultKeyword instanceof PsiKeyword) && defaultKeyword != null) {
-             defaultKeyword = defaultKeyword.getPrevSibling();
-           }
-           if (defaultKeyword == null) defaultKeyword = defaultValue;
-           defaultValue.getParent().deleteChildRange(defaultKeyword, defaultValue);
-         }
-       }
-       results.add(decorateMethod(aClass, method, toCopyJavaDoc, insertOverrideIfPossible, result));
-     }
-     for (Iterator<PsiMethod> iterator = results.iterator(); iterator.hasNext();) {
-       if (aClass.findMethodBySignature(iterator.next(), false) != null) {
-         iterator.remove();
-       }
-     }
-     return results;
-   }
-   private static PsiMethod decorateMethod(PsiClass aClass,
-                                           PsiMethod method,
-                                           boolean toCopyJavaDoc,
-                                           boolean insertOverrideIfPossible,
-                                           PsiMethod result) {
-     PsiUtil.setModifierProperty(result, PsiModifier.ABSTRACT, aClass.isInterface());
-     PsiUtil.setModifierProperty(result, PsiModifier.NATIVE, false);
-     if (!toCopyJavaDoc){
-       PsiDocComment comment = result.getDocComment();
-       if (comment != null){
-         comment.delete();
-       }
-     }
-     //method type params are not allowed when overriding from raw type
-     final PsiTypeParameterList list = result.getTypeParameterList();
-     if (list != null) {
-       final PsiClass containingClass = method.getContainingClass();
-       if (containingClass != null) {
-         for (PsiClassType classType : aClass.getSuperTypes()) {
-           if (InheritanceUtil.isInheritorOrSelf(PsiUtil.resolveClassInType(classType), containingClass, true) && classType.isRaw()) {
-             list.replace(JavaPsiFacade.getElementFactory(aClass.getProject()).createTypeParameterList());
-             break;
-           }
-         }
-       }
-     }
-     annotateOnOverrideImplement(result, aClass, method, insertOverrideIfPossible);
-     
-     if (CodeStyleSettingsManager.getSettings(aClass.getProject()).REPEAT_SYNCHRONIZED && method.hasModifierProperty(PsiModifier.SYNCHRONIZED)) {
-       result.getModifierList().setModifierProperty(PsiModifier.SYNCHRONIZED, true);
-     }
-     final PsiCodeBlock body = JavaPsiFacade.getInstance(method.getProject()).getElementFactory().createCodeBlockFromText("{}", null);
-     PsiCodeBlock oldbody = result.getBody();
-     if (oldbody != null){
-       oldbody.replace(body);
-     }
-     else{
-       result.add(body);
-     }
-     setupMethodBody(result, method, aClass);
-     // probably, it's better to reformat the whole method - it can go from other style sources
-     final Project project = method.getProject();
-     CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(project);
-     CommonCodeStyleSettings javaSettings = CodeStyleSettingsManager.getSettings(project).getCommonSettings(JavaLanguage.INSTANCE);
-     boolean keepBreaks = javaSettings.KEEP_LINE_BREAKS;
-     javaSettings.KEEP_LINE_BREAKS = false;
-     result = (PsiMethod)JavaCodeStyleManager.getInstance(project).shortenClassReferences(result);
-     result = (PsiMethod)codeStyleManager.reformat(result);
-     javaSettings.KEEP_LINE_BREAKS = keepBreaks;
-     return result;
-   }
-   public static void annotateOnOverrideImplement(PsiMethod method, PsiClass targetClass, PsiMethod overridden) {
-     annotateOnOverrideImplement(method, targetClass, overridden,
-                                 CodeStyleSettingsManager.getSettings(method.getProject()).INSERT_OVERRIDE_ANNOTATION);
-   }
-   public static void annotateOnOverrideImplement(PsiMethod method, PsiClass targetClass, PsiMethod overridden, boolean insertOverride) {
-     if (insertOverride && canInsertOverride(overridden, targetClass)) {
-       annotate(method, Override.class.getName());
-     }
-     final Module module = ModuleUtil.findModuleForPsiElement(targetClass);
-     final GlobalSearchScope moduleScope = module != null ? GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module) : null;
-     final Project project = targetClass.getProject();
-     final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
-     for (OverrideImplementsAnnotationsHandler each : Extensions.getExtensions(OverrideImplementsAnnotationsHandler.EP_NAME)) {
-       for (String annotation : each.getAnnotations(project)) {
-         if (moduleScope != null && facade.findClass(annotation, moduleScope) == null) continue;
-         if (AnnotationUtil.isAnnotated(overridden, annotation, false)) {
-           annotate(method, annotation, each.annotationsToRemove(project, annotation));
-         }
-       }
-     }
-   }
-   public static void annotate(@NotNull PsiMethod result, String fqn, String... annosToRemove) throws IncorrectOperationException {
-     Project project = result.getProject();
-     AddAnnotationFix fix = new AddAnnotationFix(fqn, result, annosToRemove);
-     if (fix.isAvailable(project, null, result.getContainingFile())) {
-       fix.invoke(project, null, result.getContainingFile());
-     }
-   }
-   public static boolean isOverridable(PsiMethod method) {
-     return !method.isConstructor()
-            && !method.hasModifierProperty(PsiModifier.STATIC)
-            && !method.hasModifierProperty(PsiModifier.FINAL)
-            && !method.hasModifierProperty(PsiModifier.PRIVATE);
-   }
-   @NotNull
-   public static List<PsiGenerationInfo<PsiMethod>> overrideOrImplementMethods(PsiClass aClass,
-                                                                               Collection<PsiMethodMember> candidates,
-                                                                               boolean toCopyJavaDoc,
-                                                                               boolean toInsertAtOverride)
-     throws IncorrectOperationException {
-     List<CandidateInfo> candidateInfos = ContainerUtil.map2List(candidates, new Function<PsiMethodMember, CandidateInfo>() {
-       public CandidateInfo fun(final PsiMethodMember s) {
-         return new CandidateInfo(s.getElement(), s.getSubstitutor());
-       }
-     });
-     final List<PsiMethod> methods = overrideOrImplementMethodCandidates(aClass, candidateInfos, toCopyJavaDoc, toInsertAtOverride);
-     return convert2GenerationInfos(methods);
-   }
-   @NotNull
-   public static List<PsiMethod> overrideOrImplementMethodCandidates(PsiClass aClass,
-                                                                     Collection<CandidateInfo> candidates,
-                                                                     boolean toCopyJavaDoc,
-                                                                     boolean insertOverrideWherePossible) throws IncorrectOperationException {
-     List<PsiMethod> result = new ArrayList<PsiMethod>();
-     for (CandidateInfo candidateInfo : candidates) {
-       result.addAll(overrideOrImplementMethod(aClass, (PsiMethod)candidateInfo.getElement(), candidateInfo.getSubstitutor(),
-                                               toCopyJavaDoc, insertOverrideWherePossible));
-     }
-     return result;
-   }
-   public static List<PsiGenerationInfo<PsiMethod>> convert2GenerationInfos(final Collection<PsiMethod> methods) {
-     return ContainerUtil.map2List(methods, new Function<PsiMethod, PsiGenerationInfo<PsiMethod>>() {
-       public PsiGenerationInfo<PsiMethod> fun(final PsiMethod s) {
-         return createGenerationInfo(s);
-       }
-     });
-   }
-   public static PsiGenerationInfo<PsiMethod> createGenerationInfo(PsiMethod s) {
-     return createGenerationInfo(s, true);
-   }
-   public static PsiGenerationInfo<PsiMethod> createGenerationInfo(PsiMethod s, boolean mergeIfExists) {
-     for (MethodImplementor implementor : getImplementors()) {
-       final GenerationInfo info = implementor.createGenerationInfo(s, mergeIfExists);
-       if (info instanceof PsiGenerationInfo) return (PsiGenerationInfo<PsiMethod>)info;
-     }
-     return new PsiGenerationInfo<PsiMethod>(s);
-   }
-   @NotNull
-   public static String callSuper (PsiMethod superMethod, PsiMethod overriding) {
-     @NonNls StringBuilder buffer = new StringBuilder();
-     if (!superMethod.isConstructor() && superMethod.getReturnType() != PsiType.VOID) {
-       buffer.append("return ");
-     }
-     buffer.append("super");
-     PsiParameter[] parms = overriding.getParameterList().getParameters();
-     if (!superMethod.isConstructor()){
-       buffer.append(".");
-       buffer.append(superMethod.getName());
-     }
-     buffer.append("(");
-     for (int i = 0; i < parms.length; i++) {
-       String name = parms[i].getName();
-       if (i > 0) buffer.append(",");
-       buffer.append(name);
-     }
-     buffer.append(")");
-     return buffer.toString();
-   }
-   public static void setupMethodBody(PsiMethod result, PsiMethod originalMethod, PsiClass targetClass) throws IncorrectOperationException {
-     String templName = originalMethod.hasModifierProperty(PsiModifier.ABSTRACT) ?
-                        JavaTemplateUtil.TEMPLATE_IMPLEMENTED_METHOD_BODY : JavaTemplateUtil.TEMPLATE_OVERRIDDEN_METHOD_BODY;
-     FileTemplate template = FileTemplateManager.getInstance().getCodeTemplate(templName);
-     setupMethodBody(result, originalMethod, targetClass, template);
-   }
-   public static void setupMethodBody(final PsiMethod result, final PsiMethod originalMethod, final PsiClass targetClass,
-                                      final FileTemplate template) throws IncorrectOperationException {
-     if (targetClass.isInterface()) {
-       final PsiCodeBlock body = result.getBody();
-       if (body != null) body.delete();
-     }
-     FileType fileType = FileTypeManager.getInstance().getFileTypeByExtension(template.getExtension());
-     PsiType returnType = result.getReturnType();
-     if (returnType == null) {
-       returnType = PsiType.VOID;
-     }
-     Properties properties = new Properties();
-     properties.setProperty(FileTemplate.ATTRIBUTE_RETURN_TYPE, returnType.getPresentableText());
-     properties.setProperty(FileTemplate.ATTRIBUTE_DEFAULT_RETURN_VALUE, PsiTypesUtil.getDefaultValueOfType(returnType));
-     properties.setProperty(FileTemplate.ATTRIBUTE_CALL_SUPER, callSuper(originalMethod, result));
-     JavaTemplateUtil.setClassAndMethodNameProperties(properties, targetClass, result);
-     JVMElementFactory factory = JVMElementFactories.getFactory(targetClass.getLanguage(), originalMethod.getProject());
-     if (factory == null) factory = JavaPsiFacade.getInstance(originalMethod.getProject()).getElementFactory();
-     @NonNls String methodText;
-     try {
-       String bodyText = template.getText(properties);
-       if (bodyText != null && !bodyText.isEmpty()) bodyText += "\n";
-       methodText = "void foo () {\n" + bodyText + "}";
-       methodText = FileTemplateUtil.indent(methodText, result.getProject(), fileType);
-     } catch (Exception e) {
-       throw new IncorrectOperationException("Failed to parse file template",e);
-     }
-     if (methodText != null) {
-       PsiMethod m;
-       try {
-         m = factory.createMethodFromText(methodText, originalMethod);
-       }
-       catch (IncorrectOperationException e) {
-         ApplicationManager.getApplication().invokeLater(new Runnable() {
-           public void run() {
-             Messages.showErrorDialog(CodeInsightBundle.message("override.implement.broken.file.template.message"),
-                                      CodeInsightBundle.message("override.implement.broken.file.template.title"));
-           }
-         });
-         return;
-       }
-       PsiCodeBlock oldBody = result.getBody();
-       if (oldBody != null) {
-         oldBody.replace(m.getBody());
-       }
-     }
-   }
-   public static void chooseAndOverrideMethods(Project project, Editor editor, PsiClass aClass){
-     FeatureUsageTracker.getInstance().triggerFeatureUsed(ProductivityFeatureNames.CODEASSISTS_OVERRIDE_IMPLEMENT);
-     chooseAndOverrideOrImplementMethods(project, editor, aClass, false);
-   }
-   public static void chooseAndImplementMethods(Project project, Editor editor, PsiClass aClass){
-     FeatureUsageTracker.getInstance().triggerFeatureUsed(ProductivityFeatureNames.CODEASSISTS_OVERRIDE_IMPLEMENT);
-     chooseAndOverrideOrImplementMethods(project, editor, aClass, true);
-   }
-   public static void chooseAndOverrideOrImplementMethods(final Project project,
-                                                           final Editor editor,
-                                                           final PsiClass aClass,
-                                                           final boolean toImplement){
-     LOG.assertTrue(aClass.isValid());
-     ApplicationManager.getApplication().assertReadAccessAllowed();
-     Collection<CandidateInfo> candidates = getMethodsToOverrideImplement(aClass, toImplement);
-     Collection<CandidateInfo> secondary = toImplement || aClass.isInterface() ? Collections.<CandidateInfo>emptyList() : getMethodsToOverrideImplement(aClass, true);
-     final MemberChooser<PsiMethodMember> chooser = showOverrideImplementChooser(editor, aClass, toImplement, candidates, secondary);
-     if (chooser == null) return;
-     final List<PsiMethodMember> selectedElements = chooser.getSelectedElements();
-     if (selectedElements == null || selectedElements.isEmpty()) return;
-     LOG.assertTrue(aClass.isValid());
-     new WriteCommandAction(project, aClass.getContainingFile()) {
-       protected void run(final Result result) throws Throwable {
-         overrideOrImplementMethodsInRightPlace(editor, aClass, selectedElements, chooser.isCopyJavadoc(), chooser.isInsertOverrideAnnotation());
-       }
-     }.execute();
-   }
-   @Nullable
-   public static MemberChooser<PsiMethodMember> showOverrideImplementChooser(Editor editor,
-                                                                             final PsiElement aClass,
-                                                                             final boolean toImplement,
-                                                                             Collection<CandidateInfo> candidates,
-                                                                             Collection<CandidateInfo> secondary) {
-     Project project = aClass.getProject();
-     if (candidates.isEmpty() && secondary.isEmpty()) return null;
-     final PsiMethodMember[] onlyPrimary = convertToMethodMembers(candidates);
-     final PsiMethodMember[] all = ArrayUtil.mergeArrays(onlyPrimary, convertToMethodMembers(secondary));
-     final String toMerge = PropertiesComponent.getInstance(project).getValue(PROP_COMBINED_OVERRIDE_IMPLEMENT);
-     final Ref<Boolean> merge = Ref.create(!"false".equals(toMerge));
-     final boolean isAll = merge.get().booleanValue();
-     final MemberChooser<PsiMethodMember> chooser = new MemberChooser<PsiMethodMember>(isAll ? all : onlyPrimary, false, true, project,
-                                                                                       PsiUtil.isLanguageLevel5OrHigher(aClass)) {
-       @Override
-       protected void fillToolbarActions(DefaultActionGroup group) {
-         super.fillToolbarActions(group);
-         if (toImplement) return;
-         final ToggleAction mergeAction = new ToggleAction("Show methods to implement", "Show methods to implement",
-                                                           AllIcons.General.Show_to_implement) {
-           @Override
-           public boolean isSelected(AnActionEvent e) {
-             return merge.get().booleanValue();
-           }
-           @Override
-           public void setSelected(AnActionEvent e, boolean state) {
-             merge.set(state);
-             resetElements(state ? all : onlyPrimary);
-             setTitle(getChooserTitle(false, merge));
-           }
-         };
-         mergeAction.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_I, InputEvent.ALT_MASK)), myTree);
-         Shortcut[] shortcuts = KeymapManager.getInstance().getActiveKeymap().getShortcuts("OverrideMethods");
-         mergeAction.registerCustomShortcutSet(new CustomShortcutSet(shortcuts), myTree);
-         group.add(mergeAction);
-       }
-     };
-     chooser.setTitle(getChooserTitle(toImplement, merge));
-     registerHandlerForComplementaryAction(project, editor, aClass, toImplement, chooser);
-     chooser.setCopyJavadocVisible(true);
-     if (toImplement) {
-       chooser.selectElements(isAll ? all : onlyPrimary);
-     }
-     if (ApplicationManager.getApplication().isUnitTestMode()) {
-       chooser.selectElements(all);
-       chooser.close(DialogWrapper.OK_EXIT_CODE);
-       return chooser;
-     }
-     chooser.show();
-     if (chooser.getExitCode() != DialogWrapper.OK_EXIT_CODE) return null;
-     PropertiesComponent.getInstance(project).setValue(PROP_COMBINED_OVERRIDE_IMPLEMENT, merge.get().toString());
-     return chooser;
-   }
-   private static String getChooserTitle(boolean toImplement, Ref<Boolean> merge) {
-     return toImplement
-                      ? CodeInsightBundle.message("methods.to.implement.chooser.title")
-                      : merge.get().booleanValue()
-                        ? CodeInsightBundle.message("methods.to.override.implement.chooser.title")
-                        : CodeInsightBundle.message("methods.to.override.chooser.title");
-   }
-   private static PsiMethodMember[] convertToMethodMembers(Collection<CandidateInfo> candidates) {
-     return ContainerUtil.map2Array(candidates, PsiMethodMember.class, new Function<CandidateInfo, PsiMethodMember>() {
-         public PsiMethodMember fun(final CandidateInfo s) {
-           return new PsiMethodMember(s);
-         }
-       });
-   }
-   private static void registerHandlerForComplementaryAction(final Project project, final Editor editor, final PsiElement aClass,
-                                                             final boolean toImplement,
-                                                             final MemberChooser<PsiMethodMember> chooser) {
-     final JComponent preferredFocusedComponent = chooser.getPreferredFocusedComponent();
-     final Keymap keymap = KeymapManager.getInstance().getActiveKeymap();
-     @NonNls final String s = toImplement ? "OverrideMethods" : "ImplementMethods";
-     final Shortcut[] shortcuts = keymap.getShortcuts(s);
-     if (shortcuts.length > 0 && shortcuts[0] instanceof KeyboardShortcut) {
-       preferredFocusedComponent.getInputMap().put(
-         ((KeyboardShortcut)shortcuts[0]).getFirstKeyStroke(), s
-       );
-       preferredFocusedComponent.getActionMap().put(
-           s,
-           new AbstractAction() {
-             public void actionPerformed(final ActionEvent e) {
-               chooser.close(DialogWrapper.CANCEL_EXIT_CODE);
-               // invoke later in order to close previous modal dialog
-               ApplicationManager.getApplication().invokeLater(new Runnable() {
-                 public void run() {
-                   final CodeInsightActionHandler handler = toImplement ? new OverrideMethodsHandler(): new ImplementMethodsHandler();
-                   handler.invoke(project, editor, aClass.getContainingFile());
-                 }
-               });
-             }
-           }
-       );
-     }
-   }
-   public static void overrideOrImplementMethodsInRightPlace(Editor editor,
-                                                             PsiClass aClass,
-                                                             Collection<PsiMethodMember> candidates,
-                                                             boolean copyJavadoc,
-                                                             boolean insertOverrideWherePossible) {
-     try {
-       int offset = editor.getCaretModel().getOffset();
-       if (aClass.getLBrace() == null) {
-         PsiClass psiClass = JavaPsiFacade.getInstance(aClass.getProject()).getElementFactory().createClass("X");
-         aClass.addRangeAfter(psiClass.getLBrace(), psiClass.getRBrace(), aClass.getLastChild());
-       }
-       int lbraceOffset = aClass.getLBrace().getTextOffset();
-       List<PsiGenerationInfo<PsiMethod>> resultMembers;
-       if (offset <= lbraceOffset || aClass.isEnum()) {
-         resultMembers = new ArrayList<PsiGenerationInfo<PsiMethod>>();
-         for (PsiMethodMember candidate : candidates) {
-           Collection<PsiMethod> prototypes =
-             overrideOrImplementMethod(aClass, candidate.getElement(), candidate.getSubstitutor(), copyJavadoc, insertOverrideWherePossible);
-           List<PsiGenerationInfo<PsiMethod>> infos = convert2GenerationInfos(prototypes);
-           for (PsiGenerationInfo<PsiMethod> info : infos) {
-             PsiElement anchor = getDefaultAnchorToOverrideOrImplement(aClass, candidate.getElement(), candidate.getSubstitutor());
-             info.insert(aClass, anchor, true);
-             resultMembers.add(info);
-           }
-         }
-       }
-       else {
-         List<PsiGenerationInfo<PsiMethod>> prototypes = overrideOrImplementMethods(aClass, candidates, copyJavadoc, insertOverrideWherePossible);
-         resultMembers = GenerateMembersUtil.insertMembersAtOffset(aClass.getContainingFile(), offset, prototypes);
-       }
-       if (!resultMembers.isEmpty()) {
-         resultMembers.get(0).positionCaret(editor, true);
-       }
-     }
-     catch (IncorrectOperationException e) {
-       LOG.error(e);
-     }
-   }
-   @Nullable
-   public static PsiElement getDefaultAnchorToOverrideOrImplement(PsiClass aClass, PsiMethod baseMethod, PsiSubstitutor substitutor){
-     PsiMethod prevBaseMethod = PsiTreeUtil.getPrevSiblingOfType(baseMethod, PsiMethod.class);
-     while(prevBaseMethod != null) {
-       String name = prevBaseMethod.isConstructor() ? aClass.getName() : prevBaseMethod.getName();
-       //Happens when aClass instanceof PsiAnonymousClass
-       if (name != null) {
-         MethodSignature signature = MethodSignatureUtil.createMethodSignature(name, prevBaseMethod.getParameterList(), prevBaseMethod.getTypeParameterList(), substitutor, prevBaseMethod.isConstructor());
-         PsiMethod prevMethod = MethodSignatureUtil.findMethodBySignature(aClass, signature, false);
-         if (prevMethod != null){
-           return prevMethod.getNextSibling();
-         }
-       }
-       prevBaseMethod = PsiTreeUtil.getPrevSiblingOfType(prevBaseMethod, PsiMethod.class);
-     }
-     PsiMethod nextBaseMethod = PsiTreeUtil.getNextSiblingOfType(baseMethod, PsiMethod.class);
-     while(nextBaseMethod != null) {
-       String name = nextBaseMethod.isConstructor() ? aClass.getName() : nextBaseMethod.getName();
-       if (name != null) {
-         MethodSignature signature = MethodSignatureUtil.createMethodSignature(name, nextBaseMethod.getParameterList(), nextBaseMethod.getTypeParameterList(), substitutor, nextBaseMethod.isConstructor());
-         PsiMethod nextMethod = MethodSignatureUtil.findMethodBySignature(aClass, signature, false);
-         if (nextMethod != null){
-           return nextMethod;
-         }
-       }
-       nextBaseMethod = PsiTreeUtil.getNextSiblingOfType(nextBaseMethod, PsiMethod.class);
-     }
-     return null;
-   }
-   public static void overrideOrImplement(PsiClass psiClass, @NotNull PsiMethod baseMethod) throws IncorrectOperationException {
-     FileEditorManager fileEditorManager = FileEditorManager.getInstance(baseMethod.getProject());
-     List<PsiGenerationInfo<PsiMethod>> prototypes = convert2GenerationInfos(overrideOrImplementMethod(psiClass, baseMethod, false));
-     if (prototypes.isEmpty()) return;
-     PsiSubstitutor substitutor = TypeConversionUtil.getSuperClassSubstitutor(baseMethod.getContainingClass(), psiClass, PsiSubstitutor.EMPTY);
-     PsiElement anchor = getDefaultAnchorToOverrideOrImplement(psiClass, baseMethod, substitutor);
-     List<PsiGenerationInfo<PsiMethod>> results = GenerateMembersUtil.insertMembersBeforeAnchor(psiClass, anchor, prototypes);
-     PsiFile psiFile = psiClass.getContainingFile();
-     Editor editor = fileEditorManager.openTextEditor(new OpenFileDescriptor(psiFile.getProject(), psiFile.getVirtualFile()), false);
-     if (editor == null) return;
-     results.get(0).positionCaret(editor, true);
-     editor.getScrollingModel().scrollToCaret(ScrollType.CENTER);
-   }
-   @Nullable
-   public static PsiClass getContextClass(Project project, Editor editor, PsiFile file, boolean allowInterface) {
-     PsiDocumentManager.getInstance(project).commitAllDocuments();
-     int offset = editor.getCaretModel().getOffset();
-     PsiElement element = file.findElementAt(offset);
-     do {
-       element = PsiTreeUtil.getParentOfType(element, PsiClass.class);
-     }
-     while (element instanceof PsiTypeParameter);
-     final PsiClass aClass = (PsiClass)element;
-     if (aClass instanceof JspClass) return null;
-     return aClass == null || !allowInterface && aClass.isInterface() ? null : aClass;
-   }
-   public static void overrideOrImplementMethodsInRightPlace(Editor editor1, PsiClass aClass, Collection<PsiMethodMember> members, boolean copyJavadoc) {
-     boolean insert = CodeStyleSettingsManager.getSettings(aClass.getProject()).INSERT_OVERRIDE_ANNOTATION;
-     overrideOrImplementMethodsInRightPlace(editor1, aClass, members, copyJavadoc, insert);
-   }
-   public static List<PsiMethod> overrideOrImplementMethodCandidates(PsiClass aClass, Collection<CandidateInfo> candidatesToImplement,
-                                                                     boolean copyJavadoc) throws IncorrectOperationException {
-     boolean insert = CodeStyleSettingsManager.getSettings(aClass.getProject()).INSERT_OVERRIDE_ANNOTATION;
-     return overrideOrImplementMethodCandidates(aClass, candidatesToImplement, copyJavadoc, insert);
-   }
-   public static class MethodSignatureComparator implements Comparator<MethodSignature> {
-     // signatures should appear in the order of declaration
-     public int compare(MethodSignature o1, MethodSignature o2) {
-       if (o1 instanceof MethodSignatureBackedByPsiMethod && o2 instanceof MethodSignatureBackedByPsiMethod) {
-         PsiMethod m1 = ((MethodSignatureBackedByPsiMethod)o1).getMethod();
-         PsiMethod m2 = ((MethodSignatureBackedByPsiMethod)o2).getMethod();
-         PsiClass c1 = m1.getContainingClass();
-         PsiClass c2 = m2.getContainingClass();
-         if (c1 != null && c2 != null) {
-           if (c1 == c2) {
-             final List<PsiMethod> methods = Arrays.asList(c1.getMethods());
-             return methods.indexOf(m1) - methods.indexOf(m2);
-           }
-           if (c1.isInheritor(c2, true)) return -1;
-           if (c2.isInheritor(c1, true)) return 1;
-           return StringUtil.notNullize(c1.getName()).compareTo(StringUtil.notNullize(c2.getName()));
-         }
-         return m1.getTextOffset() - m2.getTextOffset();
-       }
-       return 0;
-     }
-   }
- }
+ /*\r
+  * Copyright 2000-2011 JetBrains s.r.o.\r
+  *\r
+  * Licensed under the Apache License, Version 2.0 (the "License");\r
+  * you may not use this file except in compliance with the License.\r
+  * You may obtain a copy of the License at\r
+  *\r
+  * http://www.apache.org/licenses/LICENSE-2.0\r
+  *\r
+  * Unless required by applicable law or agreed to in writing, software\r
+  * distributed under the License is distributed on an "AS IS" BASIS,\r
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+  * See the License for the specific language governing permissions and\r
+  * limitations under the License.\r
+  */\r
+ package com.intellij.codeInsight.generation;\r
\r
+ import com.intellij.codeInsight.AnnotationUtil;\r
+ import com.intellij.codeInsight.CodeInsightActionHandler;\r
+ import com.intellij.codeInsight.CodeInsightBundle;\r
+ import com.intellij.codeInsight.MethodImplementor;\r
+ import com.intellij.codeInsight.intention.AddAnnotationFix;\r
+ import com.intellij.featureStatistics.FeatureUsageTracker;\r
+ import com.intellij.featureStatistics.ProductivityFeatureNames;\r
+ import com.intellij.icons.AllIcons;\r
+ import com.intellij.ide.fileTemplates.FileTemplate;\r
+ import com.intellij.ide.fileTemplates.FileTemplateManager;\r
+ import com.intellij.ide.fileTemplates.FileTemplateUtil;\r
+ import com.intellij.ide.fileTemplates.JavaTemplateUtil;\r
+ import com.intellij.ide.util.MemberChooser;\r
+ import com.intellij.ide.util.PropertiesComponent;\r
+ import com.intellij.lang.java.JavaLanguage;\r
+ import com.intellij.openapi.actionSystem.*;\r
+ import com.intellij.openapi.application.ApplicationManager;\r
+ import com.intellij.openapi.application.Result;\r
+ import com.intellij.openapi.command.WriteCommandAction;\r
+ import com.intellij.openapi.diagnostic.Logger;\r
+ import com.intellij.openapi.editor.Editor;\r
+ import com.intellij.openapi.editor.ScrollType;\r
+ import com.intellij.openapi.extensions.Extensions;\r
+ import com.intellij.openapi.fileEditor.FileEditorManager;\r
+ import com.intellij.openapi.fileEditor.OpenFileDescriptor;\r
+ import com.intellij.openapi.fileTypes.FileType;\r
+ import com.intellij.openapi.fileTypes.FileTypeManager;\r
+ import com.intellij.openapi.keymap.Keymap;\r
+ import com.intellij.openapi.keymap.KeymapManager;\r
+ import com.intellij.openapi.module.Module;\r
+ import com.intellij.openapi.module.ModuleUtil;\r
+ import com.intellij.openapi.project.Project;\r
+ import com.intellij.openapi.ui.DialogWrapper;\r
+ import com.intellij.openapi.ui.Messages;\r
+ import com.intellij.openapi.util.Ref;\r
+ import com.intellij.openapi.util.text.StringUtil;\r
+ import com.intellij.psi.*;\r
+ import com.intellij.psi.codeStyle.CodeStyleManager;\r
+ import com.intellij.psi.codeStyle.CodeStyleSettingsManager;\r
+ import com.intellij.psi.codeStyle.CommonCodeStyleSettings;\r
+ import com.intellij.psi.codeStyle.JavaCodeStyleManager;\r
+ import com.intellij.psi.impl.source.jsp.jspJava.JspClass;\r
+ import com.intellij.psi.infos.CandidateInfo;\r
+ import com.intellij.psi.javadoc.PsiDocComment;\r
+ import com.intellij.psi.search.GlobalSearchScope;\r
+ import com.intellij.psi.util.*;\r
+ import com.intellij.util.ArrayUtil;\r
+ import com.intellij.util.Function;\r
+ import com.intellij.util.IncorrectOperationException;\r
+ import com.intellij.util.containers.ContainerUtil;\r
+ import org.jetbrains.annotations.NonNls;\r
+ import org.jetbrains.annotations.NotNull;\r
+ import org.jetbrains.annotations.Nullable;\r
\r
+ import javax.swing.*;\r
+ import java.awt.event.ActionEvent;\r
+ import java.awt.event.InputEvent;\r
+ import java.awt.event.KeyEvent;\r
+ import java.util.*;\r
\r
+ public class OverrideImplementUtil {\r
+   private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.generation.OverrideImplementUtil");\r
\r
+   @NonNls private static final String PROP_COMBINED_OVERRIDE_IMPLEMENT = "OverrideImplement.combined";\r
\r
+   private OverrideImplementUtil() {\r
+   }\r
\r
+   @NotNull\r
+   public static Collection<CandidateInfo> getMethodsToOverrideImplement(PsiClass aClass, boolean toImplement) {\r
+     return getMapToOverrideImplement(aClass, toImplement).values();\r
+   }\r
\r
+   @NotNull\r
+   public static Collection<MethodSignature> getMethodSignaturesToImplement(@NotNull PsiClass aClass) {\r
+     return getMapToOverrideImplement(aClass, true).keySet();\r
+   }\r
\r
+   @NotNull\r
+   public static Collection<MethodSignature> getMethodSignaturesToOverride(@NotNull PsiClass aClass) {\r
+     return getMapToOverrideImplement(aClass, false).keySet();\r
+   }\r
\r
+   @NotNull\r
+   private static Map<MethodSignature, CandidateInfo> getMapToOverrideImplement(PsiClass aClass, boolean toImplement) {\r
+     Map<MethodSignature, PsiMethod> abstracts = new LinkedHashMap<MethodSignature,PsiMethod>();\r
+     Map<MethodSignature, PsiMethod> finals = new LinkedHashMap<MethodSignature,PsiMethod>();\r
+     Map<MethodSignature, PsiMethod> concretes = new LinkedHashMap<MethodSignature,PsiMethod>();\r
\r
+     LOG.assertTrue(aClass.isValid());\r
+     Collection<HierarchicalMethodSignature> allMethodSigs = aClass.getVisibleSignatures();\r
+     PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(aClass.getProject()).getResolveHelper();\r
+     for (HierarchicalMethodSignature signature : allMethodSigs) {\r
+       PsiMethod method = signature.getMethod();\r
+       LOG.assertTrue(method.isValid(), aClass);\r
\r
+       if (method.hasModifierProperty(PsiModifier.STATIC) || !resolveHelper.isAccessible(method, aClass, aClass)) continue;\r
+       PsiClass hisClass = method.getContainingClass();\r
+       if (hisClass == null) continue;\r
+       // filter non-immediate super constructors\r
+       if (method.isConstructor() && (!aClass.isInheritor(hisClass, false) || aClass instanceof PsiAnonymousClass || aClass.isEnum())) {\r
+         continue;\r
+       }\r
+       // filter already implemented\r
+       if (MethodSignatureUtil.findMethodBySignature(aClass, signature, false) != null) {\r
+         continue;\r
+       }\r
\r
+       if (method.hasModifierProperty(PsiModifier.FINAL)) {\r
+         finals.put(signature, method);\r
+         continue;\r
+       }\r
\r
+       Map<MethodSignature, PsiMethod> map = hisClass.isInterface() || method.hasModifierProperty(PsiModifier.ABSTRACT) ? abstracts : concretes;\r
+       PsiMethod other = map.get(signature);\r
+       if (other == null || preferLeftForImplement(method, other)) {\r
+         map.put(signature, method);\r
+       }\r
+     }\r
\r
+     final Map<MethodSignature, CandidateInfo> result = new TreeMap<MethodSignature,CandidateInfo>(new MethodSignatureComparator());\r
+     if (toImplement || aClass.isInterface()) {\r
+       collectMethodsToImplement(aClass, abstracts, finals, concretes, result);\r
+     }\r
+     else {\r
+       for (Map.Entry<MethodSignature, PsiMethod> entry : concretes.entrySet()) {\r
+         MethodSignature signature = entry.getKey();\r
+         PsiMethod concrete = entry.getValue();\r
+         if (finals.get(signature) == null) {\r
+           PsiMethod abstractOne = abstracts.get(signature);\r
+           if (abstractOne == null || !abstractOne.getContainingClass().isInheritor(concrete.getContainingClass(), true) ||\r
+               CommonClassNames.JAVA_LANG_OBJECT.equals(concrete.getContainingClass().getQualifiedName())) {\r
+             PsiSubstitutor subst = GenerateMembersUtil.correctSubstitutor(concrete, signature.getSubstitutor());\r
+             CandidateInfo info = new CandidateInfo(concrete, subst);\r
+             result.put(signature, info);\r
+           }\r
+         }\r
+       }\r
+     }\r
\r
+     return result;\r
+   }\r
\r
+   public static void collectMethodsToImplement(PsiClass aClass,\r
+                                                Map<MethodSignature, PsiMethod> abstracts,\r
+                                                Map<MethodSignature, PsiMethod> finals,\r
+                                                Map<MethodSignature, PsiMethod> concretes,\r
+                                                Map<MethodSignature, CandidateInfo> result) {\r
+     for (Map.Entry<MethodSignature, PsiMethod> entry : abstracts.entrySet()) {\r
+       MethodSignature signature = entry.getKey();\r
+       PsiMethod abstractOne = entry.getValue();\r
+       PsiMethod concrete = concretes.get(signature);\r
+       if (concrete == null\r
+           || PsiUtil.getAccessLevel(concrete.getModifierList()) < PsiUtil.getAccessLevel(abstractOne.getModifierList())\r
+           || !abstractOne.getContainingClass().isInterface() && abstractOne.getContainingClass().isInheritor(concrete.getContainingClass(), true)) {\r
+         if (finals.get(signature) == null) {\r
+           PsiSubstitutor subst = GenerateMembersUtil.correctSubstitutor(abstractOne, signature.getSubstitutor());\r
+           CandidateInfo info = new CandidateInfo(abstractOne, subst);\r
+           result.put(signature, info);\r
+         }\r
+       }\r
+     }\r
\r
+     for (final MethodImplementor implementor : getImplementors()) {\r
+       for (final PsiMethod method : implementor.getMethodsToImplement(aClass)) {\r
+         MethodSignature signature = MethodSignatureUtil.createMethodSignature(method.getName(), method.getParameterList(),\r
+                                                                               method.getTypeParameterList(), PsiSubstitutor.EMPTY, method.isConstructor());\r
+         CandidateInfo info = new CandidateInfo(method, PsiSubstitutor.EMPTY);\r
+         result.put(signature, info);\r
+       }\r
+     }\r
+   }\r
\r
+   private static boolean preferLeftForImplement(PsiMethod left, PsiMethod right) {\r
+     if (PsiUtil.getAccessLevel(left.getModifierList()) > PsiUtil.getAccessLevel(right.getModifierList())) return true;\r
+     if (!left.getContainingClass().isInterface()) return true;\r
+     if (!right.getContainingClass().isInterface()) return false;\r
+     // implement annotated method\r
+     PsiAnnotation[] leftAnnotations = left.getModifierList().getAnnotations();\r
+     PsiAnnotation[] rightAnnotations = right.getModifierList().getAnnotations();\r
+     return leftAnnotations.length > rightAnnotations.length;\r
+   }\r
\r
+   private static MethodImplementor[] getImplementors() {\r
+     return Extensions.getExtensions(MethodImplementor.EXTENSION_POINT_NAME);\r
+   }\r
\r
+   /**\r
+    * generate methods (with bodies) corresponding to given method declaration\r
+    *  there are maybe two method implementations for one declaration\r
+    * (e.g. EJB' create() -> ejbCreate(), ejbPostCreate() )\r
+    * @param aClass context for method implementations\r
+    * @param method method to override or implement\r
+    * @param toCopyJavaDoc true if copy JavaDoc from method declaration\r
+    * @return list of method prototypes\r
+    */\r
+   @NotNull\r
+   public static Collection<PsiMethod> overrideOrImplementMethod(PsiClass aClass, PsiMethod method, boolean toCopyJavaDoc) throws IncorrectOperationException {\r
+     final PsiClass containingClass = method.getContainingClass();\r
+     LOG.assertTrue(containingClass != null);\r
+     PsiSubstitutor substitutor = aClass.isInheritor(containingClass, true)\r
+                                  ? TypeConversionUtil.getSuperClassSubstitutor(containingClass, aClass, PsiSubstitutor.EMPTY)\r
+                                  : PsiSubstitutor.EMPTY;\r
+     return overrideOrImplementMethod(aClass, method, substitutor, toCopyJavaDoc, CodeStyleSettingsManager.getSettings(aClass.getProject()).INSERT_OVERRIDE_ANNOTATION);\r
+   }\r
\r
+   public static boolean isInsertOverride(PsiMethod superMethod, PsiClass targetClass) {\r
+     if (!CodeStyleSettingsManager.getSettings(targetClass.getProject()).INSERT_OVERRIDE_ANNOTATION) {\r
+       return false;\r
+     }\r
+     return canInsertOverride(superMethod, targetClass);\r
+   }\r
\r
+   public static boolean canInsertOverride(PsiMethod superMethod, PsiClass targetClass) {\r
+     if (superMethod.isConstructor() || superMethod.hasModifierProperty(PsiModifier.STATIC)) {\r
+       return false;\r
+     }\r
+     if (!PsiUtil.isLanguageLevel5OrHigher(targetClass)) {\r
+       return false;\r
+     }\r
+     if (PsiUtil.isLanguageLevel6OrHigher(targetClass)) return true;\r
+     if (targetClass.isInterface()) return true;\r
+     PsiClass superClass = superMethod.getContainingClass();\r
+     return !superClass.isInterface();\r
+   }\r
\r
+   @NotNull\r
+   private static Collection<PsiMethod> overrideOrImplementMethod(PsiClass aClass,\r
+                                                        PsiMethod method,\r
+                                                        PsiSubstitutor substitutor,\r
+                                                        boolean toCopyJavaDoc,\r
+                                                        boolean insertOverrideIfPossible) throws IncorrectOperationException {\r
+     if (!method.isValid() || !substitutor.isValid()) return Collections.emptyList();\r
\r
+     List<PsiMethod> results = new ArrayList<PsiMethod>();\r
+     for (final MethodImplementor implementor : getImplementors()) {\r
+       final PsiMethod[] prototypes = implementor.createImplementationPrototypes(aClass, method);\r
+       if (implementor.isBodyGenerated()) {\r
+         ContainerUtil.addAll(results, prototypes);\r
+       }\r
+       else {\r
+         for (PsiMethod prototype : prototypes) {\r
+           results.add(decorateMethod(aClass, method, toCopyJavaDoc, insertOverrideIfPossible, prototype));\r
+         }\r
+       }\r
+     }\r
+     if (results.isEmpty()) {\r
+       PsiMethod method1 = GenerateMembersUtil.substituteGenericMethod(method, substitutor, aClass);\r
+       \r
+       PsiElementFactory factory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory();\r
+       PsiMethod result = (PsiMethod)factory.createClass("Dummy").add(method1);\r
+       if (result instanceof PsiAnnotationMethod) {\r
+         PsiAnnotationMemberValue defaultValue = ((PsiAnnotationMethod)result).getDefaultValue();\r
+         if (defaultValue != null) {\r
+           PsiElement defaultKeyword = defaultValue;\r
+           while (!(defaultKeyword instanceof PsiKeyword) && defaultKeyword != null) {\r
+             defaultKeyword = defaultKeyword.getPrevSibling();\r
+           }\r
+           if (defaultKeyword == null) defaultKeyword = defaultValue;\r
+           defaultValue.getParent().deleteChildRange(defaultKeyword, defaultValue);\r
+         }\r
+       }\r
+       results.add(decorateMethod(aClass, method, toCopyJavaDoc, insertOverrideIfPossible, result));\r
+     }\r
\r
+     for (Iterator<PsiMethod> iterator = results.iterator(); iterator.hasNext();) {\r
+       if (aClass.findMethodBySignature(iterator.next(), false) != null) {\r
+         iterator.remove();\r
+       }\r
+     }\r
\r
+     return results;\r
+   }\r
\r
+   private static PsiMethod decorateMethod(PsiClass aClass,\r
+                                           PsiMethod method,\r
+                                           boolean toCopyJavaDoc,\r
+                                           boolean insertOverrideIfPossible,\r
+                                           PsiMethod result) {\r
+     PsiUtil.setModifierProperty(result, PsiModifier.ABSTRACT, aClass.isInterface());\r
+     PsiUtil.setModifierProperty(result, PsiModifier.NATIVE, false);\r
\r
+     if (!toCopyJavaDoc){\r
+       PsiDocComment comment = result.getDocComment();\r
+       if (comment != null){\r
+         comment.delete();\r
+       }\r
+     }\r
\r
+     //method type params are not allowed when overriding from raw type\r
+     final PsiTypeParameterList list = result.getTypeParameterList();\r
+     if (list != null) {\r
+       final PsiClass containingClass = method.getContainingClass();\r
+       if (containingClass != null) {\r
+         for (PsiClassType classType : aClass.getSuperTypes()) {\r
+           if (InheritanceUtil.isInheritorOrSelf(PsiUtil.resolveClassInType(classType), containingClass, true) && classType.isRaw()) {\r
+             list.replace(JavaPsiFacade.getElementFactory(aClass.getProject()).createTypeParameterList());\r
+             break;\r
+           }\r
+         }\r
+       }\r
+     }\r
\r
+     annotateOnOverrideImplement(result, aClass, method, insertOverrideIfPossible);\r
+     \r
+     if (CodeStyleSettingsManager.getSettings(aClass.getProject()).REPEAT_SYNCHRONIZED && method.hasModifierProperty(PsiModifier.SYNCHRONIZED)) {\r
+       result.getModifierList().setModifierProperty(PsiModifier.SYNCHRONIZED, true);\r
+     }\r
\r
+     final PsiCodeBlock body = JavaPsiFacade.getInstance(method.getProject()).getElementFactory().createCodeBlockFromText("{}", null);\r
+     PsiCodeBlock oldbody = result.getBody();\r
+     if (oldbody != null){\r
+       oldbody.replace(body);\r
+     }\r
+     else{\r
+       result.add(body);\r
+     }\r
\r
+     setupMethodBody(result, method, aClass);\r
\r
+     // probably, it's better to reformat the whole method - it can go from other style sources\r
+     final Project project = method.getProject();\r
+     CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(project);\r
+     CommonCodeStyleSettings javaSettings = CodeStyleSettingsManager.getSettings(project).getCommonSettings(JavaLanguage.INSTANCE);\r
+     boolean keepBreaks = javaSettings.KEEP_LINE_BREAKS;\r
+     javaSettings.KEEP_LINE_BREAKS = false;\r
+     result = (PsiMethod)JavaCodeStyleManager.getInstance(project).shortenClassReferences(result);\r
+     result = (PsiMethod)codeStyleManager.reformat(result);\r
+     javaSettings.KEEP_LINE_BREAKS = keepBreaks;\r
+     return result;\r
+   }\r
\r
+   public static void annotateOnOverrideImplement(PsiMethod method, PsiClass targetClass, PsiMethod overridden) {\r
+     annotateOnOverrideImplement(method, targetClass, overridden,\r
+                                 CodeStyleSettingsManager.getSettings(method.getProject()).INSERT_OVERRIDE_ANNOTATION);\r
+   }\r
\r
+   public static void annotateOnOverrideImplement(PsiMethod method, PsiClass targetClass, PsiMethod overridden, boolean insertOverride) {\r
+     if (insertOverride && canInsertOverride(overridden, targetClass)) {\r
+       annotate(method, Override.class.getName());\r
+     }\r
+     final Module module = ModuleUtil.findModuleForPsiElement(targetClass);\r
+     final GlobalSearchScope moduleScope = module != null ? GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module) : null;\r
+     final Project project = targetClass.getProject();\r
+     final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);\r
+     for (OverrideImplementsAnnotationsHandler each : Extensions.getExtensions(OverrideImplementsAnnotationsHandler.EP_NAME)) {\r
+       for (String annotation : each.getAnnotations(project)) {\r
+         if (moduleScope != null && facade.findClass(annotation, moduleScope) == null) continue;\r
+         if (AnnotationUtil.isAnnotated(overridden, annotation, false)) {\r
+           annotate(method, annotation, each.annotationsToRemove(project, annotation));\r
+         }\r
+       }\r
+     }\r
+   }\r
\r
+   public static void annotate(@NotNull PsiMethod result, String fqn, String... annosToRemove) throws IncorrectOperationException {\r
+     Project project = result.getProject();\r
+     AddAnnotationFix fix = new AddAnnotationFix(fqn, result, annosToRemove);\r
+     if (fix.isAvailable(project, null, result.getContainingFile())) {\r
+       fix.invoke(project, null, result.getContainingFile());\r
+     }\r
+   }\r
\r
+   public static boolean isOverridable(PsiMethod method) {\r
+     return !method.isConstructor()\r
+            && !method.hasModifierProperty(PsiModifier.STATIC)\r
+            && !method.hasModifierProperty(PsiModifier.FINAL)\r
+            && !method.hasModifierProperty(PsiModifier.PRIVATE);\r
+   }\r
\r
+   @NotNull\r
+   public static List<PsiGenerationInfo<PsiMethod>> overrideOrImplementMethods(PsiClass aClass,\r
+                                                                               Collection<PsiMethodMember> candidates,\r
+                                                                               boolean toCopyJavaDoc,\r
+                                                                               boolean toInsertAtOverride)\r
+     throws IncorrectOperationException {\r
+     List<CandidateInfo> candidateInfos = ContainerUtil.map2List(candidates, new Function<PsiMethodMember, CandidateInfo>() {\r
+       public CandidateInfo fun(final PsiMethodMember s) {\r
+         return new CandidateInfo(s.getElement(), s.getSubstitutor());\r
+       }\r
+     });\r
+     final List<PsiMethod> methods = overrideOrImplementMethodCandidates(aClass, candidateInfos, toCopyJavaDoc, toInsertAtOverride);\r
+     return convert2GenerationInfos(methods);\r
+   }\r
\r
+   @NotNull\r
+   public static List<PsiMethod> overrideOrImplementMethodCandidates(PsiClass aClass,\r
+                                                                     Collection<CandidateInfo> candidates,\r
+                                                                     boolean toCopyJavaDoc,\r
+                                                                     boolean insertOverrideWherePossible) throws IncorrectOperationException {\r
+     List<PsiMethod> result = new ArrayList<PsiMethod>();\r
+     for (CandidateInfo candidateInfo : candidates) {\r
+       result.addAll(overrideOrImplementMethod(aClass, (PsiMethod)candidateInfo.getElement(), candidateInfo.getSubstitutor(),\r
+                                               toCopyJavaDoc, insertOverrideWherePossible));\r
+     }\r
+     return result;\r
+   }\r
\r
+   public static List<PsiGenerationInfo<PsiMethod>> convert2GenerationInfos(final Collection<PsiMethod> methods) {\r
+     return ContainerUtil.map2List(methods, new Function<PsiMethod, PsiGenerationInfo<PsiMethod>>() {\r
+       public PsiGenerationInfo<PsiMethod> fun(final PsiMethod s) {\r
+         return createGenerationInfo(s);\r
+       }\r
+     });\r
+   }\r
\r
+   public static PsiGenerationInfo<PsiMethod> createGenerationInfo(PsiMethod s) {\r
+     return createGenerationInfo(s, true);\r
+   }\r
\r
+   public static PsiGenerationInfo<PsiMethod> createGenerationInfo(PsiMethod s, boolean mergeIfExists) {\r
+     for (MethodImplementor implementor : getImplementors()) {\r
+       final GenerationInfo info = implementor.createGenerationInfo(s, mergeIfExists);\r
+       if (info instanceof PsiGenerationInfo) return (PsiGenerationInfo<PsiMethod>)info;\r
+     }\r
+     return new PsiGenerationInfo<PsiMethod>(s);\r
+   }\r
\r
+   @NotNull\r
+   public static String callSuper (PsiMethod superMethod, PsiMethod overriding) {\r
+     @NonNls StringBuilder buffer = new StringBuilder();\r
+     if (!superMethod.isConstructor() && superMethod.getReturnType() != PsiType.VOID) {\r
+       buffer.append("return ");\r
+     }\r
+     buffer.append("super");\r
+     PsiParameter[] parms = overriding.getParameterList().getParameters();\r
+     if (!superMethod.isConstructor()){\r
+       buffer.append(".");\r
+       buffer.append(superMethod.getName());\r
+     }\r
+     buffer.append("(");\r
+     for (int i = 0; i < parms.length; i++) {\r
+       String name = parms[i].getName();\r
+       if (i > 0) buffer.append(",");\r
+       buffer.append(name);\r
+     }\r
+     buffer.append(")");\r
+     return buffer.toString();\r
+   }\r
\r
+   public static void setupMethodBody(PsiMethod result, PsiMethod originalMethod, PsiClass targetClass) throws IncorrectOperationException {\r
+     String templName = originalMethod.hasModifierProperty(PsiModifier.ABSTRACT) ?\r
+                        JavaTemplateUtil.TEMPLATE_IMPLEMENTED_METHOD_BODY : JavaTemplateUtil.TEMPLATE_OVERRIDDEN_METHOD_BODY;\r
+     FileTemplate template = FileTemplateManager.getInstance().getCodeTemplate(templName);\r
+     setupMethodBody(result, originalMethod, targetClass, template);\r
+   }\r
\r
+   public static void setupMethodBody(final PsiMethod result, final PsiMethod originalMethod, final PsiClass targetClass,\r
+                                      final FileTemplate template) throws IncorrectOperationException {\r
+     if (targetClass.isInterface()) {\r
+       final PsiCodeBlock body = result.getBody();\r
+       if (body != null) body.delete();\r
+     }\r
\r
+     FileType fileType = FileTypeManager.getInstance().getFileTypeByExtension(template.getExtension());\r
+     PsiType returnType = result.getReturnType();\r
+     if (returnType == null) {\r
+       returnType = PsiType.VOID;\r
+     }\r
+     Properties properties = new Properties();\r
+     properties.setProperty(FileTemplate.ATTRIBUTE_RETURN_TYPE, returnType.getPresentableText());\r
+     properties.setProperty(FileTemplate.ATTRIBUTE_DEFAULT_RETURN_VALUE, PsiTypesUtil.getDefaultValueOfType(returnType));\r
+     properties.setProperty(FileTemplate.ATTRIBUTE_CALL_SUPER, callSuper(originalMethod, result));\r
+     JavaTemplateUtil.setClassAndMethodNameProperties(properties, targetClass, result);\r
\r
 -    PsiElementFactory factory = JavaPsiFacade.getInstance(originalMethod.getProject()).getElementFactory();\r
++    JVMElementFactory factory = JVMElementFactories.getFactory(targetClass.getLanguage(), originalMethod.getProject());\r
++    if (factory == null) factory = JavaPsiFacade.getInstance(originalMethod.getProject()).getElementFactory();\r
+     @NonNls String methodText;\r
+     try {\r
+       String bodyText = template.getText(properties);\r
 -      if (!"".equals(bodyText)) bodyText += "\n";\r
++      if (bodyText != null && !bodyText.isEmpty()) bodyText += "\n";\r
+       methodText = "void foo () {\n" + bodyText + "}";\r
+       methodText = FileTemplateUtil.indent(methodText, result.getProject(), fileType);\r
+     } catch (Exception e) {\r
+       throw new IncorrectOperationException("Failed to parse file template",e);\r
+     }\r
+     if (methodText != null) {\r
+       PsiMethod m;\r
+       try {\r
+         m = factory.createMethodFromText(methodText, originalMethod);\r
+       }\r
+       catch (IncorrectOperationException e) {\r
+         ApplicationManager.getApplication().invokeLater(new Runnable() {\r
+           public void run() {\r
+             Messages.showErrorDialog(CodeInsightBundle.message("override.implement.broken.file.template.message"),\r
+                                      CodeInsightBundle.message("override.implement.broken.file.template.title"));\r
+           }\r
+         });\r
+         return;\r
+       }\r
+       PsiCodeBlock oldBody = result.getBody();\r
+       if (oldBody != null) {\r
+         oldBody.replace(m.getBody());\r
+       }\r
+     }\r
+   }\r
\r
+   public static void chooseAndOverrideMethods(Project project, Editor editor, PsiClass aClass){\r
+     FeatureUsageTracker.getInstance().triggerFeatureUsed(ProductivityFeatureNames.CODEASSISTS_OVERRIDE_IMPLEMENT);\r
+     chooseAndOverrideOrImplementMethods(project, editor, aClass, false);\r
+   }\r
\r
+   public static void chooseAndImplementMethods(Project project, Editor editor, PsiClass aClass){\r
+     FeatureUsageTracker.getInstance().triggerFeatureUsed(ProductivityFeatureNames.CODEASSISTS_OVERRIDE_IMPLEMENT);\r
+     chooseAndOverrideOrImplementMethods(project, editor, aClass, true);\r
+   }\r
\r
+   public static void chooseAndOverrideOrImplementMethods(final Project project,\r
+                                                           final Editor editor,\r
+                                                           final PsiClass aClass,\r
+                                                           final boolean toImplement){\r
+     LOG.assertTrue(aClass.isValid());\r
+     ApplicationManager.getApplication().assertReadAccessAllowed();\r
\r
+     Collection<CandidateInfo> candidates = getMethodsToOverrideImplement(aClass, toImplement);\r
+     Collection<CandidateInfo> secondary = toImplement || aClass.isInterface() ? Collections.<CandidateInfo>emptyList() : getMethodsToOverrideImplement(aClass, true);\r
\r
+     final MemberChooser<PsiMethodMember> chooser = showOverrideImplementChooser(editor, aClass, toImplement, candidates, secondary);\r
+     if (chooser == null) return;\r
\r
+     final List<PsiMethodMember> selectedElements = chooser.getSelectedElements();\r
+     if (selectedElements == null || selectedElements.isEmpty()) return;\r
\r
+     LOG.assertTrue(aClass.isValid());\r
+     new WriteCommandAction(project, aClass.getContainingFile()) {\r
+       protected void run(final Result result) throws Throwable {\r
+         overrideOrImplementMethodsInRightPlace(editor, aClass, selectedElements, chooser.isCopyJavadoc(), chooser.isInsertOverrideAnnotation());\r
+       }\r
+     }.execute();\r
+   }\r
\r
+   @Nullable\r
+   public static MemberChooser<PsiMethodMember> showOverrideImplementChooser(Editor editor,\r
+                                                                             final PsiElement aClass,\r
+                                                                             final boolean toImplement,\r
+                                                                             Collection<CandidateInfo> candidates,\r
+                                                                             Collection<CandidateInfo> secondary) {\r
+     Project project = aClass.getProject();\r
+     if (candidates.isEmpty() && secondary.isEmpty()) return null;\r
\r
+     final PsiMethodMember[] onlyPrimary = convertToMethodMembers(candidates);\r
+     final PsiMethodMember[] all = ArrayUtil.mergeArrays(onlyPrimary, convertToMethodMembers(secondary));\r
\r
+     final String toMerge = PropertiesComponent.getInstance(project).getValue(PROP_COMBINED_OVERRIDE_IMPLEMENT);\r
+     final Ref<Boolean> merge = Ref.create(!"false".equals(toMerge));\r
\r
+     final boolean isAll = merge.get().booleanValue();\r
+     final MemberChooser<PsiMethodMember> chooser = new MemberChooser<PsiMethodMember>(isAll ? all : onlyPrimary, false, true, project,\r
+                                                                                       PsiUtil.isLanguageLevel5OrHigher(aClass)) {\r
\r
+       @Override\r
+       protected void fillToolbarActions(DefaultActionGroup group) {\r
+         super.fillToolbarActions(group);\r
+         if (toImplement) return;\r
\r
+         final ToggleAction mergeAction = new ToggleAction("Show methods to implement", "Show methods to implement",\r
+                                                           AllIcons.General.Show_to_implement) {\r
+           @Override\r
+           public boolean isSelected(AnActionEvent e) {\r
+             return merge.get().booleanValue();\r
+           }\r
\r
+           @Override\r
+           public void setSelected(AnActionEvent e, boolean state) {\r
+             merge.set(state);\r
+             resetElements(state ? all : onlyPrimary);\r
+             setTitle(getChooserTitle(false, merge));\r
+           }\r
+         };\r
+         mergeAction.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_I, InputEvent.ALT_MASK)), myTree);\r
\r
+         Shortcut[] shortcuts = KeymapManager.getInstance().getActiveKeymap().getShortcuts("OverrideMethods");\r
+         mergeAction.registerCustomShortcutSet(new CustomShortcutSet(shortcuts), myTree);\r
\r
+         group.add(mergeAction);\r
+       }\r
+     };\r
+     chooser.setTitle(getChooserTitle(toImplement, merge));\r
+     registerHandlerForComplementaryAction(project, editor, aClass, toImplement, chooser);\r
\r
+     chooser.setCopyJavadocVisible(true);\r
\r
+     if (toImplement) {\r
+       chooser.selectElements(isAll ? all : onlyPrimary);\r
+     }\r
\r
+     if (ApplicationManager.getApplication().isUnitTestMode()) {\r
+       chooser.selectElements(all);\r
+       chooser.close(DialogWrapper.OK_EXIT_CODE);\r
+       return chooser;\r
+     }\r
\r
+     chooser.show();\r
+     if (chooser.getExitCode() != DialogWrapper.OK_EXIT_CODE) return null;\r
\r
+     PropertiesComponent.getInstance(project).setValue(PROP_COMBINED_OVERRIDE_IMPLEMENT, merge.get().toString());\r
+     return chooser;\r
+   }\r
\r
+   private static String getChooserTitle(boolean toImplement, Ref<Boolean> merge) {\r
+     return toImplement\r
+                      ? CodeInsightBundle.message("methods.to.implement.chooser.title")\r
+                      : merge.get().booleanValue()\r
+                        ? CodeInsightBundle.message("methods.to.override.implement.chooser.title")\r
+                        : CodeInsightBundle.message("methods.to.override.chooser.title");\r
+   }\r
\r
+   private static PsiMethodMember[] convertToMethodMembers(Collection<CandidateInfo> candidates) {\r
+     return ContainerUtil.map2Array(candidates, PsiMethodMember.class, new Function<CandidateInfo, PsiMethodMember>() {\r
+         public PsiMethodMember fun(final CandidateInfo s) {\r
+           return new PsiMethodMember(s);\r
+         }\r
+       });\r
+   }\r
\r
+   private static void registerHandlerForComplementaryAction(final Project project, final Editor editor, final PsiElement aClass,\r
+                                                             final boolean toImplement,\r
+                                                             final MemberChooser<PsiMethodMember> chooser) {\r
+     final JComponent preferredFocusedComponent = chooser.getPreferredFocusedComponent();\r
+     final Keymap keymap = KeymapManager.getInstance().getActiveKeymap();\r
\r
+     @NonNls final String s = toImplement ? "OverrideMethods" : "ImplementMethods";\r
+     final Shortcut[] shortcuts = keymap.getShortcuts(s);\r
\r
+     if (shortcuts.length > 0 && shortcuts[0] instanceof KeyboardShortcut) {\r
+       preferredFocusedComponent.getInputMap().put(\r
+         ((KeyboardShortcut)shortcuts[0]).getFirstKeyStroke(), s\r
+       );\r
\r
+       preferredFocusedComponent.getActionMap().put(\r
+           s,\r
+           new AbstractAction() {\r
+             public void actionPerformed(final ActionEvent e) {\r
+               chooser.close(DialogWrapper.CANCEL_EXIT_CODE);\r
\r
+               // invoke later in order to close previous modal dialog\r
+               ApplicationManager.getApplication().invokeLater(new Runnable() {\r
+                 public void run() {\r
+                   final CodeInsightActionHandler handler = toImplement ? new OverrideMethodsHandler(): new ImplementMethodsHandler();\r
+                   handler.invoke(project, editor, aClass.getContainingFile());\r
+                 }\r
+               });\r
+             }\r
+           }\r
+       );\r
+     }\r
+   }\r
\r
+   public static void overrideOrImplementMethodsInRightPlace(Editor editor,\r
+                                                             PsiClass aClass,\r
+                                                             Collection<PsiMethodMember> candidates,\r
+                                                             boolean copyJavadoc,\r
+                                                             boolean insertOverrideWherePossible) {\r
+     try {\r
+       int offset = editor.getCaretModel().getOffset();\r
+       if (aClass.getLBrace() == null) {\r
+         PsiClass psiClass = JavaPsiFacade.getInstance(aClass.getProject()).getElementFactory().createClass("X");\r
+         aClass.addRangeAfter(psiClass.getLBrace(), psiClass.getRBrace(), aClass.getLastChild());\r
+       }\r
\r
+       int lbraceOffset = aClass.getLBrace().getTextOffset();\r
+       List<PsiGenerationInfo<PsiMethod>> resultMembers;\r
+       if (offset <= lbraceOffset || aClass.isEnum()) {\r
+         resultMembers = new ArrayList<PsiGenerationInfo<PsiMethod>>();\r
+         for (PsiMethodMember candidate : candidates) {\r
+           Collection<PsiMethod> prototypes =\r
+             overrideOrImplementMethod(aClass, candidate.getElement(), candidate.getSubstitutor(), copyJavadoc, insertOverrideWherePossible);\r
+           List<PsiGenerationInfo<PsiMethod>> infos = convert2GenerationInfos(prototypes);\r
+           for (PsiGenerationInfo<PsiMethod> info : infos) {\r
+             PsiElement anchor = getDefaultAnchorToOverrideOrImplement(aClass, candidate.getElement(), candidate.getSubstitutor());\r
+             info.insert(aClass, anchor, true);\r
+             resultMembers.add(info);\r
+           }\r
+         }\r
+       }\r
+       else {\r
+         List<PsiGenerationInfo<PsiMethod>> prototypes = overrideOrImplementMethods(aClass, candidates, copyJavadoc, insertOverrideWherePossible);\r
+         resultMembers = GenerateMembersUtil.insertMembersAtOffset(aClass.getContainingFile(), offset, prototypes);\r
+       }\r
\r
+       if (!resultMembers.isEmpty()) {\r
+         resultMembers.get(0).positionCaret(editor, true);\r
+       }\r
+     }\r
+     catch (IncorrectOperationException e) {\r
+       LOG.error(e);\r
+     }\r
+   }\r
\r
+   @Nullable\r
+   public static PsiElement getDefaultAnchorToOverrideOrImplement(PsiClass aClass, PsiMethod baseMethod, PsiSubstitutor substitutor){\r
+     PsiMethod prevBaseMethod = PsiTreeUtil.getPrevSiblingOfType(baseMethod, PsiMethod.class);\r
+     while(prevBaseMethod != null) {\r
+       String name = prevBaseMethod.isConstructor() ? aClass.getName() : prevBaseMethod.getName();\r
+       //Happens when aClass instanceof PsiAnonymousClass\r
+       if (name != null) {\r
+         MethodSignature signature = MethodSignatureUtil.createMethodSignature(name, prevBaseMethod.getParameterList(), prevBaseMethod.getTypeParameterList(), substitutor, prevBaseMethod.isConstructor());\r
+         PsiMethod prevMethod = MethodSignatureUtil.findMethodBySignature(aClass, signature, false);\r
+         if (prevMethod != null){\r
+           return prevMethod.getNextSibling();\r
+         }\r
+       }\r
+       prevBaseMethod = PsiTreeUtil.getPrevSiblingOfType(prevBaseMethod, PsiMethod.class);\r
+     }\r
\r
+     PsiMethod nextBaseMethod = PsiTreeUtil.getNextSiblingOfType(baseMethod, PsiMethod.class);\r
+     while(nextBaseMethod != null) {\r
+       String name = nextBaseMethod.isConstructor() ? aClass.getName() : nextBaseMethod.getName();\r
+       if (name != null) {\r
+         MethodSignature signature = MethodSignatureUtil.createMethodSignature(name, nextBaseMethod.getParameterList(), nextBaseMethod.getTypeParameterList(), substitutor, nextBaseMethod.isConstructor());\r
+         PsiMethod nextMethod = MethodSignatureUtil.findMethodBySignature(aClass, signature, false);\r
+         if (nextMethod != null){\r
+           return nextMethod;\r
+         }\r
+       }\r
+       nextBaseMethod = PsiTreeUtil.getNextSiblingOfType(nextBaseMethod, PsiMethod.class);\r
+     }\r
\r
+     return null;\r
+   }\r
\r
+   public static void overrideOrImplement(PsiClass psiClass, @NotNull PsiMethod baseMethod) throws IncorrectOperationException {\r
+     FileEditorManager fileEditorManager = FileEditorManager.getInstance(baseMethod.getProject());\r
\r
+     List<PsiGenerationInfo<PsiMethod>> prototypes = convert2GenerationInfos(overrideOrImplementMethod(psiClass, baseMethod, false));\r
+     if (prototypes.isEmpty()) return;\r
\r
+     PsiSubstitutor substitutor = TypeConversionUtil.getSuperClassSubstitutor(baseMethod.getContainingClass(), psiClass, PsiSubstitutor.EMPTY);\r
+     PsiElement anchor = getDefaultAnchorToOverrideOrImplement(psiClass, baseMethod, substitutor);\r
+     List<PsiGenerationInfo<PsiMethod>> results = GenerateMembersUtil.insertMembersBeforeAnchor(psiClass, anchor, prototypes);\r
\r
+     PsiFile psiFile = psiClass.getContainingFile();\r
+     Editor editor = fileEditorManager.openTextEditor(new OpenFileDescriptor(psiFile.getProject(), psiFile.getVirtualFile()), false);\r
+     if (editor == null) return;\r
\r
+     results.get(0).positionCaret(editor, true);\r
+     editor.getScrollingModel().scrollToCaret(ScrollType.CENTER);\r
+   }\r
\r
+   @Nullable\r
+   public static PsiClass getContextClass(Project project, Editor editor, PsiFile file, boolean allowInterface) {\r
+     PsiDocumentManager.getInstance(project).commitAllDocuments();\r
\r
+     int offset = editor.getCaretModel().getOffset();\r
+     PsiElement element = file.findElementAt(offset);\r
+     do {\r
+       element = PsiTreeUtil.getParentOfType(element, PsiClass.class);\r
+     }\r
+     while (element instanceof PsiTypeParameter);\r
\r
+     final PsiClass aClass = (PsiClass)element;\r
+     if (aClass instanceof JspClass) return null;\r
+     return aClass == null || !allowInterface && aClass.isInterface() ? null : aClass;\r
+   }\r
\r
 -  private static PsiSubstitutor getContextSubstitutor(PsiClass aClass) {\r
 -    if (aClass instanceof PsiAnonymousClass) {\r
 -      return ((PsiAnonymousClass)aClass).getBaseClassType().resolveGenerics().getSubstitutor();\r
 -    }\r
 -\r
 -    return PsiSubstitutor.EMPTY;\r
 -  }\r
 -\r
+   public static void overrideOrImplementMethodsInRightPlace(Editor editor1, PsiClass aClass, Collection<PsiMethodMember> members, boolean copyJavadoc) {\r
+     boolean insert = CodeStyleSettingsManager.getSettings(aClass.getProject()).INSERT_OVERRIDE_ANNOTATION;\r
+     overrideOrImplementMethodsInRightPlace(editor1, aClass, members, copyJavadoc, insert);\r
+   }\r
\r
+   public static List<PsiMethod> overrideOrImplementMethodCandidates(PsiClass aClass, Collection<CandidateInfo> candidatesToImplement,\r
+                                                                     boolean copyJavadoc) throws IncorrectOperationException {\r
+     boolean insert = CodeStyleSettingsManager.getSettings(aClass.getProject()).INSERT_OVERRIDE_ANNOTATION;\r
+     return overrideOrImplementMethodCandidates(aClass, candidatesToImplement, copyJavadoc, insert);\r
+   }\r
\r
+   public static class MethodSignatureComparator implements Comparator<MethodSignature> {\r
+     // signatures should appear in the order of declaration\r
+     public int compare(MethodSignature o1, MethodSignature o2) {\r
+       if (o1 instanceof MethodSignatureBackedByPsiMethod && o2 instanceof MethodSignatureBackedByPsiMethod) {\r
+         PsiMethod m1 = ((MethodSignatureBackedByPsiMethod)o1).getMethod();\r
+         PsiMethod m2 = ((MethodSignatureBackedByPsiMethod)o2).getMethod();\r
+         PsiClass c1 = m1.getContainingClass();\r
+         PsiClass c2 = m2.getContainingClass();\r
+         if (c1 != null && c2 != null) {\r
+           if (c1 == c2) {\r
+             final List<PsiMethod> methods = Arrays.asList(c1.getMethods());\r
+             return methods.indexOf(m1) - methods.indexOf(m2);\r
+           }\r
\r
+           if (c1.isInheritor(c2, true)) return -1;\r
+           if (c2.isInheritor(c1, true)) return 1;\r
\r
+           return StringUtil.notNullize(c1.getName()).compareTo(StringUtil.notNullize(c2.getName()));\r
+         }\r
+         return m1.getTextOffset() - m2.getTextOffset();\r
+       }\r
+       return 0;\r
+     }\r
+   }\r
+ }\r