private boolean isOverridden( PsiClass inheritor, PsiMethod method, PsiMethod superMethod, PsiClass superInterface) { // calculate substitutor of containingClass --> inheritor PsiSubstitutor substitutor = TypeConversionUtil.getSuperClassSubstitutor( myContainingClass, inheritor, PsiSubstitutor.EMPTY); // calculate substitutor of inheritor --> superInterface substitutor = TypeConversionUtil.getSuperClassSubstitutor(superInterface, inheritor, substitutor); return MethodSignatureUtil.isSubsignature( superMethod.getSignature(substitutor), method.getSignature(PsiSubstitutor.EMPTY)); }
@Nullable private static PsiMethod doFindMethodInSuperClassBySignatureInDerived( @NotNull PsiClass superClass, @NotNull PsiSubstitutor superSubstitutor, @NotNull MethodSignature signature, final boolean checkDeep) { final String name = signature.getName(); final PsiMethod[] methods = superClass.findMethodsByName(name, false); for (final PsiMethod method : methods) { if (isSubsignature(method.getSignature(superSubstitutor), signature)) { return method; } } if (checkDeep) { final PsiClass clazz = superClass.getSuperClass(); if (clazz != null && clazz != superClass) { PsiSubstitutor substitutor1 = TypeConversionUtil.getSuperClassSubstitutor(clazz, superClass, superSubstitutor); return doFindMethodInSuperClassBySignatureInDerived(clazz, substitutor1, signature, true); } } return null; }
private static void addDefaultConstructor( JavaChangeInfo changeInfo, PsiClass aClass, final UsageInfo[] usages) throws IncorrectOperationException { if (!(aClass instanceof PsiAnonymousClass)) { PsiElementFactory factory = JavaPsiFacade.getElementFactory(aClass.getProject()); PsiMethod defaultConstructor = factory.createMethodFromText(aClass.getName() + "(){}", aClass); defaultConstructor = (PsiMethod) CodeStyleManager.getInstance(aClass.getProject()).reformat(defaultConstructor); defaultConstructor = (PsiMethod) aClass.add(defaultConstructor); PsiUtil.setModifierProperty( defaultConstructor, VisibilityUtil.getVisibilityModifier(aClass.getModifierList()), true); addSuperCall(changeInfo, defaultConstructor, null, usages); } else { final PsiElement parent = aClass.getParent(); if (parent instanceof PsiNewExpression) { final PsiExpressionList argumentList = ((PsiNewExpression) parent).getArgumentList(); final PsiClass baseClass = changeInfo.getMethod().getContainingClass(); final PsiSubstitutor substitutor = TypeConversionUtil.getSuperClassSubstitutor(baseClass, aClass, PsiSubstitutor.EMPTY); fixActualArgumentsList(argumentList, changeInfo, true, substitutor); } } }
@NotNull private static List<PsiMethod> findMethodsBySignature( @NotNull PsiClass aClass, @NotNull PsiMethod patternMethod, boolean checkBases, boolean stopOnFirst) { final PsiMethod[] methodsByName = aClass.findMethodsByName(patternMethod.getName(), checkBases); if (methodsByName.length == 0) return Collections.emptyList(); final List<PsiMethod> methods = new SmartList<PsiMethod>(); final MethodSignature patternSignature = patternMethod.getSignature(PsiSubstitutor.EMPTY); for (final PsiMethod method : methodsByName) { final PsiClass superClass = method.getContainingClass(); final PsiSubstitutor substitutor; if (checkBases && !aClass.equals(superClass)) { substitutor = TypeConversionUtil.getSuperClassSubstitutor(superClass, aClass, PsiSubstitutor.EMPTY); } else { substitutor = PsiSubstitutor.EMPTY; } final MethodSignature signature = method.getSignature(substitutor); if (signature.equals(patternSignature)) { methods.add(method); if (stopOnFirst) { break; } } } return methods; }
private static PsiSubstitutor calculateSubstitutor( PsiMethod derivedMethod, PsiMethod baseMethod) { PsiSubstitutor substitutor; if (derivedMethod.getManager().areElementsEquivalent(derivedMethod, baseMethod)) { substitutor = PsiSubstitutor.EMPTY; } else { final PsiClass baseClass = baseMethod.getContainingClass(); final PsiClass derivedClass = derivedMethod.getContainingClass(); if (baseClass != null && derivedClass != null && InheritanceUtil.isInheritorOrSelf(derivedClass, baseClass, true)) { final PsiSubstitutor superClassSubstitutor = TypeConversionUtil.getSuperClassSubstitutor( baseClass, derivedClass, PsiSubstitutor.EMPTY); final MethodSignature superMethodSignature = baseMethod.getSignature(superClassSubstitutor); final MethodSignature methodSignature = derivedMethod.getSignature(PsiSubstitutor.EMPTY); final PsiSubstitutor superMethodSubstitutor = MethodSignatureUtil.getSuperMethodSignatureSubstitutor( methodSignature, superMethodSignature); substitutor = superMethodSubstitutor != null ? superMethodSubstitutor : superClassSubstitutor; } else { substitutor = PsiSubstitutor.EMPTY; } } return substitutor; }
@Nullable public static PsiMethod findMethodInSuperClassBySignatureInDerived( @NotNull final PsiClass aClass, @NotNull final PsiClass superClass, @NotNull MethodSignature signature, final boolean checkDeep) { PsiSubstitutor superSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(superClass, aClass, PsiSubstitutor.EMPTY); return doFindMethodInSuperClassBySignatureInDerived( superClass, superSubstitutor, signature, checkDeep); }
public static boolean isSuperMethod( @NotNull PsiMethod superMethodCandidate, @NotNull PsiMethod derivedMethod) { PsiClass superClassCandidate = superMethodCandidate.getContainingClass(); PsiClass derivedClass = derivedMethod.getContainingClass(); if (derivedClass == null || superClassCandidate == null) return false; if (!derivedClass.isInheritor(superClassCandidate, true)) return false; final PsiSubstitutor superSubstitutor = TypeConversionUtil.getSuperClassSubstitutor( superClassCandidate, derivedClass, PsiSubstitutor.EMPTY); final MethodSignature superSignature = superMethodCandidate.getSignature(superSubstitutor); final MethodSignature derivedSignature = derivedMethod.getSignature(PsiSubstitutor.EMPTY); return isSubsignature(superSignature, derivedSignature); }
@Nullable private static PsiType getReturnType(PsiClass psiClass, MethodSignature methodSignature) { final PsiMethod method = getMethod(psiClass, methodSignature); if (method != null) { final PsiClass containingClass = method.getContainingClass(); if (containingClass == null) return null; return TypeConversionUtil.getSuperClassSubstitutor( containingClass, psiClass, PsiSubstitutor.EMPTY) .substitute(method.getReturnType()); } else { return null; } }
private static MethodSignature getMethodSignature( PsiMethod method, PsiClass psiClass, PsiClass containingClass) { final MethodSignature methodSignature; if (containingClass != null && containingClass != psiClass) { methodSignature = method.getSignature( TypeConversionUtil.getSuperClassSubstitutor( containingClass, psiClass, PsiSubstitutor.EMPTY)); } else { methodSignature = method.getSignature(PsiSubstitutor.EMPTY); } return methodSignature; }
public static PsiSubstitutor getSubstitutor( @NotNull PsiMethod method, @NotNull PsiClassType.ClassResolveResult resolveResult) { final PsiClass derivedClass = resolveResult.getElement(); LOG.assertTrue(derivedClass != null); final PsiClass methodContainingClass = method.getContainingClass(); LOG.assertTrue(methodContainingClass != null); PsiSubstitutor initialSubst = resolveResult.getSubstitutor(); final PsiSubstitutor superClassSubstitutor = TypeConversionUtil.getSuperClassSubstitutor( methodContainingClass, derivedClass, PsiSubstitutor.EMPTY); for (PsiTypeParameter param : superClassSubstitutor.getSubstitutionMap().keySet()) { final PsiType substitute = superClassSubstitutor.substitute(param); if (substitute != null) { initialSubst = initialSubst.put(param, initialSubst.substitute(substitute)); } } return initialSubst; }
private static void processConstructor(GrMethod constructor, JavaChangeInfo changeInfo) { final PsiClass containingClass = constructor.getContainingClass(); final PsiClass baseClass = changeInfo.getMethod().getContainingClass(); final PsiSubstitutor substitutor = TypeConversionUtil.getSuperClassSubstitutor( baseClass, containingClass, PsiSubstitutor.EMPTY); GrOpenBlock block = constructor.getBlock(); GrConstructorInvocation invocation = GroovyPsiElementFactory.getInstance(constructor.getProject()) .createConstructorInvocation("super()"); invocation = (GrConstructorInvocation) block.addStatementBefore(invocation, getFirstStatement(block)); processMethodUsage( invocation.getInvokedExpression(), changeInfo, changeInfo.isParameterSetOrOrderChanged() || changeInfo.isParameterNamesChanged(), changeInfo.isExceptionSetChanged(), GrClosureSignatureUtil.ArgInfo.<PsiElement>empty_array(), substitutor); }
private static void addSuperCall( JavaChangeInfo changeInfo, PsiMethod constructor, PsiMethod callee, final UsageInfo[] usages) throws IncorrectOperationException { final PsiElementFactory factory = JavaPsiFacade.getElementFactory(constructor.getProject()); PsiExpressionStatement superCall = (PsiExpressionStatement) factory.createStatementFromText("super();", constructor); PsiCodeBlock body = constructor.getBody(); assert body != null; PsiStatement[] statements = body.getStatements(); if (statements.length > 0) { superCall = (PsiExpressionStatement) body.addBefore(superCall, statements[0]); } else { superCall = (PsiExpressionStatement) body.add(superCall); } PsiMethodCallExpression callExpression = (PsiMethodCallExpression) superCall.getExpression(); final PsiClass aClass = constructor.getContainingClass(); final PsiClass baseClass = changeInfo.getMethod().getContainingClass(); final PsiSubstitutor substitutor = TypeConversionUtil.getSuperClassSubstitutor(baseClass, aClass, PsiSubstitutor.EMPTY); processMethodUsage( callExpression.getMethodExpression(), changeInfo, true, false, callee, substitutor, usages); }
private static void checkSuperclassMembers( PsiClass superClass, MemberInfoBase<? extends PsiMember>[] infos, MultiMap<PsiElement, String> conflictsList) { for (MemberInfoBase<? extends PsiMember> info : infos) { PsiMember member = info.getMember(); boolean isConflict = false; if (member instanceof PsiField) { String name = member.getName(); isConflict = superClass.findFieldByName(name, false) != null; } else if (member instanceof PsiMethod) { PsiSubstitutor superSubstitutor = TypeConversionUtil.getSuperClassSubstitutor( superClass, member.getContainingClass(), PsiSubstitutor.EMPTY); MethodSignature signature = ((PsiMethod) member).getSignature(superSubstitutor); final PsiMethod superClassMethod = MethodSignatureUtil.findMethodBySignature(superClass, signature, false); isConflict = superClassMethod != null; } if (isConflict) { String message = RefactoringBundle.message( "0.already.contains.a.1", RefactoringUIUtil.getDescription(superClass, false), RefactoringUIUtil.getDescription(member, false)); message = CommonRefactoringUtil.capitalize(message); conflictsList.putValue(superClass, message); } if (member instanceof PsiMethod) { final PsiMethod method = (PsiMethod) member; final PsiModifierList modifierList = method.getModifierList(); if (!modifierList.hasModifierProperty(PsiModifier.PRIVATE)) { for (PsiClass subClass : ClassInheritorsSearch.search(superClass)) { if (method.getContainingClass() != subClass) { MethodSignature signature = ((PsiMethod) member) .getSignature( TypeConversionUtil.getSuperClassSubstitutor( superClass, subClass, PsiSubstitutor.EMPTY)); final PsiMethod wouldBeOverriden = MethodSignatureUtil.findMethodBySignature(subClass, signature, false); if (wouldBeOverriden != null && VisibilityUtil.compare( VisibilityUtil.getVisibilityModifier(wouldBeOverriden.getModifierList()), VisibilityUtil.getVisibilityModifier(modifierList)) > 0) { conflictsList.putValue( wouldBeOverriden, CommonRefactoringUtil.capitalize( RefactoringUIUtil.getDescription(method, true) + " in super class would clash with local method from " + RefactoringUIUtil.getDescription(subClass, true))); } } } } } } }
@NotNull private static LookupElement castQualifier( @NotNull LookupElement item, @Nullable final PsiTypeLookupItem castTypeItem, @Nullable PsiType plainQualifier, JavaCompletionProcessor processor) { if (castTypeItem == null) { return item; } if (plainQualifier != null) { Object o = item.getObject(); if (o instanceof PsiMethod) { PsiType castType = castTypeItem.getType(); if (plainQualifier instanceof PsiClassType && castType instanceof PsiClassType) { PsiMethod method = (PsiMethod) o; PsiClassType.ClassResolveResult plainResult = ((PsiClassType) plainQualifier).resolveGenerics(); PsiClass plainClass = plainResult.getElement(); if (plainClass != null && plainClass.findMethodBySignature(method, true) != null) { PsiClass castClass = ((PsiClassType) castType).resolveGenerics().getElement(); if (castClass == null || !castClass.isInheritor(plainClass, true)) { return item; } PsiSubstitutor plainSub = plainResult.getSubstitutor(); PsiSubstitutor castSub = TypeConversionUtil.getSuperClassSubstitutor(plainClass, (PsiClassType) castType); PsiType returnType = method.getReturnType(); if (method.getSignature(plainSub).equals(method.getSignature(castSub))) { PsiType typeAfterCast = toRaw(castSub.substitute(returnType)); PsiType typeDeclared = toRaw(plainSub.substitute(returnType)); if (typeAfterCast != null && typeDeclared != null && typeAfterCast.isAssignableFrom(typeDeclared) && processor.isAccessible(plainClass.findMethodBySignature(method, true))) { return item; } } } } } else if (containsMember(plainQualifier, o)) { return item; } } return LookupElementDecorator.withInsertHandler( item, new InsertHandlerDecorator<LookupElement>() { @Override public void handleInsert( InsertionContext context, LookupElementDecorator<LookupElement> item) { final Document document = context.getEditor().getDocument(); context.commitDocument(); final PsiFile file = context.getFile(); final PsiJavaCodeReferenceElement ref = PsiTreeUtil.findElementOfClassAtOffset( file, context.getStartOffset(), PsiJavaCodeReferenceElement.class, false); if (ref != null) { final PsiElement qualifier = ref.getQualifier(); if (qualifier != null) { final CommonCodeStyleSettings settings = context.getCodeStyleSettings(); final String parenSpace = settings.SPACE_WITHIN_PARENTHESES ? " " : ""; document.insertString(qualifier.getTextRange().getEndOffset(), parenSpace + ")"); final String spaceWithin = settings.SPACE_WITHIN_CAST_PARENTHESES ? " " : ""; final String prefix = "(" + parenSpace + "(" + spaceWithin; final String spaceAfter = settings.SPACE_AFTER_TYPE_CAST ? " " : ""; final int exprStart = qualifier.getTextRange().getStartOffset(); document.insertString(exprStart, prefix + spaceWithin + ")" + spaceAfter); CompletionUtil.emulateInsertion(context, exprStart + prefix.length(), castTypeItem); PsiDocumentManager.getInstance(file.getProject()) .doPostponedOperationsAndUnblockDocument(document); context.getEditor().getCaretModel().moveToOffset(context.getTailOffset()); } } item.getDelegate().handleInsert(context); } }); }