[duplicates] enable duplicates analysis in PyCharm/WebStorm/PhpStorm/RubyMine
[idea/community.git] / java / java-impl / src / com / intellij / refactoring / extractMethodObject / reflect / ReflectionAccessorBase.java
1 // Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 package com.intellij.refactoring.extractMethodObject.reflect;
3
4 import com.intellij.openapi.diagnostic.Logger;
5 import com.intellij.psi.PsiClass;
6 import com.intellij.psi.PsiElement;
7 import com.intellij.psi.PsiElementFactory;
8 import com.intellij.refactoring.extractMethodObject.ItemToReplaceDescriptor;
9 import org.jetbrains.annotations.NotNull;
10
11 import java.util.List;
12
13 /**
14  * Grants access for inaccessible members using reflection. Adds an additional method per each expression
15  * with inaccessible members (method calls, field references, constructor calls, etc)
16  *
17  * @author Vitaliy.Bibaev
18  */
19 public abstract class ReflectionAccessorBase<T extends ItemToReplaceDescriptor> implements ReflectionAccessor {
20   private final PsiClass myPsiClass;
21   private final PsiElementFactory myElementFactory;
22   private final Logger log = Logger.getInstance(getClass());
23
24   protected ReflectionAccessorBase(@NotNull PsiClass psiClass, @NotNull PsiElementFactory elementFactory) {
25     myPsiClass = psiClass;
26     myElementFactory = elementFactory;
27   }
28
29   @Override
30   public void accessThroughReflection(@NotNull PsiElement element) {
31     List<T> toReplace = findItemsToReplace(element);
32     if (!toReplace.isEmpty()) {
33       log.info("Found " + toReplace.size() + " items to replace");
34     }
35
36     for (T item : toReplace) {
37       grantAccess(item);
38     }
39
40     List<T> remaining = findItemsToReplace(element);
41     if (!remaining.isEmpty()) {
42       log.warn("Some inaccessible items were not replaced");
43     }
44   }
45
46   @NotNull
47   protected PsiElementFactory getElementFactory() {
48     return myElementFactory;
49   }
50
51   @NotNull
52   protected PsiClass getOuterClass() {
53     return myPsiClass;
54   }
55
56   /**
57    * Implementers of this method must place all child elements before their parent to ensure that all elements are not replaced
58    * together a previous element
59    */
60   protected abstract List<T> findItemsToReplace(@NotNull PsiElement element);
61
62   protected abstract void grantAccess(@NotNull T descriptor);
63 }