Cleanup (typos; formatting)
[idea/community.git] / java / java-impl / src / com / intellij / refactoring / extractMethodObject / reflect / ReflectionAccessorToEverything.java
1 // Copyright 2000-2019 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.psi.*;
5 import com.intellij.refactoring.extractMethodObject.ItemToReplaceDescriptor;
6 import com.intellij.refactoring.util.LambdaRefactoringUtil;
7 import org.jetbrains.annotations.NotNull;
8 import org.jetbrains.annotations.Nullable;
9
10 import java.util.ArrayList;
11 import java.util.List;
12
13 public class ReflectionAccessorToEverything {
14   private final PsiClass myOuterClass;
15   private final PsiElementFactory myElementFactory;
16
17   public ReflectionAccessorToEverything(@NotNull PsiClass generatedInnerClass, @NotNull PsiElementFactory elementFactory) {
18     myOuterClass = generatedInnerClass;
19     myElementFactory = elementFactory;
20   }
21
22   public void grantAccessThroughReflection(@NotNull PsiMethodCallExpression generatedMethodCall) {
23     MyInaccessibleMethodReferencesVisitor methodReferencesVisitor = new MyInaccessibleMethodReferencesVisitor();
24     myOuterClass.accept(methodReferencesVisitor);
25     methodReferencesVisitor.replaceAll();
26
27     MyInaccessibleItemsVisitor inaccessibleItemsVisitor = new MyInaccessibleItemsVisitor();
28     myOuterClass.accept(inaccessibleItemsVisitor);
29
30     inaccessibleItemsVisitor.myReplaceDescriptors
31       .forEach(descriptor -> descriptor.replace(myOuterClass, myElementFactory, generatedMethodCall));
32   }
33
34   private class MyInaccessibleItemsVisitor extends JavaRecursiveElementVisitor {
35     private final List<ItemToReplaceDescriptor> myReplaceDescriptors = new ArrayList<>();
36
37     @Override
38     public void visitParameter(PsiParameter parameter) {
39       super.visitParameter(parameter);
40       addIfNotNull(ParameterDescriptor.createIfInaccessible(parameter));
41     }
42
43     @Override
44     public void visitThisExpression(PsiThisExpression expression) {
45       super.visitThisExpression(expression);
46       addIfNotNull(ThisReferenceDescriptor.createIfInaccessible(expression));
47     }
48
49     @Override
50     public void visitDeclarationStatement(PsiDeclarationStatement statement) {
51       super.visitDeclarationStatement(statement);
52       addIfNotNull(LocalVariableDeclarationDescriptor.createIfInaccessible(statement));
53     }
54
55     @Override
56     public void visitField(PsiField field) {
57       super.visitField(field);
58       addIfNotNull(FieldDeclarationDescriptor.createIfInaccessible(field));
59     }
60
61     @Override
62     public void visitReferenceExpression(PsiReferenceExpression expression) {
63       super.visitReferenceExpression(expression);
64       addIfNotNull(FieldDescriptor.createIfInaccessible(myOuterClass, expression));
65     }
66
67     @Override
68     public void visitNewExpression(PsiNewExpression expression) {
69       super.visitNewExpression(expression);
70       PsiAnonymousClass anonymousClass = expression.getAnonymousClass();
71       // TODO: check if anonymous class is accessible
72       if (anonymousClass != null || expression.getArrayInitializer() != null) return;
73       addIfNotNull(ConstructorDescriptor.createIfInaccessible(expression));
74     }
75
76     @Override
77     public void visitMethodCallExpression(PsiMethodCallExpression expression) {
78       super.visitMethodCallExpression(expression);
79       addIfNotNull(MethodDescriptor.createIfInaccessible(myOuterClass, expression));
80     }
81
82     private void addIfNotNull(@Nullable ItemToReplaceDescriptor descriptor) {
83       if (descriptor != null) {
84         myReplaceDescriptors.add(descriptor);
85       }
86     }
87   }
88
89   private static class MyInaccessibleMethodReferencesVisitor extends JavaRecursiveElementVisitor {
90     private final List<PsiMethodReferenceExpression> myMethodReferencesToReplace = new ArrayList<>();
91
92     @Override
93     public void visitMethodReferenceExpression(PsiMethodReferenceExpression expression) {
94       if (!PsiReflectionAccessUtil.isAccessibleMethodReference(expression)) {
95         myMethodReferencesToReplace.add(expression);
96       }
97     }
98
99     private void replaceAll() {
100       for (PsiMethodReferenceExpression referenceExpression : myMethodReferencesToReplace) {
101         LambdaRefactoringUtil.convertMethodReferenceToLambda(referenceExpression, false, true);
102       }
103     }
104   }
105 }