IDEA-118279 create constructor params: apply cleanup

This commit is contained in:
Anna Kozlova
2014-05-29 15:20:49 +04:00
parent 11d1e29e36
commit d67e9b4f4b
9 changed files with 129 additions and 80 deletions

View File

@@ -25,6 +25,7 @@ import com.intellij.codeInsight.generation.PsiMethodMember;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.impl.AssignFieldFromParameterAction;
import com.intellij.codeInsight.intention.impl.FieldFromParameterUtils;
import com.intellij.codeInspection.ex.GlobalInspectionContextBase;
import com.intellij.ide.util.MemberChooser;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Editor;
@@ -123,6 +124,7 @@ public class CreateConstructorParameterFromFieldFix implements IntentionAction {
}
}
});
final List<PsiElement> cleanupElements = new ArrayList<PsiElement>();
final ArrayList<PsiMethod> constrs = filterConstructorsIfFieldAlreadyAssigned(constructors, getField());
if (constrs.size() > 1) {
final PsiMethodMember[] members = new PsiMethodMember[constrs.size()];
@@ -142,7 +144,7 @@ public class CreateConstructorParameterFromFieldFix implements IntentionAction {
}
for (PsiMethodMember member : elements) {
if (!addParameterToConstructor(project, file, editor, member.getElement(), new PsiField[] {getField()})) break;
if (!addParameterToConstructor(project, file, editor, member.getElement(), new PsiField[] {getField()}, cleanupElements)) break;
}
} else if (!constrs.isEmpty()) {
@@ -177,12 +179,13 @@ public class CreateConstructorParameterFromFieldFix implements IntentionAction {
addParameterToConstructor(project, file, editor, constructor, constrs.size() == constructors.length
? fields.toArray(new PsiField[fields.size()])
: new PsiField[]{getField()});
: new PsiField[]{getField()}, cleanupElements);
}
finally {
fieldsToFix.clear();
}
}
GlobalInspectionContextBase.cleanupElements(project, null, cleanupElements.toArray(new PsiElement[cleanupElements.size()]));
}
@NotNull
@@ -231,7 +234,7 @@ public class CreateConstructorParameterFromFieldFix implements IntentionAction {
final PsiFile file,
final Editor editor,
final PsiMethod constructor,
final PsiField[] fields) throws IncorrectOperationException {
final PsiField[] fields, final List<PsiElement> cleanupElements) throws IncorrectOperationException {
final PsiParameterList parameterList = constructor.getParameterList();
final PsiParameter[] parameters = parameterList.getParameters();
ParameterInfoImpl[] newParamInfos = new ParameterInfoImpl[parameters.length + fields.length];
@@ -267,7 +270,7 @@ public class CreateConstructorParameterFromFieldFix implements IntentionAction {
return ApplicationManager.getApplication().runWriteAction(new Computable<Boolean>() {
@Override
public Boolean compute() {
return doCreate(project, editor, parameters, constructorPointer, resultParams, usedFields);
return doCreate(project, editor, parameters, constructorPointer, resultParams, usedFields, cleanupElements);
}
});
}
@@ -309,7 +312,7 @@ public class CreateConstructorParameterFromFieldFix implements IntentionAction {
}
private static boolean doCreate(Project project, Editor editor, PsiParameter[] parameters, SmartPsiElementPointer constructorPointer,
ParameterInfoImpl[] parameterInfos, HashMap<PsiField, String> fields) {
ParameterInfoImpl[] parameterInfos, HashMap<PsiField, String> fields, List<PsiElement> cleanupElements) {
PsiMethod constructor = (PsiMethod)constructorPointer.getElement();
assert constructor != null;
PsiParameter[] newParameters = constructor.getParameterList().getParameters();
@@ -324,7 +327,11 @@ public class CreateConstructorParameterFromFieldFix implements IntentionAction {
continue;
}
notNull(project, field, parameter);
AssignFieldFromParameterAction.addFieldAssignmentStatement(project, field, parameter, editor);
cleanupElements.add(parameter);
final PsiElement assignmentStatement = AssignFieldFromParameterAction.addFieldAssignmentStatement(project, field, parameter, editor);
if (assignmentStatement != null) {
cleanupElements.add(assignmentStatement);
}
created = true;
}
}

