IDEA-169518 Convert "Move assignment to field declaration" to the inspection

This commit is contained in:
Tagir Valeev
2017-03-20 16:23:16 +07:00
parent c90b64b7e8
commit efdfa0a22c
23 changed files with 436 additions and 265 deletions

View File

@@ -1,201 +0,0 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.intention.impl;
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.codeInsight.PsiEquivalenceUtil;
import com.intellij.codeInsight.highlighting.HighlightManager;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* @author cdr
*/
public class MoveFieldAssignmentToInitializerAction extends BaseIntentionAction {
@Override
@NotNull
public String getFamilyName() {
return getText();
}
@Override
@NotNull
public String getText() {
return CodeInsightBundle.message("intention.move.field.assignment.to.declaration");
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
PsiAssignmentExpression assignment = getAssignmentUnderCaret(editor, file);
if (assignment == null) return false;
PsiElement parent = assignment.getParent();
if (!(parent instanceof PsiExpressionStatement)) return false;
PsiField field = getAssignedField(assignment);
if (field == null || field.hasInitializer()) return false;
PsiClass psiClass = field.getContainingClass();
if (psiClass == null || psiClass.isInterface()) return false;
if (psiClass.getContainingFile() != file) return false;
PsiModifierListOwner ctrOrInitializer = enclosingMethodOrClassInitializer(assignment, field);
if (ctrOrInitializer == null) return false;
if (ctrOrInitializer.hasModifierProperty(PsiModifier.STATIC) != field.hasModifierProperty(PsiModifier.STATIC)) return false;
if (!isValidAsFieldInitializer(assignment.getRExpression(), ctrOrInitializer)) return false;
if (!isInitializedWithSameExpression(field, assignment, new ArrayList<>())) return false;
return true;
}
private static boolean isValidAsFieldInitializer(final PsiExpression initializer, final PsiModifierListOwner ctrOrInitializer) {
if (initializer == null) return false;
final Ref<Boolean> result = new Ref<>(Boolean.TRUE);
initializer.accept(new JavaRecursiveElementWalkingVisitor() {
@Override
public void visitReferenceExpression(PsiReferenceExpression expression) {
PsiElement resolved = expression.resolve();
if (resolved == null) return;
if (PsiTreeUtil.isAncestor(ctrOrInitializer, resolved, false) && !PsiTreeUtil.isAncestor(initializer, resolved, false)) {
// resolved somewhere inside constructor but outside initializer
result.set(Boolean.FALSE);
}
}
});
return result.get().booleanValue();
}
private static PsiModifierListOwner enclosingMethodOrClassInitializer(final PsiAssignmentExpression assignment, final PsiField field) {
PsiElement parentOwner = assignment;
while (true) {
parentOwner = PsiTreeUtil.getParentOfType(parentOwner, PsiModifierListOwner.class, true, PsiMember.class);
if (parentOwner == null) return null;
PsiElement parent = parentOwner.getParent();
if (parent == field.getContainingClass()) return (PsiModifierListOwner)parentOwner;
}
}
private static boolean isInitializedWithSameExpression(final PsiField field,
final PsiAssignmentExpression assignment,
final Collection<PsiAssignmentExpression> initializingAssignments) {
final PsiExpression expression = assignment.getRExpression();
if (expression == null) return false;
PsiClass containingClass = field.getContainingClass();
if (containingClass == null) return false;
final Ref<Boolean> result = new Ref<>(Boolean.TRUE);
final List<PsiAssignmentExpression> totalUsages = new ArrayList<>();
containingClass.accept(new JavaRecursiveElementVisitor() {
private PsiCodeBlock currentInitializingBlock; //ctr or class initializer
@Override
public void visitCodeBlock(PsiCodeBlock block) {
PsiElement parent = block.getParent();
if (parent instanceof PsiClassInitializer || parent instanceof PsiMethod && ((PsiMethod)parent).isConstructor()) {
currentInitializingBlock = block;
super.visitCodeBlock(block);
currentInitializingBlock = null;
}
else {
super.visitCodeBlock(block);
}
}
@Override
public void visitReferenceExpression(PsiReferenceExpression reference) {
if (!result.get().booleanValue()) return;
super.visitReferenceExpression(reference);
if (!PsiUtil.isOnAssignmentLeftHand(reference)) return;
PsiElement resolved = reference.resolve();
if (resolved != field) return;
PsiAssignmentExpression assignmentExpression = PsiTreeUtil.getParentOfType(reference, PsiAssignmentExpression.class);
PsiExpression rValue = assignmentExpression.getRExpression();
if (currentInitializingBlock != null) {
// ignore usages other than initializing
if (rValue == null || !PsiEquivalenceUtil.areElementsEquivalent(rValue, expression)) {
result.set(Boolean.FALSE);
}
initializingAssignments.add(assignmentExpression);
}
totalUsages.add(assignment);
}
});
// the only assignment is OK
if (totalUsages.size() == 1 && initializingAssignments.isEmpty()) {
initializingAssignments.addAll(totalUsages);
return true;
}
return result.get().booleanValue();
}
private static PsiField getAssignedField(final PsiAssignmentExpression assignment) {
PsiExpression lExpression = PsiUtil.skipParenthesizedExprDown(assignment.getLExpression());
if (!(lExpression instanceof PsiReferenceExpression)) return null;
PsiElement resolved = ((PsiReferenceExpression)lExpression).resolve();
if (!(resolved instanceof PsiField)) return null;
return (PsiField)resolved;
}
private static PsiAssignmentExpression getAssignmentUnderCaret(final Editor editor, final PsiFile file) {
int offset = editor.getCaretModel().getOffset();
PsiElement element = file.findElementAt(offset);
if (element == null || element instanceof PsiCompiledElement) return null;
return PsiTreeUtil.getParentOfType(element, PsiAssignmentExpression.class, false, PsiMember.class);
}
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
PsiAssignmentExpression assignment = getAssignmentUnderCaret(editor, file);
if (assignment == null) return;
PsiField field = getAssignedField(assignment);
if (field == null) return;
List<PsiAssignmentExpression> assignments = new ArrayList<>();
if (!isInitializedWithSameExpression(field, assignment, assignments)) return;
PsiExpression initializer = assignment.getRExpression();
field.setInitializer(initializer);
for (PsiAssignmentExpression assignmentExpression : assignments) {
PsiElement statement = assignmentExpression.getParent();
PsiElement parent = statement.getParent();
if (parent instanceof PsiIfStatement ||
parent instanceof PsiWhileStatement ||
parent instanceof PsiForStatement ||
parent instanceof PsiForeachStatement) {
PsiStatement emptyStatement =
JavaPsiFacade.getInstance(file.getProject()).getElementFactory().createStatementFromText(";", statement);
statement.replace(emptyStatement);
}
else {
statement.delete();
}
}
TextAttributes attributes = EditorColorsManager.getInstance().getGlobalScheme().getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES);
HighlightManager.getInstance(project).addOccurrenceHighlights(editor, new PsiElement[]{field.getInitializer()}, attributes, false, null);
}
}

