IDEA-242718: dont pass static fields as parameters

GitOrigin-RevId: 2b00ccc0466cc643ca6bd9c40fcc974b82d2fed8
This commit is contained in:
Alexandr Suhinin
2020-06-30 11:38:36 +00:00
committed by intellij-monorepo-bot
parent be377e3ede
commit 0ea2cc86c8
6 changed files with 31 additions and 9 deletions
@@ -117,7 +117,7 @@ class CodeFragmentAnalyzer(val elements: List<PsiElement>) {
return declaredVariables.intersect(externallyWrittenVariables).toList()
}
fun findFieldUsages(targetClass: PsiClass, elements: List<PsiElement>): List<FieldUsage> {
fun findLocalFieldUsages(targetClass: PsiClass, elements: List<PsiElement>): List<FieldUsage> {
val usedFields = ArrayList<FieldUsage>()
val visitor = object : ClassMemberReferencesVisitor(targetClass) {
override fun visitClassMemberReferenceElement(classMember: PsiMember, classMemberReference: PsiJavaCodeReferenceElement) {
@@ -128,7 +128,7 @@ class CodeFragmentAnalyzer(val elements: List<PsiElement>) {
}
}
elements.forEach { it.accept(visitor) }
return usedFields.distinct()
return usedFields.distinct().filterNot { usage -> usage.field.modifierList?.hasExplicitModifier(PsiModifier.STATIC) == true }
}
private fun lastGotoPointFrom(instructionOffset: Int): Int {
@@ -90,8 +90,8 @@ fun findExtractOptions(elements: List<PsiElement>): ExtractOptions {
val targetClass = PsiTreeUtil.getParentOfType(ExtractMethodHelper.getValidParentOf(elements.first()), PsiClass::class.java)!!
val fieldUsages = analyzer.findFieldUsages(targetClass, elements)
val finalFieldsWrites = fieldUsages.filter { it.isWrite && it.field.hasExplicitModifier(PsiModifier.FINAL) }
val fieldUsages = analyzer.findLocalFieldUsages(targetClass, elements)
val finalFieldsWrites = fieldUsages.filter { fieldsUsage -> fieldsUsage.isWrite && fieldsUsage.field.hasExplicitModifier(PsiModifier.FINAL) }
val finalFields = finalFieldsWrites.map { it.field }.distinct()
val field = finalFields.singleOrNull()
extractOptions = when {
@@ -13,7 +13,6 @@ import com.intellij.psi.*
import com.intellij.psi.search.PsiElementProcessor
import com.intellij.psi.util.PsiTreeUtil
import com.intellij.psi.util.PsiUtil
import com.intellij.refactoring.extractMethod.PrepareFailedException
import com.intellij.refactoring.extractMethod.newImpl.ExtractMethodHelper.findUsedTypeParameters
import com.intellij.refactoring.extractMethod.newImpl.ExtractMethodHelper.hasExplicitModifier
import com.intellij.refactoring.extractMethod.newImpl.ExtractMethodHelper.inputParameterOf
@@ -211,7 +210,7 @@ object ExtractMethodPipeline {
fun withForcedStatic(analyzer: CodeFragmentAnalyzer, extractOptions: ExtractOptions): ExtractOptions? {
val targetClass = PsiTreeUtil.getParentOfType(ExtractMethodHelper.getValidParentOf(extractOptions.elements.first()), PsiClass::class.java)!!
val fieldUsages = analyzer.findFieldUsages(targetClass, extractOptions.elements)
val fieldUsages = analyzer.findLocalFieldUsages(targetClass, extractOptions.elements)
if (fieldUsages.any { it.isWrite }) return null
val fieldInputParameters =
fieldUsages.groupBy { it.field }.entries.map { (field, fieldUsages) ->
@@ -232,9 +231,8 @@ object ExtractMethodPipeline {
val firstStatement = method.body?.statements?.firstOrNull() ?: return false
val startsOnBegin = firstStatement.textRange in TextRange(elements.first().textRange.startOffset, elements.last().textRange.endOffset)
val outStatements = method.body?.statements.orEmpty().dropWhile { it.textRange.endOffset <= elements.last().textRange.endOffset }
val hasOuterFinalFieldAssignments = analyzer
.findFieldUsages(holderClass, outStatements)
.any { it.isWrite && it.field.hasExplicitModifier(PsiModifier.FINAL) }
val hasOuterFinalFieldAssignments = analyzer.findLocalFieldUsages(holderClass, outStatements)
.any { fieldUsage -> fieldUsage.isWrite && fieldUsage.field.hasExplicitModifier(PsiModifier.FINAL) }
return method.isConstructor && startsOnBegin && !hasOuterFinalFieldAssignments && analyzer.findOutputVariables().isEmpty()
}
@@ -0,0 +1,8 @@
class Test {
int local = 42;
static int global = 42;
void test(){
<selection>System.out.println(local + global);</selection>
}
}
@@ -0,0 +1,12 @@
class Test {
int local = 42;
static int global = 42;
void test(){
newMethod(local);
}
private static void newMethod(int local) {
System.out.println(local + global);
}
}
@@ -253,6 +253,10 @@ public class ExtractMethodNewTest extends LightJavaCodeInsightTestCase {
doTest();
}
public void testNotPassedStaticField() throws Exception {
doTestPassFieldsAsParams();
}
public void testExtractAssignmentExpression() throws Exception {
try {
doTest();