View File

@@ -136,8 +136,7 @@ public abstract class GenerateMembersHandlerBase implements CodeInsightActionHan
}
}
AnalysisScope scope = new AnalysisScope(new LocalSearchScope(elements.toArray(new PsiElement[elements.size()])), project);
GlobalInspectionContextBase.codeCleanup(project, scope, null);
GlobalInspectionContextBase.cleanupElements(project, null, elements.toArray(new PsiElement[elements.size()]));
}
final ArrayList<TemplateGenerationInfo> templates = new ArrayList<TemplateGenerationInfo>();

View File

@@ -99,19 +99,19 @@ public class AssignFieldFromParameterAction extends BaseIntentionAction {
return field;
}
public static void addFieldAssignmentStatement(@NotNull Project project,
@NotNull PsiField field,
@NotNull PsiParameter parameter,
@NotNull Editor editor) throws IncorrectOperationException {
public static PsiElement addFieldAssignmentStatement(@NotNull Project project,
@NotNull PsiField field,
@NotNull PsiParameter parameter,
@NotNull Editor editor) throws IncorrectOperationException {
final PsiMethod method = (PsiMethod)parameter.getDeclarationScope();
final PsiCodeBlock methodBody = method.getBody();
if (methodBody == null) return;
if (methodBody == null) return null;
final PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory();
final String fieldName = field.getName();
final String parameterName = parameter.getName();
final boolean isMethodStatic = method.hasModifierProperty(PsiModifier.STATIC);
final PsiClass targetClass = method.getContainingClass();
if (targetClass == null) return;
if (targetClass == null) return null;
String stmtText = fieldName + " = " + parameterName + ";";
if (Comparing.strEqual(fieldName, parameterName) || JavaPsiFacade.getInstance(project).getResolveHelper().resolveReferencedVariable(fieldName, methodBody) != field) {
@@ -131,5 +131,6 @@ public class AssignFieldFromParameterAction extends BaseIntentionAction {
}
editor.getCaretModel().moveToOffset(inserted.getTextRange().getEndOffset());
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
return inserted;
}
}

View File

@@ -3,7 +3,7 @@ class A {
private final int _field;
private final int field;
A(int field, int field1) {
_field = field;
this._field = field;
this.field = field1;
}

View File

@@ -2,6 +2,8 @@ package com.intellij.codeInsight.daemon.quickFix;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection;
import com.siyeh.ig.style.MissortedModifiersInspection;
import com.siyeh.ig.style.UnqualifiedFieldAccessInspection;
import org.jetbrains.annotations.NotNull;
/**
@@ -11,7 +13,7 @@ public class CreateConstructorParameterFromFieldTest extends LightQuickFixParame
@NotNull
@Override
protected LocalInspectionTool[] configureLocalInspectionTools() {
return new LocalInspectionTool[]{ new UnusedSymbolLocalInspection()};
return new LocalInspectionTool[]{ new UnusedSymbolLocalInspection(), new MissortedModifiersInspection(), new UnqualifiedFieldAccessInspection()};
}

View File

@@ -56,7 +56,7 @@ public abstract class CleanupIntention implements IntentionAction, LowPriorityAc
final AnalysisScope scope = getScope(project, file);
if (scope != null) {
final InspectionProfile profile = InspectionProjectProfileManager.getInstance(project).getInspectionProfile();
globalContext.codeCleanup(project, scope, profile, getText(), null);
globalContext.codeCleanup(project, scope, profile, getText(), null, false);
}
}

View File

@@ -39,6 +39,7 @@ import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.scope.packageSet.NamedScope;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
@@ -409,13 +410,19 @@ public class GlobalInspectionContextBase extends UserDataHolderBase implements G
public void codeCleanup(final Project project,
final AnalysisScope scope,
final InspectionProfile profile,
final String commandName, Runnable postRunnable) {}
final String commandName, Runnable postRunnable,
final boolean modal) {}
public static void codeCleanup(Project project, AnalysisScope scope, Runnable runnable) {
GlobalInspectionContextBase globalContext =
(GlobalInspectionContextBase)InspectionManager.getInstance(project).createNewGlobalContext(false);
GlobalInspectionContextBase globalContext = (GlobalInspectionContextBase)InspectionManager.getInstance(project).createNewGlobalContext(false);
final InspectionProfile profile = InspectionProjectProfileManager.getInstance(project).getInspectionProfile();
globalContext.codeCleanup(project, scope, profile, null, runnable);
globalContext.codeCleanup(project, scope, profile, null, runnable, false);
}
public static void cleanupElements(Project project, Runnable runnable, PsiElement... scope) {
GlobalInspectionContextBase globalContext = (GlobalInspectionContextBase)InspectionManager.getInstance(project).createNewGlobalContext(false);
final InspectionProfile profile = InspectionProjectProfileManager.getInstance(project).getInspectionProfile();
globalContext.codeCleanup(project, new AnalysisScope(new LocalSearchScope(scope), project), profile, null, runnable, true);
}
public void close(boolean noSuspisiousCodeFound) {

View File

@@ -37,7 +37,7 @@ public class CodeCleanupAction extends CodeInspectionAction {
final InspectionProfile profile = myExternalProfile != null ? myExternalProfile : InspectionProjectProfileManager.getInstance(project).getInspectionProfile();
final InspectionManager managerEx = InspectionManager.getInstance(project);
final GlobalInspectionContextBase globalContext = (GlobalInspectionContextBase)managerEx.createNewGlobalContext(false);
globalContext.codeCleanup(project, scope, profile, getTemplatePresentation().getText(), null);
globalContext.codeCleanup(project, scope, profile, getTemplatePresentation().getText(), null, false);
}
@Override

View File

@@ -48,6 +48,7 @@ import com.intellij.openapi.project.ProjectUtilCore;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.util.JDOMUtil;
import com.intellij.openapi.util.NotNullLazyValue;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
@@ -55,6 +56,7 @@ import com.intellij.openapi.wm.ToolWindowId;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.psi.*;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.ui.content.*;
import com.intellij.util.Processor;
@@ -612,75 +614,106 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
final AnalysisScope scope,
final InspectionProfile profile,
final String commandName,
final Runnable postRunnable) {
final Runnable postRunnable,
final boolean modal) {
Task task;
if (modal) {
task = new Task.Modal(project, "Inspect code...", true) {
@Override
public void run(@NotNull ProgressIndicator indicator) {
cleanup(scope, profile, project, postRunnable, commandName);
}
};
} else {
task = new Task.Backgroundable(project, "Inspect code...", true) {
@Override
public void run(@NotNull ProgressIndicator indicator) {
cleanup(scope, profile, project, postRunnable, commandName);
}
};
}
ProgressManager.getInstance().run(task);
}
private void cleanup(final AnalysisScope scope,
final InspectionProfile profile,
final Project project,
final Runnable postRunnable,
final String commandName) {
final List<LocalInspectionToolWrapper> lTools = new ArrayList<LocalInspectionToolWrapper>();
final LinkedHashMap<PsiFile, List<HighlightInfo>> results = new LinkedHashMap<PsiFile, List<HighlightInfo>>();
ProgressManager.getInstance().run(new Task.Backgroundable(project, "Inspect code...", true) {
final SearchScope searchScope = scope.toSearchScope();
scope.accept(new PsiElementVisitor() {
@Override
public void run(@NotNull ProgressIndicator indicator) {
scope.accept(new PsiElementVisitor() {
@Override
public void visitFile(PsiFile file) {
final VirtualFile virtualFile = file.getVirtualFile();
if (virtualFile == null || virtualFile.getFileType().isBinary()) return;
for (final Tools tools : profile.getAllEnabledInspectionTools(project)) {
if (tools.getTool().getTool() instanceof CleanupLocalInspectionTool) {
final InspectionToolWrapper tool = tools.getEnabledTool(file);
if (tool instanceof LocalInspectionToolWrapper) {
lTools.add((LocalInspectionToolWrapper)tool);
tool.initialize(GlobalInspectionContextImpl.this);
}
}
}
if (!lTools.isEmpty()) {
final LocalInspectionsPass pass = new LocalInspectionsPass(file, PsiDocumentManager.getInstance(project).getDocument(file), 0,
file.getTextLength(), LocalInspectionsPass.EMPTY_PRIORITY_RANGE, true,
HighlightInfoProcessor.getEmpty());
Runnable runnable = new Runnable() {
public void run() {
pass.doInspectInBatch(GlobalInspectionContextImpl.this, (InspectionManagerEx)InspectionManager.getInstance(project), lTools);
}
};
ApplicationManager.getApplication().runReadAction(runnable);
results.put(file, pass.getInfos());
public void visitFile(PsiFile file) {
final VirtualFile virtualFile = file.getVirtualFile();
if (virtualFile == null || virtualFile.getFileType().isBinary()) return;
for (final Tools tools : profile.getAllEnabledInspectionTools(project)) {
if (tools.getTool().getTool() instanceof CleanupLocalInspectionTool) {
final InspectionToolWrapper tool = tools.getEnabledTool(file);
if (tool instanceof LocalInspectionToolWrapper) {
lTools.add((LocalInspectionToolWrapper)tool);
tool.initialize(GlobalInspectionContextImpl.this);
}
}
});
}
Runnable runnable = new Runnable() {
@Override
public void run() {
if (!FileModificationService.getInstance().preparePsiElementsForWrite(results.keySet())) return;
final SequentialModalProgressTask progressTask = new SequentialModalProgressTask(project, "Code Cleanup", true);
progressTask.setMinIterationTime(200);
progressTask.setTask(new SequentialCleanupTask(project, results, progressTask));
CommandProcessor.getInstance().executeCommand(project, new Runnable() {
@Override
public void run() {
CommandProcessor.getInstance().markCurrentCommandAsGlobal(project);
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
ProgressManager.getInstance().run(progressTask);
}
});
if (postRunnable != null) {
ApplicationManager.getApplication().invokeLater(postRunnable);
}
if (!lTools.isEmpty()) {
final LocalInspectionsPass pass = new LocalInspectionsPass(file, PsiDocumentManager.getInstance(project).getDocument(file), 0,
file.getTextLength(), LocalInspectionsPass.EMPTY_PRIORITY_RANGE, true,
HighlightInfoProcessor.getEmpty());
Runnable runnable = new Runnable() {
public void run() {
pass.doInspectInBatch(GlobalInspectionContextImpl.this, (InspectionManagerEx)InspectionManager.getInstance(project), lTools);
}
};
ApplicationManager.getApplication().runReadAction(runnable);
final List<HighlightInfo> infos = pass.getInfos();
if (searchScope instanceof LocalSearchScope) {
for (Iterator<HighlightInfo> iterator = infos.iterator(); iterator.hasNext(); ) {
final HighlightInfo info = iterator.next();
final TextRange infoRange = new TextRange(info.getStartOffset(), info.getEndOffset());
if (!((LocalSearchScope)searchScope).containsRange(file, infoRange)) {
iterator.remove();
}
}, commandName, null);
}
}
};
if (ApplicationManager.getApplication().isUnitTestMode()) {
runnable.run();
} else {
ApplicationManager.getApplication().invokeLater(runnable);
results.put(file, infos);
}
}
});
Runnable runnable = new Runnable() {
@Override
public void run() {
if (!FileModificationService.getInstance().preparePsiElementsForWrite(results.keySet())) return;
final SequentialModalProgressTask progressTask = new SequentialModalProgressTask(project, "Code Cleanup", true);
progressTask.setMinIterationTime(200);
progressTask.setTask(new SequentialCleanupTask(project, results, progressTask));
CommandProcessor.getInstance().executeCommand(project, new Runnable() {
@Override
public void run() {
CommandProcessor.getInstance().markCurrentCommandAsGlobal(project);
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
ProgressManager.getInstance().run(progressTask);
}
});
if (postRunnable != null) {
ApplicationManager.getApplication().invokeLater(postRunnable);
}
}
}, commandName, null);
}
};
if (ApplicationManager.getApplication().isUnitTestMode()) {
runnable.run();
} else {
ApplicationManager.getApplication().invokeLater(runnable);
}
}
}