private void generateAccessors() { // generate accessors myNameToGetter = new HashMap<String, PsiMethod>(); myNameToSetter = new HashMap<String, PsiMethod>(); for (FieldDescriptor fieldDescriptor : myFieldDescriptors) { final DocCommentPolicy<PsiDocComment> commentPolicy = new DocCommentPolicy<PsiDocComment>(myDescriptor.getJavadocPolicy()); PsiField field = fieldDescriptor.getField(); final PsiDocComment docComment = field.getDocComment(); if (myDescriptor.isToEncapsulateGet()) { final PsiMethod prototype = fieldDescriptor.getGetterPrototype(); assert prototype != null; final PsiMethod getter = addOrChangeAccessor(prototype, myNameToGetter); if (docComment != null) { final PsiDocComment getterJavadoc = (PsiDocComment) getter.addBefore(docComment, getter.getFirstChild()); commentPolicy.processNewJavaDoc(getterJavadoc); } } if (myDescriptor.isToEncapsulateSet() && !field.hasModifierProperty(PsiModifier.FINAL)) { PsiMethod prototype = fieldDescriptor.getSetterPrototype(); assert prototype != null; addOrChangeAccessor(prototype, myNameToSetter); } if (docComment != null) { commentPolicy.processOldJavaDoc(docComment); } } }
protected boolean preprocessUsages(Ref<UsageInfo[]> refUsages) { final MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>(); checkExistingMethods(conflicts, true); checkExistingMethods(conflicts, false); final Collection<PsiClass> classes = ClassInheritorsSearch.search(myClass).findAll(); for (FieldDescriptor fieldDescriptor : myFieldDescriptors) { final Set<PsiMethod> setters = new HashSet<PsiMethod>(); final Set<PsiMethod> getters = new HashSet<PsiMethod>(); for (PsiClass aClass : classes) { final PsiMethod getterOverrider = myDescriptor.isToEncapsulateGet() ? aClass.findMethodBySignature(fieldDescriptor.getGetterPrototype(), false) : null; if (getterOverrider != null) { getters.add(getterOverrider); } final PsiMethod setterOverrider = myDescriptor.isToEncapsulateSet() ? aClass.findMethodBySignature(fieldDescriptor.getSetterPrototype(), false) : null; if (setterOverrider != null) { setters.add(setterOverrider); } } if (!getters.isEmpty() || !setters.isEmpty()) { final PsiField field = fieldDescriptor.getField(); for (PsiReference reference : ReferencesSearch.search(field)) { final PsiElement place = reference.getElement(); if (place instanceof PsiReferenceExpression) { final PsiExpression qualifierExpression = ((PsiReferenceExpression) place).getQualifierExpression(); final PsiClass ancestor; if (qualifierExpression == null) { ancestor = PsiTreeUtil.getParentOfType(place, PsiClass.class, false); } else { ancestor = PsiUtil.resolveClassInType(qualifierExpression.getType()); } final boolean isGetter = !PsiUtil.isAccessedForWriting((PsiExpression) place); for (PsiMethod overridden : isGetter ? getters : setters) { if (InheritanceUtil.isInheritorOrSelf(myClass, ancestor, true)) { conflicts.putValue( overridden, "There is already a " + RefactoringUIUtil.getDescription(overridden, true) + " which would hide generated " + (isGetter ? "getter" : "setter") + " for " + place.getText()); break; } } } } } } return showConflicts(conflicts, refUsages.get()); }
@Nullable public EncapsulateFieldUsageInfo createUsage( @NotNull EncapsulateFieldsDescriptor descriptor, @NotNull FieldDescriptor fieldDescriptor, @NotNull PsiReference reference) { if (!(reference instanceof PsiReferenceExpression)) return null; boolean findSet = descriptor.isToEncapsulateSet(); boolean findGet = descriptor.isToEncapsulateGet(); PsiReferenceExpression ref = (PsiReferenceExpression) reference; // [Jeka] to avoid recursion in the field's accessors if (findGet && isUsedInExistingAccessor( descriptor.getTargetClass(), fieldDescriptor.getGetterPrototype(), ref)) return null; if (findSet && isUsedInExistingAccessor( descriptor.getTargetClass(), fieldDescriptor.getSetterPrototype(), ref)) return null; if (!findGet) { if (!PsiUtil.isAccessedForWriting(ref)) return null; } if (!findSet || fieldDescriptor.getField().hasModifierProperty(PsiModifier.FINAL)) { if (!PsiUtil.isAccessedForReading(ref)) return null; } if (!descriptor.isToUseAccessorsWhenAccessible()) { PsiModifierList newModifierList = createNewModifierList(descriptor); PsiClass accessObjectClass = null; PsiExpression qualifier = ref.getQualifierExpression(); if (qualifier != null) { accessObjectClass = (PsiClass) PsiUtil.getAccessObjectClass(qualifier).getElement(); } final PsiResolveHelper helper = JavaPsiFacade.getInstance(((PsiReferenceExpression) reference).getProject()) .getResolveHelper(); if (helper.isAccessible( fieldDescriptor.getField(), newModifierList, ref, accessObjectClass, null)) { return null; } } return new EncapsulateFieldUsageInfo(ref, fieldDescriptor); }
private void checkExistingMethods(MultiMap<PsiElement, String> conflicts, boolean isGetter) { if (isGetter) { if (!myDescriptor.isToEncapsulateGet()) return; } else { if (!myDescriptor.isToEncapsulateSet()) return; } for (FieldDescriptor descriptor : myFieldDescriptors) { PsiMethod prototype = isGetter ? descriptor.getGetterPrototype() : descriptor.getSetterPrototype(); final PsiType prototypeReturnType = prototype.getReturnType(); PsiMethod existing = myClass.findMethodBySignature(prototype, true); if (existing != null) { final PsiType returnType = existing.getReturnType(); if (!RefactoringUtil.equivalentTypes( prototypeReturnType, returnType, myClass.getManager())) { final String descr = PsiFormatUtil.formatMethod( existing, PsiSubstitutor.EMPTY, PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_PARAMETERS | PsiFormatUtilBase.SHOW_TYPE, PsiFormatUtilBase.SHOW_TYPE); String message = isGetter ? RefactoringBundle.message( "encapsulate.fields.getter.exists", CommonRefactoringUtil.htmlEmphasize(descr), CommonRefactoringUtil.htmlEmphasize(prototype.getName())) : RefactoringBundle.message( "encapsulate.fields.setter.exists", CommonRefactoringUtil.htmlEmphasize(descr), CommonRefactoringUtil.htmlEmphasize(prototype.getName())); conflicts.putValue(existing, message); } } else { PsiClass containingClass = myClass.getContainingClass(); while (containingClass != null && existing == null) { existing = containingClass.findMethodBySignature(prototype, true); if (existing != null) { for (PsiReference reference : ReferencesSearch.search(existing)) { final PsiElement place = reference.getElement(); LOG.assertTrue(place instanceof PsiReferenceExpression); final PsiExpression qualifierExpression = ((PsiReferenceExpression) place).getQualifierExpression(); final PsiClass inheritor; if (qualifierExpression == null) { inheritor = PsiTreeUtil.getParentOfType(place, PsiClass.class, false); } else { inheritor = PsiUtil.resolveClassInType(qualifierExpression.getType()); } if (InheritanceUtil.isInheritorOrSelf(inheritor, myClass, true)) { conflicts.putValue( existing, "There is already a " + RefactoringUIUtil.getDescription(existing, true) + " which would be hidden by generated " + (isGetter ? "getter" : "setter")); break; } } } containingClass = containingClass.getContainingClass(); } } } }
public boolean processUsage( @NotNull EncapsulateFieldUsageInfo usage, @NotNull EncapsulateFieldsDescriptor descriptor, PsiMethod setter, PsiMethod getter) { final PsiElement element = usage.getElement(); if (!(element instanceof PsiReferenceExpression)) return false; final FieldDescriptor fieldDescriptor = usage.getFieldDescriptor(); PsiField field = fieldDescriptor.getField(); boolean processGet = descriptor.isToEncapsulateGet(); boolean processSet = descriptor.isToEncapsulateSet() && !field.hasModifierProperty(PsiModifier.FINAL); if (!processGet && !processSet) return true; PsiElementFactory factory = JavaPsiFacade.getInstance(descriptor.getTargetClass().getProject()).getElementFactory(); try { final PsiReferenceExpression expr = (PsiReferenceExpression) element; final PsiElement parent = expr.getParent(); if (parent instanceof PsiAssignmentExpression && expr.equals(((PsiAssignmentExpression) parent).getLExpression())) { PsiAssignmentExpression assignment = (PsiAssignmentExpression) parent; if (assignment.getRExpression() == null) return true; PsiJavaToken opSign = assignment.getOperationSign(); IElementType opType = opSign.getTokenType(); if (opType == JavaTokenType.EQ) { { if (!processSet) return true; final PsiExpression setterArgument = assignment.getRExpression(); PsiMethodCallExpression methodCall = createSetterCall( fieldDescriptor, setterArgument, expr, descriptor.getTargetClass(), setter); if (methodCall != null) { assignment.replace(methodCall); } // TODO: check if value is used!!! } } else if (opType == JavaTokenType.ASTERISKEQ || opType == JavaTokenType.DIVEQ || opType == JavaTokenType.PERCEQ || opType == JavaTokenType.PLUSEQ || opType == JavaTokenType.MINUSEQ || opType == JavaTokenType.LTLTEQ || opType == JavaTokenType.GTGTEQ || opType == JavaTokenType.GTGTGTEQ || opType == JavaTokenType.ANDEQ || opType == JavaTokenType.OREQ || opType == JavaTokenType.XOREQ) { { // Q: side effects of qualifier??! String opName = opSign.getText(); LOG.assertTrue(StringUtil.endsWithChar(opName, '=')); opName = opName.substring(0, opName.length() - 1); PsiExpression getExpr = expr; if (processGet) { final PsiMethodCallExpression getterCall = createGetterCall(fieldDescriptor, expr, descriptor.getTargetClass(), getter); if (getterCall != null) { getExpr = getterCall; } } @NonNls String text = "a" + opName + "b"; PsiBinaryExpression binExpr = (PsiBinaryExpression) factory.createExpressionFromText(text, expr); binExpr.getLOperand().replace(getExpr); binExpr.getROperand().replace(assignment.getRExpression()); PsiExpression setExpr; if (processSet) { setExpr = createSetterCall( fieldDescriptor, binExpr, expr, descriptor.getTargetClass(), setter); } else { text = "a = b"; PsiAssignmentExpression assignment1 = (PsiAssignmentExpression) factory.createExpressionFromText(text, null); assignment1.getLExpression().replace(expr); assignment1.getRExpression().replace(binExpr); setExpr = assignment1; } assignment.replace(setExpr); // TODO: check if value is used!!! } } } else if (RefactoringUtil.isPlusPlusOrMinusMinus(parent)) { IElementType sign; if (parent instanceof PsiPrefixExpression) { sign = ((PsiPrefixExpression) parent).getOperationTokenType(); } else { sign = ((PsiPostfixExpression) parent).getOperationTokenType(); } PsiExpression getExpr = expr; if (processGet) { final PsiMethodCallExpression getterCall = createGetterCall(fieldDescriptor, expr, descriptor.getTargetClass(), getter); if (getterCall != null) { getExpr = getterCall; } } @NonNls String text; if (sign == JavaTokenType.PLUSPLUS) { text = "a+1"; } else { text = "a-1"; } PsiBinaryExpression binExpr = (PsiBinaryExpression) factory.createExpressionFromText(text, null); binExpr.getLOperand().replace(getExpr); PsiExpression setExpr; if (processSet) { setExpr = createSetterCall(fieldDescriptor, binExpr, expr, descriptor.getTargetClass(), setter); } else { text = "a = b"; PsiAssignmentExpression assignment = (PsiAssignmentExpression) factory.createExpressionFromText(text, null); assignment.getLExpression().replace(expr); assignment.getRExpression().replace(binExpr); setExpr = assignment; } parent.replace(setExpr); } else { if (!processGet) return true; PsiMethodCallExpression methodCall = createGetterCall(fieldDescriptor, expr, descriptor.getTargetClass(), getter); if (methodCall != null) { expr.replace(methodCall); } } } catch (IncorrectOperationException e) { LOG.error(e); } return true; }