/* * Copyright 2000-2013 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.ExceptionUtil; import com.intellij.codeInsight.daemon.impl.quickfix.CreateFromUsageUtils; import com.intellij.lang.ASTNode; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.RangeMarker; import com.intellij.openapi.editor.ScrollType; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Pair; 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.JavaCodeStyleManager; import com.intellij.psi.codeStyle.VariableKind; import com.intellij.psi.impl.light.LightTypeElement; import com.intellij.psi.impl.source.tree.PsiWhiteSpaceImpl; import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PropertyUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; import com.intellij.refactoring.util.RefactoringUtil; import com.intellij.util.IncorrectOperationException; import com.intellij.util.VisibilityUtil; import com.intellij.util.containers.HashMap; import com.intellij.util.text.UniqueNameGenerator; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; public class GenerateMembersUtil { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.generation.GenerateMembersUtil"); private GenerateMembersUtil() { } @NotNull public static List insertMembersAtOffset(PsiFile file, int offset, @NotNull List memberPrototypes) throws IncorrectOperationException { if (memberPrototypes.isEmpty()) return memberPrototypes; final PsiElement leaf = file.findElementAt(offset); if (leaf == null) return Collections.emptyList(); PsiClass aClass = findClassAtOffset(file, leaf); if (aClass == null) return Collections.emptyList(); PsiElement anchor = memberPrototypes.get(0).findInsertionAnchor(aClass, leaf); if (anchor instanceof PsiWhiteSpace) { final ASTNode spaceNode = anchor.getNode(); anchor = anchor.getNextSibling(); assert spaceNode != null; if (spaceNode.getStartOffset() <= offset && spaceNode.getStartOffset() + spaceNode.getTextLength() >= offset) { String whiteSpace = spaceNode.getText().substring(0, offset - spaceNode.getStartOffset()); if (!StringUtil.containsLineBreak(whiteSpace)) { // There is a possible case that the caret is located at the end of the line that already contains expression, say, we // want to override particular method while caret is located after the field. // Example - consider that we want to override toString() method at the class below: // class Test { // int i; // } // We want to add line feed then in order to avoid situation like below: // class Test { // int i;@Override String toString() { // super.toString(); // } // } whiteSpace += "\n"; } final PsiParserFacade parserFacade = PsiParserFacade.SERVICE.getInstance(file.getProject()); final ASTNode singleNewLineWhitespace = parserFacade.createWhiteSpaceFromText(whiteSpace).getNode(); if (singleNewLineWhitespace != null) { spaceNode.getTreeParent().replaceChild(spaceNode, singleNewLineWhitespace); // See http://jetbrains.net/jira/browse/IDEADEV-12837 } } } // Q: shouldn't it be somewhere in PSI? PsiElement element = anchor; while (true) { if (element == null) break; if (element instanceof PsiField || element instanceof PsiMethod || element instanceof PsiClassInitializer) break; element = element.getNextSibling(); } if (element instanceof PsiField) { PsiField field = (PsiField)element; PsiTypeElement typeElement = field.getTypeElement(); if (typeElement != null && !field.equals(typeElement.getParent())) { field.normalizeDeclaration(); anchor = field; } } return insertMembersBeforeAnchor(aClass, anchor, memberPrototypes); } @NotNull public static List insertMembersBeforeAnchor(PsiClass aClass, @Nullable PsiElement anchor, @NotNull List memberPrototypes) throws IncorrectOperationException { boolean before = true; for (T memberPrototype : memberPrototypes) { memberPrototype.insert(aClass, anchor, before); before = false; anchor = memberPrototype.getPsiMember(); } return memberPrototypes; } /** * @see GenerationInfo#positionCaret(com.intellij.openapi.editor.Editor, boolean) */ public static void positionCaret(@NotNull Editor editor, @NotNull PsiElement firstMember, boolean toEditMethodBody) { LOG.assertTrue(firstMember.isValid()); Project project = firstMember.getProject(); if (toEditMethodBody) { PsiMethod method = (PsiMethod)firstMember; PsiCodeBlock body = method.getBody(); if (body != null) { PsiElement firstBodyElement = body.getFirstBodyElement(); PsiElement l = firstBodyElement; while (l instanceof PsiWhiteSpace) l = l.getNextSibling(); if (l == null) l = body; PsiElement lastBodyElement = body.getLastBodyElement(); PsiElement r = lastBodyElement; while (r instanceof PsiWhiteSpace) r = r.getPrevSibling(); if (r == null) r = body; int start = l.getTextRange().getStartOffset(); int end = r.getTextRange().getEndOffset(); boolean adjustLineIndent = false; // body is whitespace if (start > end && firstBodyElement == lastBodyElement && firstBodyElement instanceof PsiWhiteSpaceImpl ) { CharSequence chars = ((PsiWhiteSpaceImpl)firstBodyElement).getChars(); if (chars.length() > 1 && chars.charAt(0) == '\n' && chars.charAt(1) == '\n') { start = end = firstBodyElement.getTextRange().getStartOffset() + 1; adjustLineIndent = true; } } editor.getCaretModel().moveToOffset(Math.min(start, end)); editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); if (start < end) { //Not an empty body editor.getSelectionModel().setSelection(start, end); } else if (adjustLineIndent) { Document document = editor.getDocument(); RangeMarker marker = document.createRangeMarker(start, start); PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(document); if (marker.isValid()) { CodeStyleManager.getInstance(project).adjustLineIndent(document, marker.getStartOffset()); } } return; } } int offset; if (firstMember instanceof PsiMethod) { PsiMethod method = (PsiMethod)firstMember; PsiCodeBlock body = method.getBody(); if (body == null) { offset = method.getTextRange().getStartOffset(); } else { offset = body.getLBrace().getTextRange().getEndOffset(); } } else { offset = firstMember.getTextRange().getStartOffset(); } editor.getCaretModel().moveToOffset(offset); editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); editor.getSelectionModel().removeSelection(); } public static PsiElement insert(@NotNull PsiClass aClass, @NotNull PsiMember member, @Nullable PsiElement anchor, boolean before) throws IncorrectOperationException { if (member instanceof PsiMethod) { if (!aClass.isInterface()) { final PsiParameter[] parameters = ((PsiMethod)member).getParameterList().getParameters(); final boolean generateFinals = CodeStyleSettingsManager.getSettings(aClass.getProject()).GENERATE_FINAL_PARAMETERS; for (final PsiParameter parameter : parameters) { final PsiModifierList modifierList = parameter.getModifierList(); assert modifierList != null; modifierList.setModifierProperty(PsiModifier.FINAL, generateFinals); } } } if (anchor != null) { return before ? aClass.addBefore(member, anchor) : aClass.addAfter(member, anchor); } else { return aClass.add(member); } } @Nullable private static PsiClass findClassAtOffset(PsiFile file, PsiElement leaf) { PsiElement element = leaf; while (element != null && !(element instanceof PsiFile)) { if (element instanceof PsiClass && !(element instanceof PsiTypeParameter)) { final PsiClass psiClass = (PsiClass)element; if (psiClass.isEnum()) { PsiElement lastChild = null; for (PsiElement child : psiClass.getChildren()) { if (child instanceof PsiJavaToken && ";".equals(child.getText())) { lastChild = child; break; } else if (child instanceof PsiJavaToken && ",".equals(child.getText()) || child instanceof PsiEnumConstant) { lastChild = child; } } if (lastChild != null) { int adjustedOffset = lastChild.getTextRange().getEndOffset(); if (leaf.getTextRange().getEndOffset() <= adjustedOffset) return findClassAtOffset(file, file.findElementAt(adjustedOffset)); } } return psiClass; } element = element.getParent(); } return null; } public static PsiMethod substituteGenericMethod(PsiMethod method, final PsiSubstitutor substitutor) { return substituteGenericMethod(method, substitutor, null); } public static PsiMethod substituteGenericMethod(@NotNull PsiMethod sourceMethod, @NotNull PsiSubstitutor substitutor, @Nullable PsiElement target) { final Project project = sourceMethod.getProject(); final JVMElementFactory factory = getFactory(sourceMethod, target); final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project); try { final PsiMethod resultMethod = createMethod(factory, sourceMethod, target); copyModifiers(sourceMethod.getModifierList(), resultMethod.getModifierList()); final PsiSubstitutor collisionResolvedSubstitutor = substituteTypeParameters(factory, target, sourceMethod.getTypeParameterList(), resultMethod.getTypeParameterList(), substitutor, sourceMethod); substituteReturnType(PsiManager.getInstance(project), resultMethod, sourceMethod.getReturnType(), collisionResolvedSubstitutor); substituteParameters(factory, codeStyleManager, sourceMethod.getParameterList(), resultMethod.getParameterList(), collisionResolvedSubstitutor, target); copyDocComment(sourceMethod, resultMethod, factory); final List thrownTypes = ExceptionUtil.collectSubstituted(collisionResolvedSubstitutor, sourceMethod.getThrowsList().getReferencedTypes()); if (target instanceof PsiClass) { final PsiClass[] supers = ((PsiClass)target).getSupers(); for (PsiClass aSuper : supers) { final PsiMethod psiMethod = aSuper.findMethodBySignature(sourceMethod, true); if (psiMethod != null && psiMethod != sourceMethod) { ExceptionUtil.retainExceptions(thrownTypes, ExceptionUtil.collectSubstituted(TypeConversionUtil.getSuperClassSubstitutor(aSuper, (PsiClass)target, PsiSubstitutor.EMPTY), psiMethod.getThrowsList().getReferencedTypes())); } } } substituteThrows(factory, resultMethod.getThrowsList(), collisionResolvedSubstitutor, sourceMethod, thrownTypes); return resultMethod; } catch (IncorrectOperationException e) { LOG.error(e); return sourceMethod; } } private static void copyModifiers(@NotNull PsiModifierList sourceModifierList, @NotNull PsiModifierList targetModifierList) { VisibilityUtil.setVisibility(targetModifierList, VisibilityUtil.getVisibilityModifier(sourceModifierList)); } @NotNull private static PsiSubstitutor substituteTypeParameters(@NotNull JVMElementFactory factory, @Nullable PsiElement target, @Nullable PsiTypeParameterList sourceTypeParameterList, @Nullable PsiTypeParameterList targetTypeParameterList, @NotNull PsiSubstitutor substitutor, @NotNull PsiMethod sourceMethod) { if (sourceTypeParameterList == null || targetTypeParameterList == null) { return substitutor; } final Map substitutionMap = new HashMap(substitutor.getSubstitutionMap()); for (PsiTypeParameter typeParam : sourceTypeParameterList.getTypeParameters()) { final PsiTypeParameter substitutedTypeParam = substituteTypeParameter(factory, typeParam, substitutor, sourceMethod); final PsiTypeParameter resolvedTypeParam = resolveTypeParametersCollision(factory, sourceTypeParameterList, target, substitutedTypeParam, substitutor); targetTypeParameterList.add(resolvedTypeParam); if (substitutedTypeParam != resolvedTypeParam) { substitutionMap.put(typeParam, factory.createType(resolvedTypeParam)); } } return substitutionMap.isEmpty() ? substitutor : factory.createSubstitutor(substitutionMap); } @NotNull private static PsiTypeParameter resolveTypeParametersCollision(@NotNull JVMElementFactory factory, @NotNull PsiTypeParameterList sourceTypeParameterList, @Nullable PsiElement target, @NotNull PsiTypeParameter typeParam, @NotNull PsiSubstitutor substitutor) { for (PsiType type : substitutor.getSubstitutionMap().values()) { if (type != null && Comparing.equal(type.getCanonicalText(), typeParam.getName())) { final String newName = suggestUniqueTypeParameterName(typeParam.getName(), sourceTypeParameterList, PsiTreeUtil.getParentOfType(target, PsiClass.class, false)); final PsiTypeParameter newTypeParameter = factory.createTypeParameter(newName, typeParam.getSuperTypes()); substitutor.put(typeParam, factory.createType(newTypeParameter)); return newTypeParameter; } } return factory.createTypeParameter(typeParam.getName(), typeParam.getSuperTypes()); } @NotNull private static String suggestUniqueTypeParameterName(@NonNls String baseName, @NotNull PsiTypeParameterList typeParameterList, @Nullable PsiClass targetClass) { int i = 0; while (true) { final String newName = baseName + ++i; if (checkUniqueTypeParameterName(newName, typeParameterList) && (targetClass == null || checkUniqueTypeParameterName(newName, targetClass.getTypeParameterList()))) { return newName; } } } private static boolean checkUniqueTypeParameterName(@NonNls @NotNull String baseName, @Nullable PsiTypeParameterList typeParameterList) { if (typeParameterList == null) return true; for (PsiTypeParameter typeParameter : typeParameterList.getTypeParameters()) { if (Comparing.equal(typeParameter.getName(), baseName)) { return false; } } return true; } @NotNull private static PsiTypeParameter substituteTypeParameter(final @NotNull JVMElementFactory factory, @NotNull PsiTypeParameter typeParameter, final @NotNull PsiSubstitutor substitutor, @NotNull final PsiMethod sourceMethod) { final PsiElement copy = typeParameter.copy(); final Map replacementMap = new HashMap(); copy.accept(new JavaRecursiveElementVisitor() { @Override public void visitReferenceElement(PsiJavaCodeReferenceElement reference) { super.visitReferenceElement(reference); final PsiElement resolve = reference.resolve(); if (resolve instanceof PsiTypeParameter) { final PsiType type = factory.createType((PsiTypeParameter)resolve); replacementMap.put(reference, factory.createReferenceElementByType((PsiClassType)substituteType(substitutor, type, sourceMethod))); } } }); return (PsiTypeParameter)RefactoringUtil.replaceElementsWithMap(copy, replacementMap); } private static void substituteParameters(@NotNull JVMElementFactory factory, @NotNull JavaCodeStyleManager codeStyleManager, @NotNull PsiParameterList sourceParameterList, @NotNull PsiParameterList targetParameterList, @NotNull PsiSubstitutor substitutor, PsiElement target) { final PsiParameter[] parameters = sourceParameterList.getParameters(); final PsiParameter[] newParameters = overriddenParameters(parameters, factory, codeStyleManager, substitutor, target); for (int i = 0; i < newParameters.length; i++) { final PsiParameter newParameter = newParameters[i]; copyOrReplaceModifierList(parameters[i], newParameter); targetParameterList.add(newParameter); } } public static PsiParameter[] overriddenParameters(PsiParameter[] parameters, @NotNull JVMElementFactory factory, @NotNull JavaCodeStyleManager codeStyleManager, @NotNull PsiSubstitutor substitutor, PsiElement target) { PsiParameter[] result = new PsiParameter[parameters.length]; UniqueNameGenerator generator = new UniqueNameGenerator(); for (int i = 0; i < parameters.length; i++) { PsiParameter parameter = parameters[i]; final PsiType parameterType = parameter.getType(); final PsiType substituted = substituteType(substitutor, parameterType, (PsiMethod)parameter.getDeclarationScope()); @NonNls String paramName = parameter.getName(); boolean isBaseNameGenerated = true; final boolean isSubstituted = substituted.equals(parameterType); if (!isSubstituted && isBaseNameGenerated(codeStyleManager, TypeConversionUtil.erasure(parameterType), paramName)) { isBaseNameGenerated = false; } if (paramName == null || isBaseNameGenerated && !isSubstituted && isBaseNameGenerated(codeStyleManager, parameterType, paramName) || !factory.isValidParameterName(paramName)) { String[] names = codeStyleManager.suggestVariableName(VariableKind.PARAMETER, null, null, substituted).names; if (names.length > 0) { paramName = generator.generateUniqueName(names[0]); } else { paramName = generator.generateUniqueName("p"); } } else if (!generator.value(paramName)) { paramName = generator.generateUniqueName(paramName); } generator.addExistingName(paramName); result[i] = factory.createParameter(paramName, substituted, target); } return result; } private static void substituteThrows(@NotNull JVMElementFactory factory, @NotNull PsiReferenceList targetThrowsList, @NotNull PsiSubstitutor substitutor, @NotNull PsiMethod sourceMethod, List thrownTypes) { for (PsiClassType thrownType : thrownTypes) { targetThrowsList.add(factory.createReferenceElementByType((PsiClassType)substituteType(substitutor, thrownType, sourceMethod))); } } private static void copyDocComment(PsiMethod source, PsiMethod target, JVMElementFactory factory) { final PsiElement navigationElement = source.getNavigationElement(); if (navigationElement instanceof PsiDocCommentOwner) { final PsiDocComment docComment = ((PsiDocCommentOwner)navigationElement).getDocComment(); if (docComment != null) { target.addAfter(factory.createDocCommentFromText(docComment.getText()), null); } } final PsiParameter[] sourceParameters = source.getParameterList().getParameters(); final PsiParameterList targetParameterList = target.getParameterList(); RefactoringUtil.fixJavadocsForParams(target, new HashSet(Arrays.asList(targetParameterList.getParameters())), new Condition>() { @Override public boolean value(Pair pair) { final int parameterIndex = targetParameterList.getParameterIndex(pair.first); if (parameterIndex >= 0 && parameterIndex < sourceParameters.length) { return Comparing.strEqual(pair.second, sourceParameters[parameterIndex].getName()); } return false; } }); } @NotNull private static PsiMethod createMethod(@NotNull JVMElementFactory factory, @NotNull PsiMethod method, PsiElement target) { if (method.isConstructor()) { return factory.createConstructor(method.getName(), target); } return factory.createMethod(method.getName(), PsiType.VOID); } private static void substituteReturnType(@NotNull PsiManager manager, @NotNull PsiMethod method, @Nullable PsiType returnType, @NotNull PsiSubstitutor substitutor) { final PsiTypeElement returnTypeElement = method.getReturnTypeElement(); if (returnTypeElement == null || returnType == null) { return; } final PsiType substitutedReturnType = substituteType(substitutor, returnType, method); returnTypeElement.replace(new LightTypeElement(manager, substitutedReturnType instanceof PsiWildcardType ? TypeConversionUtil.erasure(substitutedReturnType) : substitutedReturnType)); } @NotNull private static JVMElementFactory getFactory(@NotNull PsiMethod method, @Nullable PsiElement target) { if (target == null) { return JavaPsiFacade.getInstance(method.getProject()).getElementFactory(); } return JVMElementFactories.getFactory(target.getLanguage(), method.getProject()); } private static boolean isBaseNameGenerated(JavaCodeStyleManager csManager, PsiType parameterType, String paramName) { return Arrays.asList(csManager.suggestVariableName(VariableKind.PARAMETER, null, null, parameterType).names).contains(paramName); } private static PsiType substituteType(final PsiSubstitutor substitutor, final PsiType type, @NotNull PsiTypeParameterListOwner owner) { if (PsiUtil.isRawSubstitutor(owner, substitutor)) { return TypeConversionUtil.erasure(type); } final PsiType psiType = substitutor.substitute(type); if (psiType != null) { final PsiType deepComponentType = psiType.getDeepComponentType(); if (!(deepComponentType instanceof PsiCapturedWildcardType || deepComponentType instanceof PsiWildcardType)){ return psiType; } } return TypeConversionUtil.erasure(type); } public static boolean isChildInRange(PsiElement child, PsiElement first, PsiElement last) { if (child.equals(first)) return true; while (true) { if (child.equals(first)) return false; // before first if (child.equals(last)) return true; child = child.getNextSibling(); if (child == null) return false; } } public static void setupGeneratedMethod(PsiMethod method) { PsiClass base = method.getContainingClass().getSuperClass(); PsiMethod overridden = base == null ? null : base.findMethodBySignature(method, true); if (overridden == null) { CreateFromUsageUtils.setupMethodBody(method, method.getContainingClass()); return; } OverrideImplementUtil.setupMethodBody(method, overridden, method.getContainingClass()); OverrideImplementUtil.annotateOnOverrideImplement(method, base, overridden); } public static void copyOrReplaceModifierList(@NotNull PsiModifierListOwner sourceParam, @NotNull PsiModifierListOwner targetParam) { PsiModifierList sourceModifierList = sourceParam.getModifierList(); PsiModifierList targetModifierList = targetParam.getModifierList(); if (sourceModifierList != null && targetModifierList != null) { if (sourceParam.getLanguage() == targetParam.getLanguage()) { targetModifierList = (PsiModifierList)targetModifierList.replace(sourceModifierList); } else { JVMElementFactory factory = JVMElementFactories.requireFactory(targetParam.getLanguage(), targetParam.getProject()); for (PsiAnnotation annotation : sourceModifierList.getAnnotations()) { targetModifierList.add(factory.createAnnotationFromText(annotation.getText(), sourceParam)); } for (@PsiModifier.ModifierConstant String m : PsiModifier.MODIFIERS) { targetModifierList.setModifierProperty(m, sourceParam.hasModifierProperty(m)); } } processAnnotations(sourceModifierList.getProject(), targetModifierList, targetModifierList.getResolveScope()); } } private static void processAnnotations(Project project, PsiModifierList modifierList, GlobalSearchScope moduleScope) { final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project); final Set toRemove = new HashSet(); for (PsiAnnotation annotation : modifierList.getAnnotations()) { final String qualifiedName = annotation.getQualifiedName(); if (qualifiedName != null) { for (OverrideImplementsAnnotationsHandler handler : Extensions.getExtensions(OverrideImplementsAnnotationsHandler.EP_NAME)) { final String[] annotations2Remove = handler.annotationsToRemove(project, qualifiedName); Collections.addAll(toRemove, annotations2Remove); if (moduleScope != null && psiFacade.findClass(qualifiedName, moduleScope) == null) { toRemove.add(qualifiedName); } } } } for (String fqn : toRemove) { final PsiAnnotation psiAnnotation = modifierList.findAnnotation(fqn); if (psiAnnotation != null) { psiAnnotation.delete(); } } } @Nullable public static PsiMethod generateGetterPrototype(@NotNull PsiField field) { return setVisibility(field, annotateOnOverrideImplement(field.getContainingClass(), PropertyUtil.generateGetterPrototype(field))); } @Nullable public static PsiMethod generateSetterPrototype(@NotNull PsiField field) { return setVisibility(field, annotateOnOverrideImplement(field.getContainingClass(), PropertyUtil.generateSetterPrototype(field))); } @Contract("_, null -> null") public static PsiMethod setVisibility(PsiMember member, PsiMethod prototype) { if (prototype == null) return null; final String visibility = CodeStyleSettingsManager.getSettings(member.getProject()).VISIBILITY; final PsiModifierList modifierList = prototype.getModifierList(); final String newVisibility = VisibilityUtil.ESCALATE_VISIBILITY.equals(visibility) ? PsiUtil.getMaximumModifierForMember(member instanceof PsiClass ? (PsiClass)member : member.getContainingClass(), false) : visibility; VisibilityUtil.setVisibility(modifierList, newVisibility); return prototype; } @Nullable public static PsiMethod annotateOnOverrideImplement(@Nullable PsiClass targetClass, @Nullable PsiMethod generated) { if (generated == null || targetClass == null) return generated; if (CodeStyleSettingsManager.getSettings(targetClass.getProject()).INSERT_OVERRIDE_ANNOTATION) { PsiMethod superMethod = targetClass.findMethodBySignature(generated, true); if (superMethod != null && superMethod.getContainingClass() != targetClass) { OverrideImplementUtil.annotateOnOverrideImplement(generated, targetClass, superMethod, true); } } return generated; } }