View File

@@ -0,0 +1,267 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInspection;
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.codeInsight.ExceptionUtil;
import com.intellij.codeInsight.PsiEquivalenceUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.ObjectUtils;
import com.siyeh.ig.psiutils.CommentTracker;
import com.siyeh.ig.psiutils.ConstructionUtils;
import com.siyeh.ig.psiutils.ExpressionUtils;
import one.util.streamex.StreamEx;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
/**
* @author cdr
* @author Tagir Valeev
*/
public class MoveFieldAssignmentToInitializerInspection extends BaseJavaBatchLocalInspectionTool {
@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
return new JavaElementVisitor() {
@Override
public void visitAssignmentExpression(PsiAssignmentExpression assignment) {
PsiElement parent = assignment.getParent();
if (!(parent instanceof PsiExpressionStatement)) return;
PsiField field = getAssignedField(assignment);
if (field == null || field.hasInitializer()) return;
PsiClass psiClass = field.getContainingClass();
if (psiClass == null || psiClass.isInterface()) return;
if (psiClass.getContainingFile() != holder.getFile()) return;
PsiModifierListOwner ctrOrInitializer = enclosingMethodOrClassInitializer(assignment, field);
if (ctrOrInitializer == null) return;
if (ctrOrInitializer.hasModifierProperty(PsiModifier.STATIC) != field.hasModifierProperty(PsiModifier.STATIC)) return;
if (!isValidAsFieldInitializer(assignment.getRExpression(), ctrOrInitializer, field)) return;
if (!isInitializedWithSameExpression(field, assignment, new ArrayList<>())) return;
boolean shouldWarn = shouldWarn(ctrOrInitializer, field, assignment);
if (shouldWarn) {
PsiExpression lValue = assignment.getLExpression();
TextRange range = new TextRange(0, lValue.getTextLength()).shiftRight(lValue.getStartOffsetInParent());
holder.registerProblem(assignment, CodeInsightBundle.message("intention.move.field.assignment.to.declaration"),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, range, new MoveFieldAssignmentToInitializerFix());
} else {
if(!isOnTheFly) return;
holder.registerProblem(assignment, CodeInsightBundle.message("intention.move.field.assignment.to.declaration"),
ProblemHighlightType.INFORMATION, new MoveFieldAssignmentToInitializerFix());
}
}
};
}
boolean shouldWarn(PsiModifierListOwner ctrOrInitializer, PsiField field, PsiAssignmentExpression assignment) {
if (!(ctrOrInitializer instanceof PsiClassInitializer)) return false;
PsiExpressionStatement statement = ObjectUtils.tryCast(assignment.getParent(), PsiExpressionStatement.class);
if (statement == null) return false;
PsiCodeBlock codeBlock = ObjectUtils.tryCast(statement.getParent(), PsiCodeBlock.class);
if (codeBlock == null) return false;
if (codeBlock.getParent() != ctrOrInitializer) return false;
if (!ReferencesSearch.search(field, new LocalSearchScope(ctrOrInitializer)).forEach(ref -> {
return PsiTreeUtil.isAncestor(assignment, ref.getElement(), true);
})) {
return false;
}
// If it's not the first statement in the initializer, allow some more (likely unrelated) assignments only
if (StreamEx.of(codeBlock.getStatements()).takeWhile(st -> statement != st).allMatch(st -> ExpressionUtils.getAssignment(st) != null)) {
return true;
}
// Or allow simple initializers
PsiExpression value = assignment.getRExpression();
return ExpressionUtils.isSimpleExpression(value) || ConstructionUtils.isEmptyCollectionInitializer(value);
}
private static boolean isValidAsFieldInitializer(final PsiExpression initializer,
final PsiModifierListOwner ctrOrInitializer,
PsiField field) {
if (initializer == null) return false;
if (!ExceptionUtil.getThrownCheckedExceptions(initializer).isEmpty()) return false;
final Ref<Boolean> result = new Ref<>(Boolean.TRUE);
initializer.accept(new JavaRecursiveElementWalkingVisitor() {
@Override
public void visitReferenceExpression(PsiReferenceExpression expression) {
super.visitReferenceExpression(expression);
PsiElement resolved = expression.resolve();
if (resolved == null) return;
if (PsiTreeUtil.isAncestor(ctrOrInitializer, resolved, false) && !PsiTreeUtil.isAncestor(initializer, resolved, false)) {
// resolved somewhere inside constructor but outside initializer
result.set(Boolean.FALSE);
}
if (resolved instanceof PsiMember &&
resolved != field &&
((PsiMember)resolved).getContainingClass() == field.getContainingClass()) {
if (field.hasModifierProperty(PsiModifier.STATIC) ||
!((PsiMember)resolved).hasModifierProperty(PsiModifier.STATIC)) {
// refers to another field/method of the same class (except referring from non-static member to static)
result.set(Boolean.FALSE);
}
}
}
});
return result.get().booleanValue();
}
static PsiModifierListOwner enclosingMethodOrClassInitializer(final PsiAssignmentExpression assignment, final PsiField field) {
PsiElement parentOwner = assignment;
while (true) {
parentOwner = PsiTreeUtil.getParentOfType(parentOwner, PsiModifierListOwner.class, true, PsiMember.class);
if (parentOwner == null) return null;
PsiElement parent = parentOwner.getParent();
if (parent == field.getContainingClass()) return (PsiModifierListOwner)parentOwner;
}
}
private static boolean isInitializedWithSameExpression(final PsiField field,
final PsiAssignmentExpression assignment,
final Collection<PsiAssignmentExpression> initializingAssignments) {
final PsiExpression expression = assignment.getRExpression();
if (expression == null) return false;
PsiClass containingClass = field.getContainingClass();
if (containingClass == null) return false;
final Ref<Boolean> result = new Ref<>(Boolean.TRUE);
final List<PsiAssignmentExpression> totalUsages = new ArrayList<>();
containingClass.accept(new JavaRecursiveElementVisitor() {
private PsiCodeBlock currentInitializingBlock; //ctr or class initializer
@Override
public void visitCodeBlock(PsiCodeBlock block) {
PsiElement parent = block.getParent();
if (parent instanceof PsiClassInitializer || parent instanceof PsiMethod && ((PsiMethod)parent).isConstructor()) {
currentInitializingBlock = block;
super.visitCodeBlock(block);
currentInitializingBlock = null;
}
else {
super.visitCodeBlock(block);
}
}
@Override
public void visitReferenceExpression(PsiReferenceExpression reference) {
if (!result.get().booleanValue()) return;
super.visitReferenceExpression(reference);
if (!PsiUtil.isOnAssignmentLeftHand(reference)) return;
PsiElement resolved = reference.resolve();
if (resolved != field) return;
PsiAssignmentExpression assignmentExpression = PsiTreeUtil.getParentOfType(reference, PsiAssignmentExpression.class);
if (assignmentExpression == null) return;
PsiExpression rValue = assignmentExpression.getRExpression();
if (currentInitializingBlock != null) {
// ignore usages other than initializing
if (rValue == null || !PsiEquivalenceUtil.areElementsEquivalent(rValue, expression)) {
result.set(Boolean.FALSE);
}
initializingAssignments.add(assignmentExpression);
}
totalUsages.add(assignment);
}
});
// the only assignment is OK
if (totalUsages.size() == 1 && initializingAssignments.isEmpty()) {
initializingAssignments.addAll(totalUsages);
return true;
}
return result.get().booleanValue();
}
private static PsiField getAssignedField(final PsiAssignmentExpression assignment) {
PsiExpression lExpression = PsiUtil.skipParenthesizedExprDown(assignment.getLExpression());
if (!(lExpression instanceof PsiReferenceExpression)) return null;
PsiElement resolved = ((PsiReferenceExpression)lExpression).resolve();
if (!(resolved instanceof PsiField)) return null;
return (PsiField)resolved;
}
private static class MoveFieldAssignmentToInitializerFix implements LocalQuickFix {
@Nls
@NotNull
@Override
public String getFamilyName() {
return CodeInsightBundle.message("intention.move.field.assignment.to.declaration");
}
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
PsiAssignmentExpression assignment = ObjectUtils.tryCast(descriptor.getStartElement(), PsiAssignmentExpression.class);
if (assignment == null) return;
PsiField field = getAssignedField(assignment);
if (field == null) return;
List<PsiAssignmentExpression> assignments = new ArrayList<>();
if (!isInitializedWithSameExpression(field, assignment, assignments)) return;
PsiElement prev = PsiTreeUtil.skipSiblingsBackward(assignment.getParent(), PsiComment.class, PsiWhiteSpace.class);
String comments = prev == null ? null : CommentTracker.commentsBetween(prev, assignment);
PsiExpression initializer = assignment.getRExpression();
field.setInitializer(initializer);
PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory();
if (comments != null) {
PsiCodeBlock block = factory.createCodeBlockFromText("{" + comments + "}", initializer);
for(PsiElement child : block.getChildren()) {
if(child instanceof PsiComment || child instanceof PsiWhiteSpace) {
field.getParent().addBefore(child, field);
}
}
}
PsiModifierListOwner owner = enclosingMethodOrClassInitializer(assignment, field);
for (PsiAssignmentExpression assignmentExpression : assignments) {
PsiElement statement = assignmentExpression.getParent();
PsiElement parent = statement.getParent();
if (parent instanceof PsiIfStatement ||
parent instanceof PsiWhileStatement ||
parent instanceof PsiForStatement ||
parent instanceof PsiForeachStatement) {
PsiStatement emptyStatement = factory.createStatementFromText(";", statement);
statement.replace(emptyStatement);
}
else {
statement.delete();
}
}
// Delete empty initializer left after fix
if (owner instanceof PsiClassInitializer) {
PsiCodeBlock body = ((PsiClassInitializer)owner).getBody();
if(body.getStatements().length == 0 && Arrays.stream(body.getChildren()).noneMatch(PsiComment.class::isInstance)) {
owner.delete();
}
}
}
}
}

