public static GrMethod generateDelegate( PsiMethod prototype, IntroduceParameterData.ExpressionWrapper initializer, Project project) { final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(project); GrMethod result; if (prototype instanceof GrMethod) { result = (GrMethod) prototype.copy(); } else { StringBuilder builder = new StringBuilder(); builder.append(prototype.getModifierList().getText()).append(' '); if (prototype.getReturnTypeElement() != null) { builder.append(prototype.getReturnTypeElement().getText()); } builder.append(' ').append(prototype.getName()); builder.append(prototype.getParameterList().getText()); builder.append("{}"); result = factory.createMethodFromText(builder.toString()); } StringBuilder call = new StringBuilder(); call.append("def foo(){\n"); final GrParameter[] parameters = result.getParameters(); call.append(prototype.getName()); if (initializer.getExpression() instanceof GrClosableBlock) { if (parameters.length > 0) { call.append('('); for (GrParameter parameter : parameters) { call.append(parameter.getName()).append(", "); } call.replace(call.length() - 2, call.length(), ")"); } call.append(initializer.getText()); } else { call.append('('); for (GrParameter parameter : parameters) { call.append(parameter.getName()).append(", "); } call.append(initializer.getText()); call.append(")"); } call.append("\n}"); final GrOpenBlock block = factory.createMethodFromText(call.toString()).getBlock(); result.getBlock().replace(block); final PsiElement parent = prototype.getParent(); final GrMethod method = (GrMethod) parent.addBefore(result, prototype); GrReferenceAdjuster.shortenReferences(method); return method; }
/** * Check the element. If the element is a PsiMethod, than we want to know if it's a @Provides * method, or a Constructor annotated w/ @Inject. * * <p>If element is a field, than we only want to see if it is annotated with @Inject. * * @return a {@link com.intellij.codeInsight.daemon.GutterIconNavigationHandler} for the * appropriate type, or null if we don't care about it. */ @Nullable @Override public LineMarkerInfo getLineMarkerInfo(@NotNull final PsiElement element) { // Check methods first (includes constructors). if (element instanceof PsiMethod) { PsiMethod methodElement = (PsiMethod) element; // @Provides if (PsiConsultantImpl.hasAnnotation(element, CLASS_PROVIDES)) { PsiTypeElement returnTypeElement = methodElement.getReturnTypeElement(); if (returnTypeElement != null) { return new LineMarkerInfo<PsiElement>( element, returnTypeElement.getTextRange(), ICON, UPDATE_ALL, null, new ProvidesToInjectHandler(), LEFT); } } // Constructor injection. if (methodElement.isConstructor() && PsiConsultantImpl.hasAnnotation(element, CLASS_INJECT)) { PsiIdentifier nameIdentifier = methodElement.getNameIdentifier(); if (nameIdentifier != null) { return new LineMarkerInfo<PsiElement>( element, nameIdentifier.getTextRange(), ICON, UPDATE_ALL, null, new ConstructorInjectToProvidesHandler(), LEFT); } } // Not a method, is it a Field? } else if (element instanceof PsiField) { // Field injection. PsiField fieldElement = (PsiField) element; PsiTypeElement typeElement = fieldElement.getTypeElement(); if (PsiConsultantImpl.hasAnnotation(element, CLASS_INJECT) && typeElement != null) { return new LineMarkerInfo<PsiElement>( element, typeElement.getTextRange(), ICON, UPDATE_ALL, null, new FieldInjectToProvidesHandler(), LEFT); } } return null; }
@NotNull private List<MethodContract> visitStatements( List<ValueConstraint[]> states, PsiStatement... statements) { List<MethodContract> result = ContainerUtil.newArrayList(); for (PsiStatement statement : statements) { if (statement instanceof PsiBlockStatement && ((PsiBlockStatement) statement).getCodeBlock().getStatements().length == 1) { result.addAll( visitStatements( states, ((PsiBlockStatement) statement).getCodeBlock().getStatements())); } else if (statement instanceof PsiIfStatement) { List<MethodContract> conditionResults = visitExpression(states, ((PsiIfStatement) statement).getCondition()); PsiStatement thenBranch = ((PsiIfStatement) statement).getThenBranch(); if (thenBranch != null) { result.addAll( visitStatements( antecedentsOf(filterReturning(conditionResults, TRUE_VALUE)), thenBranch)); } List<ValueConstraint[]> falseStates = antecedentsOf(filterReturning(conditionResults, FALSE_VALUE)); PsiStatement elseBranch = ((PsiIfStatement) statement).getElseBranch(); if (elseBranch != null) { result.addAll(visitStatements(falseStates, elseBranch)); } else if (alwaysReturns(thenBranch)) { states = falseStates; continue; } } else if (statement instanceof PsiThrowStatement) { result.addAll(toContracts(states, THROW_EXCEPTION)); } else if (statement instanceof PsiReturnStatement) { List<MethodContract> contracts = visitExpression(states, ((PsiReturnStatement) statement).getReturnValue()); for (MethodContract contract : contracts) { if ((contract.returnValue == TRUE_VALUE || contract.returnValue == FALSE_VALUE) && !textMatches(myMethod.getReturnTypeElement(), PsiKeyword.BOOLEAN)) { continue; } result.add(contract); } } else if (statement instanceof PsiAssertStatement) { List<MethodContract> conditionResults = visitExpression(states, ((PsiAssertStatement) statement).getAssertCondition()); result.addAll( toContracts( antecedentsOf(filterReturning(conditionResults, FALSE_VALUE)), THROW_EXCEPTION)); } break; // visit only the first statement unless it's 'if' whose 'then' always returns and the // next statement is effectively 'else' } return result; }
public JLabel getPopupEntryText(RearrangerSettings settings) { StringBuffer name = new StringBuffer(80); PsiMethod m = (PsiMethod) myEnd; if (m.getReturnTypeElement() != null && !settings.isShowTypeAfterMethod()) { name.append(m.getReturnTypeElement().getText()); name.append(' '); } name.append(m.getName()); PsiParameterList plist = m.getParameterList(); if (settings.isShowParameterNames() || settings.isShowParameterTypes()) { if (plist != null) { name.append("("); for (int i = 0; i < plist.getParameters().length; i++) { if (i > 0) { name.append(", "); } if (settings.isShowParameterTypes()) { String modifiers = plist.getParameters()[i].getModifierList().getText(); if (modifiers.length() > 0) { name.append(modifiers); name.append(' '); } name.append(plist.getParameters()[i].getTypeElement().getText()); if (settings.isShowParameterNames()) { name.append(' '); } } if (settings.isShowParameterNames()) { name.append(plist.getParameters()[i].getName()); } } name.append(")"); } } if (m.getReturnTypeElement() != null && settings.isShowTypeAfterMethod()) { name.append(": "); name.append(m.getReturnTypeElement().getText()); } return new JLabel(name.toString()); }
@Nullable public static PsiTypeElement getPropertyTypeElement(final PsiMember member) { if (member instanceof PsiField) { return ((PsiField) member).getTypeElement(); } else if (member instanceof PsiMethod) { final PsiMethod psiMethod = (PsiMethod) member; if (isSimplePropertyGetter(psiMethod)) { return psiMethod.getReturnTypeElement(); } else if (isSimplePropertySetter(psiMethod)) { return psiMethod.getParameterList().getParameters()[0].getTypeElement(); } } return null; }
public static MultiMap<PsiElement, String> checkConflicts( final MemberInfoBase<? extends PsiMember>[] infos, @NotNull final PsiClass subclass, @Nullable PsiClass superClass, @NotNull final PsiPackage targetPackage, @NotNull PsiDirectory targetDirectory, final InterfaceContainmentVerifier interfaceContainmentVerifier, boolean movedMembers2Super) { final Set<PsiMember> movedMembers = new HashSet<PsiMember>(); final Set<PsiMethod> abstractMethods = new HashSet<PsiMethod>(); final boolean isInterfaceTarget; final PsiElement targetRepresentativeElement; if (superClass != null) { isInterfaceTarget = superClass.isInterface(); targetRepresentativeElement = superClass; } else { isInterfaceTarget = false; targetRepresentativeElement = targetDirectory; } for (MemberInfoBase<? extends PsiMember> info : infos) { PsiMember member = info.getMember(); if (member instanceof PsiMethod) { if (!info.isToAbstract() && !isInterfaceTarget) { movedMembers.add(member); } else { abstractMethods.add((PsiMethod) member); } } else { movedMembers.add(member); } } final MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>(); final Set<PsiMethod> abstrMethods = new HashSet<PsiMethod>(abstractMethods); if (superClass != null) { for (PsiMethod method : subclass.getMethods()) { if (!movedMembers.contains(method) && !method.hasModifierProperty(PsiModifier.PRIVATE)) { if (method.findSuperMethods(superClass).length > 0) { abstrMethods.add(method); } } } } RefactoringConflictsUtil.analyzeAccessibilityConflicts( movedMembers, superClass, conflicts, VisibilityUtil.ESCALATE_VISIBILITY, targetRepresentativeElement, abstrMethods); if (superClass != null) { if (movedMembers2Super) { checkSuperclassMembers(superClass, infos, conflicts); if (isInterfaceTarget) { checkInterfaceTarget(infos, conflicts); } } else { final String qualifiedName = superClass.getQualifiedName(); assert qualifiedName != null; if (superClass.hasModifierProperty(PsiModifier.PACKAGE_LOCAL)) { if (!Comparing.strEqual( StringUtil.getPackageName(qualifiedName), targetPackage.getQualifiedName())) { conflicts.putValue( superClass, RefactoringUIUtil.getDescription(superClass, true) + " won't be accessible from " + RefactoringUIUtil.getDescription(targetPackage, true)); } } } } // check if moved methods use other members in the classes between Subclass and Superclass List<PsiElement> checkModuleConflictsList = new ArrayList<PsiElement>(); for (PsiMember member : movedMembers) { if (member instanceof PsiMethod || member instanceof PsiClass && !(member instanceof PsiCompiledElement)) { ClassMemberReferencesVisitor visitor = movedMembers2Super ? new ConflictingUsagesOfSubClassMembers( member, movedMembers, abstractMethods, subclass, superClass, superClass != null ? null : targetPackage, conflicts, interfaceContainmentVerifier) : new ConflictingUsagesOfSuperClassMembers( member, subclass, targetPackage, movedMembers, conflicts); member.accept(visitor); } ContainerUtil.addIfNotNull(checkModuleConflictsList, member); } for (final PsiMethod method : abstractMethods) { ContainerUtil.addIfNotNull(checkModuleConflictsList, method.getParameterList()); ContainerUtil.addIfNotNull(checkModuleConflictsList, method.getReturnTypeElement()); ContainerUtil.addIfNotNull(checkModuleConflictsList, method.getTypeParameterList()); } RefactoringConflictsUtil.analyzeModuleConflicts( subclass.getProject(), checkModuleConflictsList, new UsageInfo[0], targetRepresentativeElement, conflicts); final String fqName = subclass.getQualifiedName(); final String packageName; if (fqName != null) { packageName = StringUtil.getPackageName(fqName); } else { final PsiFile psiFile = PsiTreeUtil.getParentOfType(subclass, PsiFile.class); if (psiFile instanceof PsiClassOwner) { packageName = ((PsiClassOwner) psiFile).getPackageName(); } else { packageName = null; } } final boolean toDifferentPackage = !Comparing.strEqual(targetPackage.getQualifiedName(), packageName); for (final PsiMethod abstractMethod : abstractMethods) { abstractMethod.accept( new ClassMemberReferencesVisitor(subclass) { @Override protected void visitClassMemberReferenceElement( PsiMember classMember, PsiJavaCodeReferenceElement classMemberReference) { if (classMember != null && willBeMoved(classMember, movedMembers)) { boolean isAccessible = false; if (classMember.hasModifierProperty(PsiModifier.PRIVATE)) { isAccessible = true; } else if (classMember.hasModifierProperty(PsiModifier.PACKAGE_LOCAL) && toDifferentPackage) { isAccessible = true; } if (isAccessible) { String message = RefactoringUIUtil.getDescription(abstractMethod, false) + " uses " + RefactoringUIUtil.getDescription(classMember, true) + " which won't be accessible from the subclass."; message = CommonRefactoringUtil.capitalize(message); conflicts.putValue(classMember, message); } } } }); if (abstractMethod.hasModifierProperty(PsiModifier.PACKAGE_LOCAL) && toDifferentPackage) { if (!isInterfaceTarget) { String message = "Can't make " + RefactoringUIUtil.getDescription(abstractMethod, false) + " abstract as it won't be accessible from the subclass."; message = CommonRefactoringUtil.capitalize(message); conflicts.putValue(abstractMethod, message); } } } return conflicts; }
private static void processPrimaryMethod( JavaChangeInfo changeInfo, PsiMethod method, PsiMethod baseMethod, boolean isOriginal) throws IncorrectOperationException { PsiElementFactory factory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory(); if (changeInfo.isVisibilityChanged()) { PsiModifierList modifierList = method.getModifierList(); final String highestVisibility = isOriginal ? changeInfo.getNewVisibility() : VisibilityUtil.getHighestVisibility( changeInfo.getNewVisibility(), VisibilityUtil.getVisibilityModifier(modifierList)); VisibilityUtil.setVisibility(modifierList, highestVisibility); } if (changeInfo.isNameChanged()) { String newName = baseMethod == null ? changeInfo.getNewName() : RefactoringUtil.suggestNewOverriderName( method.getName(), baseMethod.getName(), changeInfo.getNewName()); if (newName != null && !newName.equals(method.getName())) { final PsiIdentifier nameId = method.getNameIdentifier(); assert nameId != null; nameId.replace( JavaPsiFacade.getInstance(method.getProject()) .getElementFactory() .createIdentifier(newName)); } } final PsiSubstitutor substitutor = baseMethod == null ? PsiSubstitutor.EMPTY : ChangeSignatureProcessor.calculateSubstitutor(method, baseMethod); if (changeInfo.isReturnTypeChanged()) { PsiType newTypeElement = changeInfo .getNewReturnType() .getType(changeInfo.getMethod().getParameterList(), method.getManager()); final PsiType returnType = substitutor.substitute(newTypeElement); // don't modify return type for non-Java overriders (EJB) if (method.getName().equals(changeInfo.getNewName())) { final PsiTypeElement typeElement = method.getReturnTypeElement(); if (typeElement != null) { typeElement.replace(factory.createTypeElement(returnType)); } } } PsiParameterList list = method.getParameterList(); PsiParameter[] parameters = list.getParameters(); final JavaParameterInfo[] parameterInfos = changeInfo.getNewParameters(); final int delta = baseMethod != null ? baseMethod.getParameterList().getParametersCount() - method.getParameterList().getParametersCount() : 0; PsiParameter[] newParms = new PsiParameter[Math.max(parameterInfos.length - delta, 0)]; final String[] oldParameterNames = changeInfo.getOldParameterNames(); final String[] oldParameterTypes = changeInfo.getOldParameterTypes(); for (int i = 0; i < newParms.length; i++) { JavaParameterInfo info = parameterInfos[i]; int index = info.getOldIndex(); if (index >= 0) { PsiParameter parameter = parameters[index]; newParms[i] = parameter; String oldName = oldParameterNames[index]; if (!oldName.equals(info.getName()) && oldName.equals(parameter.getName())) { PsiIdentifier newIdentifier = factory.createIdentifier(info.getName()); parameter.getNameIdentifier().replace(newIdentifier); } String oldType = oldParameterTypes[index]; if (!oldType.equals(info.getTypeText())) { parameter.normalizeDeclaration(); PsiType newType = substitutor.substitute( info.createType(changeInfo.getMethod().getParameterList(), method.getManager())); parameter.getTypeElement().replace(factory.createTypeElement(newType)); } } else { newParms[i] = createNewParameter(changeInfo, info, substitutor); } } resolveParameterVsFieldsConflicts(newParms, method, list, changeInfo.toRemoveParm()); fixJavadocsForChangedMethod(method, changeInfo, newParms.length); if (changeInfo.isExceptionSetOrOrderChanged()) { final PsiClassType[] newExceptions = getPrimaryChangedExceptionInfo(changeInfo); fixPrimaryThrowsLists(method, newExceptions); } }