mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-05-06 05:10:22 +07:00
Inline field/method: check for reflective usages
Fixes EA-126479 - CCE: InlineConstantFieldProcessor.inlineExpressionUsage
This commit is contained in:
@@ -24,6 +24,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.javadoc.PsiDocMethodOrFieldRef;
|
||||
import com.intellij.psi.impl.source.resolve.reference.impl.JavaLangClassMemberReference;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
@@ -42,6 +43,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* @author ven
|
||||
@@ -201,6 +203,10 @@ public class InlineConstantFieldProcessor extends BaseRefactoringProcessor {
|
||||
private void inlineExpressionUsage(PsiExpression expr,
|
||||
PsiExpression initializer1,
|
||||
Set<PsiAssignmentExpression> assignments) throws IncorrectOperationException {
|
||||
if (expr instanceof PsiLiteralExpression) {
|
||||
// Possible reflective usage
|
||||
return;
|
||||
}
|
||||
if (myField.isWritable()) {
|
||||
myField.normalizeDeclaration();
|
||||
}
|
||||
@@ -268,6 +274,10 @@ public class InlineConstantFieldProcessor extends BaseRefactoringProcessor {
|
||||
conflicts.putValue(element, "Inlined field is used in javadoc");
|
||||
}
|
||||
}
|
||||
if (element instanceof PsiLiteralExpression &&
|
||||
Stream.of(element.getReferences()).anyMatch(JavaLangClassMemberReference.class::isInstance)) {
|
||||
conflicts.putValue(element, "Inlined field is used reflectively");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.intellij.psi.codeStyle.VariableKind;
|
||||
import com.intellij.psi.controlFlow.*;
|
||||
import com.intellij.psi.impl.source.codeStyle.CodeEditUtil;
|
||||
import com.intellij.psi.impl.source.javadoc.PsiDocMethodOrFieldRef;
|
||||
import com.intellij.psi.impl.source.resolve.reference.impl.JavaLangClassMemberReference;
|
||||
import com.intellij.psi.infos.MethodCandidateInfo;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.LocalSearchScope;
|
||||
@@ -53,6 +54,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class InlineMethodProcessor extends BaseRefactoringProcessor {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.inline.InlineMethodProcessor");
|
||||
@@ -210,6 +212,10 @@ public class InlineMethodProcessor extends BaseRefactoringProcessor {
|
||||
if (element instanceof PsiDocMethodOrFieldRef && !PsiTreeUtil.isAncestor(myMethod, element, false)) {
|
||||
conflicts.putValue(element, "Inlined method is used in javadoc");
|
||||
}
|
||||
if (element instanceof PsiLiteralExpression &&
|
||||
Stream.of(element.getReferences()).anyMatch(JavaLangClassMemberReference.class::isInstance)) {
|
||||
conflicts.putValue(element, "Inlined method is used reflectively");
|
||||
}
|
||||
if (element instanceof PsiMethodReferenceExpression) {
|
||||
final PsiExpression qualifierExpression = ((PsiMethodReferenceExpression)element).getQualifierExpression();
|
||||
if (qualifierExpression != null) {
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
class Test {
|
||||
private static final int <caret>FIELD = 5;
|
||||
|
||||
/**
|
||||
* Prints the value of {@link Test#FIELD}
|
||||
*/
|
||||
void test() {
|
||||
System.out.println(FIELD);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
class Test {
|
||||
private static final int <caret>FIELD = 5;
|
||||
|
||||
void test() {
|
||||
System.out.println(FIELD);
|
||||
System.out.println(Test.class.getDeclaredField("FIELD"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
class InlineMethodTest {
|
||||
public void f<caret>oo(){}
|
||||
|
||||
void test() throws Exception {
|
||||
System.out.println(InlineMethodTest.class.getDeclaredMethod("foo"));
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@ import com.intellij.codeInsight.TargetElementUtil;
|
||||
import com.intellij.java.refactoring.LightRefactoringTestCase;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.refactoring.BaseRefactoringProcessor;
|
||||
import com.intellij.refactoring.inline.InlineConstantFieldHandler;
|
||||
import com.intellij.refactoring.inline.InlineConstantFieldProcessor;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
@@ -82,6 +83,14 @@ public class InlineConstantFieldTest extends LightRefactoringTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testFieldUsedReflectively() {
|
||||
doTestConflict("Inlined field is used reflectively");
|
||||
}
|
||||
|
||||
public void testFieldUsedInJavadoc() {
|
||||
doTestConflict("Inlined field is used in javadoc");
|
||||
}
|
||||
|
||||
public void testMultipleInitializers() {
|
||||
configureByFile("/refactoring/inlineConstantField/" + getTestName(false) + ".java");
|
||||
PsiElement element = TargetElementUtil
|
||||
@@ -107,4 +116,14 @@ public class InlineConstantFieldTest extends LightRefactoringTestCase {
|
||||
new InlineConstantFieldProcessor(field, getProject(), refExpr, inlineThisOnly || element instanceof PsiCompiledElement).run();
|
||||
checkResultByFile(fileName + ".after");
|
||||
}
|
||||
|
||||
private void doTestConflict(final String conflict) {
|
||||
try {
|
||||
doTest();
|
||||
fail("Conflict was not detected");
|
||||
}
|
||||
catch (BaseRefactoringProcessor.ConflictsInTestsException e) {
|
||||
assertEquals(conflict, e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -231,6 +231,10 @@ public class InlineMethodTest extends LightRefactoringTestCase {
|
||||
doTestConflict("Inlined method is used in javadoc");
|
||||
}
|
||||
|
||||
public void testMethodUsedReflectively() {
|
||||
doTestConflict("Inlined method is used reflectively");
|
||||
}
|
||||
|
||||
public void testNotAStatement() {
|
||||
doTestConflict("Inlined result would contain parse errors");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user