View File

@@ -1,4 +1,4 @@
// "Move assignment to field declaration" "true"
// "Move assignment to field declaration" "INFORMATION"
class X {
int f = 0;

View File

@@ -1,10 +1,12 @@
// "Move assignment to field declaration" "true"
// "Move assignment to field declaration" "GENERIC_ERROR_OR_WARNING"
class X {
static int f = 0;
static {
<caret>}
X(int i) {
/*
Set to zero
*/
static int f = 0;
X(int i) {
}
void x() {
int i = f;

View File

@@ -1,15 +1,16 @@
// "Move assignment to field declaration" "true"
class X {
Object f = new Runnable() {
void x(int p) {
int f = p;
}
// Create default runnable
Object f = new Runnable() {
void x(int p) {
int f = p;
}
public void run() {
public void run() {
}
};
}
};
X() {
<caret>//
}

View File

@@ -0,0 +1,23 @@
// "Move assignment to field declaration" "INFORMATION"
public class Test {
static LoggingSystem LOG = LoggingSystem.getLogger();
static {
LoggingSystem.init();
}
}
class LoggingSystem {
private static LoggingSystem L;
static LoggingSystem getLogger() {
return L;
}
static void init() {
if(L == null) {
L = new LoggingSystem();
}
}
}

View File

@@ -1,6 +1,4 @@
// "Move assignment to field declaration" "true"
public class X {
int i = 0;
{
}
}

View File

@@ -0,0 +1,12 @@
// "Move assignment to field declaration" "INFORMATION"
public class Test {
String myField = getValue();
private String value;
void f() {
}
public static String getValue() {
return value;
}
}

View File

@@ -1,4 +1,4 @@
// "Move assignment to field declaration" "true"
// "Move assignment to field declaration" "INFORMATION"
class X {
int f;

View File

@@ -1,9 +1,12 @@
// "Move assignment to field declaration" "true"
// "Move assignment to field declaration" "GENERIC_ERROR_OR_WARNING"
class X {
static int f;
static {
f = <caret>0;
/*
Set to zero
*/
<caret>f = 0;
}
X(int i) {
}

View File

@@ -3,6 +3,7 @@
class X {
Object f;
X() {
// Create default runnable
<caret>f = new Runnable() {
void x(int p) {
int f = p;

View File

@@ -0,0 +1,24 @@
// "Move assignment to field declaration" "INFORMATION"
public class Test {
static LoggingSystem LOG;
static {
LoggingSystem.init();
<caret>LOG = LoggingSystem.getLogger();
}
}
class LoggingSystem {
private static LoggingSystem L;
static LoggingSystem getLogger() {
return L;
}
static void init() {
if(L == null) {
L = new LoggingSystem();
}
}
}

View File

@@ -0,0 +1,13 @@
// "Move assignment to field declaration" "false"
public class Test {
String myField;
private String value;
void f() {
<caret>myField = getValue();
}
public String getValue() {
return value;
}
}

View File

@@ -2,6 +2,6 @@
public class X {
int i;
{
(i)=<caret>0;
(<caret>i)=0;
}
}

View File

@@ -0,0 +1,8 @@
// "Move assignment to field declaration" "false"
public class Test {
final static String FIELD;
static {
String data = " foo ";
<caret>FIELD = data.trim();
}
}

View File

@@ -0,0 +1,13 @@
// "Move assignment to field declaration" "INFORMATION"
public class Test {
String myField;
private String value;
void f() {
<caret>myField = getValue();
}
public static String getValue() {
return value;
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.daemon.quickFix;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.MoveFieldAssignmentToInitializerInspection;
import org.jetbrains.annotations.NotNull;
/**
* @author Tagir Valeev
*/
public class MoveFieldAssignmentToInitializerInspectionTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@NotNull
@Override
protected LocalInspectionTool[] configureLocalInspectionTools() {
return new LocalInspectionTool[]{new MoveFieldAssignmentToInitializerInspection()};
}
@Override
protected String getBasePath() {
return "/codeInsight/daemonCodeAnalyzer/quickFix/moveFieldAssignmentToInitializer";
}
}

View File

@@ -1,15 +0,0 @@
package com.intellij.codeInsight.intention;
import com.intellij.codeInsight.daemon.LightIntentionActionTestCase;
/**
* @author ven
*/
public class MoveFieldAssignmentToInitializerActionTest extends LightIntentionActionTestCase {
public void test() throws Exception { doAllTests(); }
@Override
protected String getBasePath() {
return "/codeInsight/daemonCodeAnalyzer/quickFix/moveFieldAssignmentToInitializer";
}
}

View File

@@ -0,0 +1,10 @@
<html>
<body>
<p>This intention replaces initialization of field via assignment with field initializer.</p>
<p>The code is highlighted only if field initializer is located in the initializer
and joining with the field declaration is likely to be safe.</p>
<p>In other cases the inspection works like intention action as it may change the code semantics.</p>
<!-- tooltip end -->
<small>Since 2017.2</small>
</body>
</html>

View File

@@ -1,9 +0,0 @@
public class X {
int field = 0;
public X() {
}
void reset() {
field = -1;
}
}

View File

@@ -1,9 +0,0 @@
public class X {
int field;
public X() {
<spot>field = 0;</spot>
}
void reset() {
field = -1;
}
}

View File

@@ -1,8 +0,0 @@
<html>
<body>
This intention replaces intialization of field via assignment with field initializer.
<p>
Please note that this intention may change program semantics.
</body>
</html>

View File

@@ -920,6 +920,10 @@
groupPath="Java" groupBundle="messages.InspectionsBundle" groupKey="group.names.reflective.access.issues"
bundle="messages.InspectionsBundle" key="inspection.handle.signature.name"
implementationClass="com.intellij.codeInspection.reflectiveAccess.JavaLangInvokeHandleSignatureInspection"/>
<localInspection language="JAVA" shortName="MoveFieldAssignmentToInitializer" enabledByDefault="true" level="WARNING"
groupPath="Java" groupBundle="messages.InspectionsBundle" groupKey="group.names.code.style.issues"
displayName="Move field assignment to initializer"
implementationClass="com.intellij.codeInspection.MoveFieldAssignmentToInitializerInspection"/>
<intentionAction>
<className>com.intellij.codeInsight.intention.impl.SplitIfAction</className>
@@ -1068,10 +1072,6 @@
<className>com.intellij.testIntegration.intention.MoveInitializerToSetUpMethodAction</className>
<category>Java/Declaration</category>
</intentionAction>
<intentionAction>
<className>com.intellij.codeInsight.intention.impl.MoveFieldAssignmentToInitializerAction</className>
<category>Java/Declaration</category>
</intentionAction>
<intentionAction>
<className>com.intellij.codeInsight.daemon.impl.quickfix.AddRuntimeExceptionToThrowsAction</className>
<category>Java/Declaration</category>