mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
moved PostHighlightingPass to analysis
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 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.
|
||||
@@ -19,6 +19,7 @@ import com.intellij.codeInsight.daemon.QuickFixActionRegistrar;
|
||||
import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement;
|
||||
import com.intellij.codeInspection.LocalQuickFixOnPsiElement;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
@@ -222,6 +223,26 @@ public abstract class QuickFixFactory {
|
||||
|
||||
public abstract void registerPullAsAbstractUpFixes(@NotNull PsiMethod method, @NotNull QuickFixActionRegistrar registrar);
|
||||
|
||||
public abstract IntentionAction createCreateAnnotationMethodFromUsageFix(PsiNameValuePair pair);
|
||||
@NotNull
|
||||
public abstract IntentionAction createCreateAnnotationMethodFromUsageFix(@NotNull PsiNameValuePair pair);
|
||||
|
||||
@NotNull
|
||||
public abstract IntentionAction createOptimizeImportsFix();
|
||||
|
||||
public abstract void registerFixesForUnusedParameter(@NotNull PsiParameter parameter, @NotNull Object highlightInfo);
|
||||
|
||||
@NotNull
|
||||
public abstract IntentionAction createAddToDependencyInjectionAnnotationsFix(@NotNull Project project, @NotNull String qualifiedName, @NotNull String element);
|
||||
|
||||
@NotNull
|
||||
public abstract IntentionAction createCreateGetterOrSetterFix(boolean createGetter, boolean createSetter, @NotNull PsiField field);
|
||||
|
||||
@NotNull
|
||||
public abstract IntentionAction createRenameToIgnoredFix(@NotNull PsiNamedElement namedElement);
|
||||
|
||||
@NotNull
|
||||
public abstract IntentionAction createEnableOptimizeImportsOnTheFlyFix();
|
||||
|
||||
@NotNull
|
||||
public abstract IntentionAction createSafeDeleteFix(@NotNull PsiElement element);
|
||||
}
|
||||
|
||||
+192
-218
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 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.
|
||||
@@ -16,32 +16,27 @@
|
||||
package com.intellij.codeInsight.daemon.impl;
|
||||
|
||||
import com.intellij.codeHighlighting.Pass;
|
||||
import com.intellij.codeInsight.CodeInsightSettings;
|
||||
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
|
||||
import com.intellij.codeInsight.daemon.ImplicitUsageProvider;
|
||||
import com.intellij.codeInsight.daemon.JavaErrorMessages;
|
||||
import com.intellij.codeInsight.daemon.ProblemHighlightFilter;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.*;
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.*;
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction;
|
||||
import com.intellij.codeInsight.intention.EmptyIntentionAction;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.codeInsight.intention.IntentionManager;
|
||||
import com.intellij.codeInspection.*;
|
||||
import com.intellij.codeInsight.intention.QuickFixFactory;
|
||||
import com.intellij.codeInspection.InspectionProfile;
|
||||
import com.intellij.codeInspection.InspectionsBundle;
|
||||
import com.intellij.codeInspection.SuppressionUtil;
|
||||
import com.intellij.codeInspection.UnusedSymbolLocalInspectionBase;
|
||||
import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection;
|
||||
import com.intellij.codeInspection.ex.EntryPointsManagerBase;
|
||||
import com.intellij.codeInspection.reference.UnusedDeclarationFixProvider;
|
||||
import com.intellij.codeInspection.unusedImport.UnusedImportLocalInspection;
|
||||
import com.intellij.codeInspection.unusedParameters.UnusedParametersInspection;
|
||||
import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection;
|
||||
import com.intellij.codeInspection.util.SpecialAnnotationsUtilBase;
|
||||
import com.intellij.diagnostic.AttachmentFactory;
|
||||
import com.intellij.diagnostic.LogMessageEx;
|
||||
import com.intellij.find.FindManager;
|
||||
import com.intellij.find.findUsages.*;
|
||||
import com.intellij.find.impl.FindManagerImpl;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.lang.annotation.HighlightSeverity;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.command.undo.UndoManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
@@ -51,8 +46,7 @@ import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ProjectFileIndex;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.pom.PomNamedTarget;
|
||||
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
|
||||
@@ -60,34 +54,35 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.impl.PsiClassImplUtil;
|
||||
import com.intellij.psi.impl.source.PsiClassImpl;
|
||||
import com.intellij.psi.impl.source.jsp.jspJava.JspxImportStatement;
|
||||
import com.intellij.psi.jsp.JspFile;
|
||||
import com.intellij.psi.jsp.JspSpiUtil;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.PsiNonJavaFileReferenceProcessor;
|
||||
import com.intellij.psi.search.PsiSearchHelper;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.psi.search.searches.OverridingMethodsSearch;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.search.searches.SuperMethodsSearch;
|
||||
import com.intellij.psi.util.PropertyUtil;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.refactoring.changeSignature.ChangeSignatureGestureDetector;
|
||||
import com.intellij.util.Processor;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.PropertyKey;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static com.intellij.psi.search.PsiSearchHelper.SearchCostResult.TOO_MANY_OCCURRENCES;
|
||||
import static com.intellij.psi.search.PsiSearchHelper.SearchCostResult.ZERO_OCCURRENCES;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.PostHighlightingPass");
|
||||
private static final Key<Long> LAST_POST_PASS_TIMESTAMP = Key.create("LAST_POST_PASS_TIMESTAMP");
|
||||
private RefCountHolder myRefCountHolder;
|
||||
private final PsiFile myFile;
|
||||
@Nullable private final Editor myEditor;
|
||||
private final boolean myUnusedImportEnabled;
|
||||
private final int myStartOffset;
|
||||
private final int myEndOffset;
|
||||
|
||||
@@ -98,22 +93,23 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
|
||||
private boolean myHasMissortedImports;
|
||||
private static final ImplicitUsageProvider[] ourImplicitUsageProviders = Extensions.getExtensions(ImplicitUsageProvider.EP_NAME);
|
||||
private UnusedDeclarationInspection myDeadCodeInspection;
|
||||
private UnusedSymbolLocalInspection myUnusedSymbolInspection;
|
||||
private UnusedSymbolLocalInspectionBase myUnusedSymbolInspection;
|
||||
private HighlightDisplayKey myUnusedSymbolKey;
|
||||
private boolean myDeadCodeEnabled;
|
||||
private boolean myInLibrary;
|
||||
private HighlightDisplayKey myDeadCodeKey;
|
||||
private HighlightInfoType myDeadCodeInfoType;
|
||||
private UnusedParametersInspection myUnusedParametersInspection;
|
||||
|
||||
PostHighlightingPass(@NotNull Project project,
|
||||
@NotNull PsiFile file,
|
||||
@Nullable Editor editor,
|
||||
@NotNull Document document,
|
||||
@NotNull HighlightInfoProcessor highlightInfoProcessor) {
|
||||
public PostHighlightingPass(@NotNull Project project,
|
||||
@NotNull PsiFile file,
|
||||
@Nullable Editor editor,
|
||||
@NotNull Document document,
|
||||
@NotNull HighlightInfoProcessor highlightInfoProcessor,
|
||||
boolean unusedImportEnabled) {
|
||||
super(project, document, "Unused symbols", file, editor, file.getTextRange(), true, highlightInfoProcessor);
|
||||
myFile = file;
|
||||
myEditor = editor;
|
||||
myUnusedImportEnabled = unusedImportEnabled;
|
||||
myStartOffset = 0;
|
||||
myEndOffset = file.getTextLength();
|
||||
|
||||
@@ -121,6 +117,21 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
|
||||
myCurrentEntryIndex = -1;
|
||||
}
|
||||
|
||||
static boolean isUpToDate(@NotNull PsiFile file) {
|
||||
Long lastStamp = file.getUserData(LAST_POST_PASS_TIMESTAMP);
|
||||
long currentStamp = PsiModificationTracker.SERVICE.getInstance(file.getProject()).getModificationCount();
|
||||
return lastStamp != null && lastStamp == currentStamp || !ProblemHighlightFilter.shouldHighlightFile(file);
|
||||
}
|
||||
|
||||
private static void markFileUpToDate(@NotNull PsiFile file) {
|
||||
long lastStamp = PsiModificationTracker.SERVICE.getInstance(file.getProject()).getModificationCount();
|
||||
file.putUserData(LAST_POST_PASS_TIMESTAMP, lastStamp);
|
||||
}
|
||||
|
||||
private static boolean isInjected(@NotNull Project project, @NotNull PsiModifierListOwner modifierListOwner) {
|
||||
return EntryPointsManagerBase.getInstance(project).isEntryPoint(modifierListOwner);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void collectInformationWithProgress(@NotNull final ProgressIndicator progress) {
|
||||
DaemonCodeAnalyzerEx daemonCodeAnalyzer = DaemonCodeAnalyzerEx.getInstanceEx(myProject);
|
||||
@@ -166,59 +177,23 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
|
||||
protected void applyInformationWithProgress() {
|
||||
if (myHighlights == null) return;
|
||||
UpdateHighlightersUtil.setHighlightersToEditor(myProject, myDocument, myStartOffset, myEndOffset, myHighlights, getColorsScheme(), Pass.POST_UPDATE_ALL);
|
||||
PostHighlightingPassFactory.markFileUpToDate(myFile);
|
||||
markFileUpToDate(myFile);
|
||||
|
||||
Editor editor = myEditor;
|
||||
if (editor != null && timeToOptimizeImports()) {
|
||||
if (editor != null) {
|
||||
optimizeImportsOnTheFly(editor);
|
||||
}
|
||||
}
|
||||
|
||||
private void optimizeImportsOnTheFly(@NotNull final Editor editor) {
|
||||
if (myHasRedundantImports || myHasMissortedImports) {
|
||||
final OptimizeImportsFix optimizeImportsFix = new OptimizeImportsFix();
|
||||
IntentionAction optimizeImportsFix = QuickFixFactory.getInstance().createOptimizeImportsFix();
|
||||
if (optimizeImportsFix.isAvailable(myProject, editor, myFile) && myFile.isWritable()) {
|
||||
invokeOnTheFlyImportOptimizer(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
optimizeImportsFix.invoke(myProject, editor, myFile);
|
||||
}
|
||||
}, myFile, editor);
|
||||
optimizeImportsFix.invoke(myProject, editor, myFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void invokeOnTheFlyImportOptimizer(@NotNull final Runnable runnable,
|
||||
@NotNull final PsiFile file,
|
||||
@NotNull final Editor editor) {
|
||||
final long stamp = editor.getDocument().getModificationStamp();
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (file.getProject().isDisposed() || editor.isDisposed() || editor.getDocument().getModificationStamp() != stamp) return;
|
||||
//no need to optimize imports on the fly during undo/redo
|
||||
final UndoManager undoManager = UndoManager.getInstance(editor.getProject());
|
||||
if (undoManager.isUndoInProgress() || undoManager.isRedoInProgress()) return;
|
||||
PsiDocumentManager.getInstance(file.getProject()).commitAllDocuments();
|
||||
String beforeText = file.getText();
|
||||
final long oldStamp = editor.getDocument().getModificationStamp();
|
||||
CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ApplicationManager.getApplication().runWriteAction(runnable);
|
||||
}
|
||||
});
|
||||
if (oldStamp != editor.getDocument().getModificationStamp()) {
|
||||
String afterText = file.getText();
|
||||
if (Comparing.strEqual(beforeText, afterText)) {
|
||||
LOG.error(LogMessageEx.createEvent("Import optimizer hasn't optimized any imports", file.getViewProvider().getVirtualFile().getPath(),
|
||||
AttachmentFactory.createAttachment(file.getViewProvider().getVirtualFile())));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// returns true if error highlight was created
|
||||
private boolean collectHighlights(@NotNull Collection<PsiElement> elements,
|
||||
@NotNull final List<HighlightInfo> result,
|
||||
@@ -226,25 +201,16 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
|
||||
ApplicationManager.getApplication().assertReadAccessAllowed();
|
||||
|
||||
InspectionProfile profile = InspectionProjectProfileManager.getInstance(myProject).getInspectionProfile();
|
||||
myUnusedSymbolKey = HighlightDisplayKey.find(UnusedSymbolLocalInspection.SHORT_NAME);
|
||||
myUnusedSymbolKey = HighlightDisplayKey.find(UnusedSymbolLocalInspectionBase.SHORT_NAME);
|
||||
boolean unusedSymbolEnabled = profile.isToolEnabled(myUnusedSymbolKey, myFile);
|
||||
HighlightDisplayKey unusedImportKey = HighlightDisplayKey.find(UnusedImportLocalInspection.SHORT_NAME);
|
||||
boolean unusedImportEnabled = profile.isToolEnabled(unusedImportKey, myFile);
|
||||
myUnusedSymbolInspection = (UnusedSymbolLocalInspection)profile.getUnwrappedTool(UnusedSymbolLocalInspection.SHORT_NAME, myFile);
|
||||
myUnusedSymbolInspection = (UnusedSymbolLocalInspectionBase)profile.getUnwrappedTool(UnusedSymbolLocalInspectionBase.SHORT_NAME, myFile);
|
||||
LOG.assertTrue(ApplicationManager.getApplication().isUnitTestMode() || myUnusedSymbolInspection != null);
|
||||
|
||||
myDeadCodeKey = HighlightDisplayKey.find(UnusedDeclarationInspection.SHORT_NAME);
|
||||
myDeadCodeInspection = (UnusedDeclarationInspection)profile.getUnwrappedTool(UnusedDeclarationInspection.SHORT_NAME, myFile);
|
||||
myDeadCodeEnabled = profile.isToolEnabled(myDeadCodeKey, myFile);
|
||||
|
||||
myUnusedParametersInspection = (UnusedParametersInspection)profile.getUnwrappedTool(UnusedParametersInspection.SHORT_NAME, myFile);
|
||||
LOG.assertTrue(ApplicationManager.getApplication().isUnitTestMode() || myUnusedParametersInspection != null);
|
||||
if (unusedImportEnabled && JspPsiUtil.isInJspFile(myFile)) {
|
||||
final JspFile jspFile = JspPsiUtil.getJspFile(myFile);
|
||||
if (jspFile != null) {
|
||||
unusedImportEnabled = !JspSpiUtil.isIncludedOrIncludesSomething(jspFile);
|
||||
}
|
||||
}
|
||||
HighlightDisplayKey unusedImportKey = HighlightDisplayKey.find(UnusedImportLocalInspection.SHORT_NAME);
|
||||
|
||||
myDeadCodeInfoType = myDeadCodeKey == null
|
||||
? null
|
||||
@@ -282,7 +248,7 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
|
||||
}
|
||||
}
|
||||
}
|
||||
if (unusedImportEnabled && myFile instanceof PsiJavaFile && HighlightingLevelManager.getInstance(myProject).shouldHighlight(myFile)) {
|
||||
if (myUnusedImportEnabled && myFile instanceof PsiJavaFile && HighlightingLevelManager.getInstance(myProject).shouldHighlight(myFile)) {
|
||||
PsiImportList importList = ((PsiJavaFile)myFile).getImportList();
|
||||
if (importList != null) {
|
||||
final PsiImportStatementBase[] imports = importList.getAllImportStatements();
|
||||
@@ -301,7 +267,7 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private HighlightInfo processIdentifier(PsiIdentifier identifier, ProgressIndicator progress, GlobalUsageHelper helper) {
|
||||
private HighlightInfo processIdentifier(@NotNull PsiIdentifier identifier, @NotNull ProgressIndicator progress, @NotNull GlobalUsageHelper helper) {
|
||||
if (SuppressionUtil.inspectionResultSuppressed(identifier, myUnusedSymbolInspection)) return null;
|
||||
PsiElement parent = identifier.getParent();
|
||||
if (PsiUtilCore.hasErrorElementChild(parent)) return null;
|
||||
@@ -310,17 +276,17 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
|
||||
return processLocalVariable((PsiLocalVariable)parent, identifier, progress);
|
||||
}
|
||||
if (parent instanceof PsiField && myUnusedSymbolInspection.FIELD) {
|
||||
return processField((PsiField)parent, identifier, progress, helper);
|
||||
return processField(myProject, (PsiField)parent, identifier, progress, helper);
|
||||
}
|
||||
if (parent instanceof PsiParameter && myUnusedSymbolInspection.PARAMETER) {
|
||||
if (SuppressionUtil.isSuppressed(identifier, UnusedParametersInspection.SHORT_NAME)) return null;
|
||||
return processParameter((PsiParameter)parent, identifier, progress);
|
||||
if (SuppressionUtil.isSuppressed(identifier, UnusedSymbolLocalInspectionBase.UNUSED_PARAMETERS_SHORT_NAME)) return null;
|
||||
return processParameter(myProject, (PsiParameter)parent, identifier, progress);
|
||||
}
|
||||
if (parent instanceof PsiMethod && myUnusedSymbolInspection.METHOD) {
|
||||
return processMethod((PsiMethod)parent, identifier, progress, helper);
|
||||
return processMethod(myProject, (PsiMethod)parent, identifier, progress, helper);
|
||||
}
|
||||
if (parent instanceof PsiClass && myUnusedSymbolInspection.CLASS) {
|
||||
return processClass((PsiClass)parent, identifier, progress, helper);
|
||||
return processClass(myProject, (PsiClass)parent, identifier, progress, helper);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -330,30 +296,30 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
|
||||
@NotNull PsiIdentifier identifier,
|
||||
@NotNull ProgressIndicator progress) {
|
||||
if (variable instanceof PsiResourceVariable && PsiUtil.isIgnoredName(variable.getName())) return null;
|
||||
if (isImplicitUsage(variable, progress)) return null;
|
||||
if (isImplicitUsage(myProject, variable, progress)) return null;
|
||||
|
||||
if (!myRefCountHolder.isReferenced(variable)) {
|
||||
String message = JavaErrorMessages.message("local.variable.is.never.used", identifier.getText());
|
||||
HighlightInfo highlightInfo = createUnusedSymbolInfo(identifier, message, HighlightInfoType.UNUSED_SYMBOL);
|
||||
IntentionAction fix = variable instanceof PsiResourceVariable ? new RenameToIgnoredFix(variable) : new RemoveUnusedVariableFix(variable);
|
||||
IntentionAction fix = variable instanceof PsiResourceVariable ? QuickFixFactory.getInstance().createRenameToIgnoredFix(variable) : QuickFixFactory.getInstance().createRemoveUnusedVariableFix(variable);
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, fix, myUnusedSymbolKey);
|
||||
return highlightInfo;
|
||||
}
|
||||
|
||||
boolean referenced = myRefCountHolder.isReferencedForRead(variable);
|
||||
if (!referenced && !isImplicitRead(variable, progress)) {
|
||||
if (!referenced && !isImplicitRead(myProject, variable, progress)) {
|
||||
String message = JavaErrorMessages.message("local.variable.is.not.used.for.reading", identifier.getText());
|
||||
HighlightInfo highlightInfo = createUnusedSymbolInfo(identifier, message, HighlightInfoType.UNUSED_SYMBOL);
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, new RemoveUnusedVariableFix(variable), myUnusedSymbolKey);
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createRemoveUnusedVariableFix(variable), myUnusedSymbolKey);
|
||||
return highlightInfo;
|
||||
}
|
||||
|
||||
if (!variable.hasInitializer()) {
|
||||
referenced = myRefCountHolder.isReferencedForWrite(variable);
|
||||
if (!referenced && !isImplicitWrite(variable, progress)) {
|
||||
if (!referenced && !isImplicitWrite(myProject, variable, progress)) {
|
||||
String message = JavaErrorMessages.message("local.variable.is.not.assigned", identifier.getText());
|
||||
final HighlightInfo unusedSymbolInfo = createUnusedSymbolInfo(identifier, message, HighlightInfoType.UNUSED_SYMBOL);
|
||||
QuickFixAction.registerQuickFixAction(unusedSymbolInfo, new EmptyIntentionAction(UnusedSymbolLocalInspection.DISPLAY_NAME), myUnusedSymbolKey);
|
||||
QuickFixAction.registerQuickFixAction(unusedSymbolInfo, new EmptyIntentionAction(UnusedSymbolLocalInspectionBase.DISPLAY_NAME), myUnusedSymbolKey);
|
||||
return unusedSymbolInfo;
|
||||
}
|
||||
}
|
||||
@@ -361,8 +327,10 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean isImplicitUsage(final PsiModifierListOwner element, ProgressIndicator progress) {
|
||||
if (UnusedSymbolLocalInspection.isInjected(element)) return true;
|
||||
public static boolean isImplicitUsage(@NotNull Project project,
|
||||
@NotNull PsiModifierListOwner element,
|
||||
@NotNull ProgressIndicator progress) {
|
||||
if (isInjected(project, element)) return true;
|
||||
for (ImplicitUsageProvider provider : ourImplicitUsageProviders) {
|
||||
progress.checkCanceled();
|
||||
if (provider.isImplicitUsage(element)) {
|
||||
@@ -373,24 +341,26 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isImplicitRead(final PsiVariable element, ProgressIndicator progress) {
|
||||
private static boolean isImplicitRead(@NotNull Project project, @NotNull PsiVariable element, @NotNull ProgressIndicator progress) {
|
||||
for(ImplicitUsageProvider provider: ourImplicitUsageProviders) {
|
||||
progress.checkCanceled();
|
||||
if (provider.isImplicitRead(element)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return UnusedSymbolLocalInspection.isInjected(element);
|
||||
return isInjected(project, element);
|
||||
}
|
||||
|
||||
private static boolean isImplicitWrite(final PsiVariable element, ProgressIndicator progress) {
|
||||
private static boolean isImplicitWrite(@NotNull Project project,
|
||||
@NotNull PsiVariable element,
|
||||
@NotNull ProgressIndicator progress) {
|
||||
for(ImplicitUsageProvider provider: ourImplicitUsageProviders) {
|
||||
progress.checkCanceled();
|
||||
if (provider.isImplicitWrite(element)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return UnusedSymbolLocalInspection.isInjected(element);
|
||||
return isInjected(project, element);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -411,7 +381,8 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private HighlightInfo processField(@NotNull final PsiField field,
|
||||
private HighlightInfo processField(@NotNull final Project project,
|
||||
@NotNull final PsiField field,
|
||||
@NotNull PsiIdentifier identifier,
|
||||
@NotNull ProgressIndicator progress,
|
||||
@NotNull GlobalUsageHelper helper) {
|
||||
@@ -419,18 +390,18 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
|
||||
return null;
|
||||
}
|
||||
if (field.hasModifierProperty(PsiModifier.PRIVATE)) {
|
||||
if (!myRefCountHolder.isReferenced(field) && !isImplicitUsage(field, progress)) {
|
||||
if (!myRefCountHolder.isReferenced(field) && !isImplicitUsage(myProject, field, progress)) {
|
||||
String message = JavaErrorMessages.message("private.field.is.not.used", identifier.getText());
|
||||
|
||||
HighlightInfo highlightInfo = suggestionsToMakeFieldUsed(field, identifier, message);
|
||||
if (!field.hasInitializer()) {
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, HighlightMethodUtil.getFixRange(field), new CreateConstructorParameterFromFieldFix(field));
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, HighlightMethodUtil.getFixRange(field), QuickFixFactory.getInstance().createCreateConstructorParameterFromFieldFix(field));
|
||||
}
|
||||
return highlightInfo;
|
||||
}
|
||||
|
||||
final boolean readReferenced = myRefCountHolder.isReferencedForRead(field);
|
||||
if (!readReferenced && !isImplicitRead(field, progress)) {
|
||||
if (!readReferenced && !isImplicitRead(project, field, progress)) {
|
||||
String message = JavaErrorMessages.message("private.field.is.not.used.for.reading", identifier.getText());
|
||||
return suggestionsToMakeFieldUsed(field, identifier, message);
|
||||
}
|
||||
@@ -439,44 +410,52 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
|
||||
return null;
|
||||
}
|
||||
final boolean writeReferenced = myRefCountHolder.isReferencedForWrite(field);
|
||||
if (!writeReferenced && !isImplicitWrite(field, progress)) {
|
||||
if (!writeReferenced && !isImplicitWrite(project, field, progress)) {
|
||||
String message = JavaErrorMessages.message("private.field.is.not.assigned", identifier.getText());
|
||||
final HighlightInfo info = createUnusedSymbolInfo(identifier, message, HighlightInfoType.UNUSED_SYMBOL);
|
||||
|
||||
QuickFixAction.registerQuickFixAction(info, new CreateGetterOrSetterFix(false, true, field), myUnusedSymbolKey);
|
||||
QuickFixAction.registerQuickFixAction(info, HighlightMethodUtil.getFixRange(field), new CreateConstructorParameterFromFieldFix(field));
|
||||
QuickFixAction.registerQuickFixAction(info, QuickFixFactory.getInstance().createCreateGetterOrSetterFix(false, true, field), myUnusedSymbolKey);
|
||||
QuickFixAction.registerQuickFixAction(info, HighlightMethodUtil.getFixRange(field), QuickFixFactory.getInstance().createCreateConstructorParameterFromFieldFix(
|
||||
field));
|
||||
SpecialAnnotationsUtilBase.createAddToSpecialAnnotationFixes(field, new Processor<String>() {
|
||||
@Override
|
||||
public boolean process(final String annoName) {
|
||||
QuickFixAction.registerQuickFixAction(info, UnusedSymbolLocalInspection.createQuickFix(annoName, "fields", field.getProject()));
|
||||
QuickFixAction.registerQuickFixAction(info, QuickFixFactory.getInstance()
|
||||
.createAddToDependencyInjectionAnnotationsFix(project, annoName, "fields"));
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return info;
|
||||
}
|
||||
}
|
||||
else if (isImplicitUsage(field, progress)) {
|
||||
else if (isImplicitUsage(myProject, field, progress)) {
|
||||
return null;
|
||||
}
|
||||
else if (isFieldUnused(field, progress, helper)) {
|
||||
return formatUnusedSymbolHighlightInfo("field.is.not.used", field, "fields", myDeadCodeKey, myDeadCodeInfoType, identifier);
|
||||
else if (isFieldUnused(myProject, myFile, field, progress, helper)) {
|
||||
return formatUnusedSymbolHighlightInfo(project, "field.is.not.used", field, "fields", myDeadCodeKey, myDeadCodeInfoType, identifier
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean isFieldUnused(PsiField field, ProgressIndicator progress, GlobalUsageHelper helper) {
|
||||
if (helper.isLocallyUsed(field) || !weAreSureThereAreNoUsages(field, progress, helper)) {
|
||||
public static boolean isFieldUnused(@NotNull Project project,
|
||||
@NotNull PsiFile containingFile,
|
||||
@NotNull PsiField field,
|
||||
@NotNull ProgressIndicator progress,
|
||||
@NotNull GlobalUsageHelper helper) {
|
||||
if (helper.isLocallyUsed(field) || !weAreSureThereAreNoUsages(project, containingFile, field, progress, helper)) {
|
||||
return false;
|
||||
}
|
||||
return !(field instanceof PsiEnumConstant) || !isEnumValuesMethodUsed(field, progress, helper);
|
||||
return !(field instanceof PsiEnumConstant) || !isEnumValuesMethodUsed(project, containingFile, field, progress, helper
|
||||
);
|
||||
}
|
||||
|
||||
private HighlightInfo suggestionsToMakeFieldUsed(final PsiField field, final PsiIdentifier identifier, final String message) {
|
||||
private HighlightInfo suggestionsToMakeFieldUsed(@NotNull PsiField field, @NotNull PsiIdentifier identifier, @NotNull String message) {
|
||||
HighlightInfo highlightInfo = createUnusedSymbolInfo(identifier, message, HighlightInfoType.UNUSED_SYMBOL);
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, new RemoveUnusedVariableFix(field), myUnusedSymbolKey);
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, new CreateGetterOrSetterFix(true, false, field), myUnusedSymbolKey);
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, new CreateGetterOrSetterFix(false, true, field), myUnusedSymbolKey);
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, new CreateGetterOrSetterFix(true, true, field), myUnusedSymbolKey);
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createRemoveUnusedVariableFix(field), myUnusedSymbolKey);
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createCreateGetterOrSetterFix(true, false, field), myUnusedSymbolKey);
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createCreateGetterOrSetterFix(false, true, field), myUnusedSymbolKey);
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createCreateGetterOrSetterFix(true, true, field), myUnusedSymbolKey);
|
||||
return highlightInfo;
|
||||
}
|
||||
|
||||
@@ -486,7 +465,8 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private HighlightInfo processParameter(@NotNull PsiParameter parameter,
|
||||
private HighlightInfo processParameter(@NotNull Project project,
|
||||
@NotNull PsiParameter parameter,
|
||||
@NotNull PsiIdentifier identifier,
|
||||
@NotNull ProgressIndicator progress) {
|
||||
PsiElement declarationScope = parameter.getDeclarationScope();
|
||||
@@ -502,18 +482,10 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
|
||||
!method.hasModifierProperty(PsiModifier.NATIVE) &&
|
||||
!JavaHighlightUtil.isSerializationRelatedMethod(method, method.getContainingClass()) &&
|
||||
!PsiClassImplUtil.isMainOrPremainMethod(method)) {
|
||||
if (UnusedSymbolLocalInspection.isInjected(method)) return null;
|
||||
if (isInjected(project, method)) return null;
|
||||
HighlightInfo highlightInfo = checkUnusedParameter(parameter, identifier, progress);
|
||||
if (highlightInfo != null) {
|
||||
List<IntentionAction> options = new ArrayList<IntentionAction>();
|
||||
options.addAll(IntentionManager.getInstance().getStandardIntentionOptions(myUnusedSymbolKey, myFile));
|
||||
if (myUnusedParametersInspection != null) {
|
||||
SuppressQuickFix[] batchSuppressActions = myUnusedParametersInspection.getBatchSuppressActions(parameter);
|
||||
Collections.addAll(options, SuppressIntentionActionFromFix.convertBatchToSuppressIntentionActions(batchSuppressActions));
|
||||
}
|
||||
//need suppress from Unused Parameters but settings from Unused Symbol
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, new RemoveUnusedParameterFix(parameter),
|
||||
options, HighlightDisplayKey.getDisplayNameByKey(myUnusedSymbolKey));
|
||||
QuickFixFactory.getInstance().registerFixesForUnusedParameter(parameter, highlightInfo);
|
||||
return highlightInfo;
|
||||
}
|
||||
}
|
||||
@@ -521,7 +493,7 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
|
||||
else if (declarationScope instanceof PsiForeachStatement && !PsiUtil.isIgnoredName(parameter.getName())) {
|
||||
HighlightInfo highlightInfo = checkUnusedParameter(parameter, identifier, progress);
|
||||
if (highlightInfo != null) {
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, new RenameToIgnoredFix(parameter), myUnusedSymbolKey);
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createRenameToIgnoredFix(parameter), myUnusedSymbolKey);
|
||||
return highlightInfo;
|
||||
}
|
||||
}
|
||||
@@ -533,7 +505,7 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
|
||||
private HighlightInfo checkUnusedParameter(@NotNull PsiParameter parameter,
|
||||
@NotNull PsiIdentifier identifier,
|
||||
@NotNull ProgressIndicator progress) {
|
||||
if (!myRefCountHolder.isReferenced(parameter) && !isImplicitUsage(parameter, progress)) {
|
||||
if (!myRefCountHolder.isReferenced(parameter) && !isImplicitUsage(myProject, parameter, progress)) {
|
||||
String message = JavaErrorMessages.message("parameter.is.not.used", identifier.getText());
|
||||
return createUnusedSymbolInfo(identifier, message, HighlightInfoType.UNUSED_SYMBOL);
|
||||
}
|
||||
@@ -541,11 +513,12 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private HighlightInfo processMethod(@NotNull final PsiMethod method,
|
||||
private HighlightInfo processMethod(@NotNull final Project project,
|
||||
@NotNull final PsiMethod method,
|
||||
@NotNull PsiIdentifier identifier,
|
||||
@NotNull ProgressIndicator progress,
|
||||
@NotNull GlobalUsageHelper helper) {
|
||||
if (isMethodReferenced(method, progress, helper)) return null;
|
||||
if (isMethodReferenced(myProject, myFile, method, progress, helper)) return null;
|
||||
HighlightInfoType highlightInfoType;
|
||||
HighlightDisplayKey highlightDisplayKey;
|
||||
String key;
|
||||
@@ -562,26 +535,23 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
|
||||
String symbolName = HighlightMessageUtil.getSymbolName(method, PsiSubstitutor.EMPTY);
|
||||
String message = JavaErrorMessages.message(key, symbolName);
|
||||
final HighlightInfo highlightInfo = createUnusedSymbolInfo(identifier, message, highlightInfoType);
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, new SafeDeleteFix(method), highlightDisplayKey);
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createSafeDeleteFix(method), highlightDisplayKey);
|
||||
SpecialAnnotationsUtilBase.createAddToSpecialAnnotationFixes(method, new Processor<String>() {
|
||||
@Override
|
||||
public boolean process(final String annoName) {
|
||||
QuickFixAction
|
||||
.registerQuickFixAction(highlightInfo, UnusedSymbolLocalInspection.createQuickFix(annoName, "methods", method.getProject()));
|
||||
IntentionAction fix = QuickFixFactory.getInstance().createAddToDependencyInjectionAnnotationsFix(project, annoName, "methods");
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, fix);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
PsiClass containingClass = method.getContainingClass();
|
||||
if (method.getReturnType() != null || containingClass != null && Comparing.strEqual(containingClass.getName(), method.getName())) {
|
||||
//ignore methods with deleted return types as they are always marked as unused without any reason
|
||||
ChangeSignatureGestureDetector.getInstance(myProject).dismissForElement(method);
|
||||
}
|
||||
return highlightInfo;
|
||||
}
|
||||
|
||||
public static boolean isMethodReferenced(PsiMethod method,
|
||||
ProgressIndicator progress,
|
||||
GlobalUsageHelper helper) {
|
||||
public static boolean isMethodReferenced(@NotNull Project project,
|
||||
@NotNull PsiFile containingFile,
|
||||
@NotNull PsiMethod method,
|
||||
@NotNull ProgressIndicator progress,
|
||||
@NotNull GlobalUsageHelper helper) {
|
||||
if (helper.isLocallyUsed(method)) return true;
|
||||
|
||||
boolean aPrivate = method.hasModifierProperty(PsiModifier.PRIVATE);
|
||||
@@ -591,39 +561,42 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
|
||||
if (isIntentionalPrivateConstructor(method, containingClass)) {
|
||||
return true;
|
||||
}
|
||||
if (isImplicitUsage(method, progress)) {
|
||||
if (isImplicitUsage(project, method, progress)) {
|
||||
return true;
|
||||
}
|
||||
if (!helper.isCurrentFileAlreadyChecked()) {
|
||||
return !weAreSureThereAreNoUsages(method, progress, helper);
|
||||
return !weAreSureThereAreNoUsages(project, containingFile, method, progress, helper);
|
||||
}
|
||||
}
|
||||
else {
|
||||
//class maybe used in some weird way, e.g. from XML, therefore the only constructor is used too
|
||||
if (containingClass != null && method.isConstructor()
|
||||
&& containingClass.getConstructors().length == 1
|
||||
&& isClassUsed(containingClass, progress, helper)) {
|
||||
&& isClassUsed(project, containingFile, containingClass, progress, helper)) {
|
||||
return true;
|
||||
}
|
||||
if (isImplicitUsage(method, progress)) return true;
|
||||
if (isImplicitUsage(project, method, progress)) return true;
|
||||
|
||||
if (method.findSuperMethods().length != 0) {
|
||||
return true;
|
||||
}
|
||||
if (!weAreSureThereAreNoUsages(method, progress, helper)) {
|
||||
if (!weAreSureThereAreNoUsages(project, containingFile, method, progress, helper)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean weAreSureThereAreNoUsages(@NotNull PsiMember member, ProgressIndicator progress, GlobalUsageHelper helper) {
|
||||
private static boolean weAreSureThereAreNoUsages(@NotNull Project project,
|
||||
@NotNull PsiFile containingFile,
|
||||
@NotNull PsiMember member,
|
||||
@NotNull ProgressIndicator progress,
|
||||
@NotNull GlobalUsageHelper helper) {
|
||||
if (!helper.shouldCheckUsages(member)) return false;
|
||||
|
||||
String name = member.getName();
|
||||
if (name == null) return false;
|
||||
SearchScope useScope = member.getUseScope();
|
||||
Project project = member.getProject();
|
||||
if (useScope instanceof GlobalSearchScope) {
|
||||
// some classes may have references from within XML outside dependent modules, e.g. our actions
|
||||
if (member instanceof PsiClass) {
|
||||
@@ -631,46 +604,67 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
|
||||
}
|
||||
|
||||
PsiSearchHelper searchHelper = PsiSearchHelper.SERVICE.getInstance(project);
|
||||
PsiFile file = member.getContainingFile();
|
||||
PsiFile ignoreFile = helper.isCurrentFileAlreadyChecked() ? file : null;
|
||||
PsiFile ignoreFile = helper.isCurrentFileAlreadyChecked() ? containingFile : null;
|
||||
PsiSearchHelper.SearchCostResult cheapEnough = searchHelper.isCheapEnoughToSearch(name, (GlobalSearchScope)useScope, ignoreFile, progress);
|
||||
if (cheapEnough == TOO_MANY_OCCURRENCES) return false;
|
||||
if (cheapEnough == PsiSearchHelper.SearchCostResult.TOO_MANY_OCCURRENCES) return false;
|
||||
|
||||
//search usages if it cheap
|
||||
//if count is 0 there is no usages since we've called myRefCountHolder.isReferenced() before
|
||||
if (cheapEnough == ZERO_OCCURRENCES) {
|
||||
if (!canBeReferencedViaWeirdNames(member)) return true;
|
||||
if (cheapEnough == PsiSearchHelper.SearchCostResult.ZERO_OCCURRENCES && !canBeReferencedViaWeirdNames(member, containingFile)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (member instanceof PsiMethod) {
|
||||
String propertyName = PropertyUtil.getPropertyName(member);
|
||||
if (propertyName != null && file != null) {
|
||||
SearchScope fileScope = file.getUseScope();
|
||||
if (propertyName != null) {
|
||||
SearchScope fileScope = containingFile.getUseScope();
|
||||
if (fileScope instanceof GlobalSearchScope &&
|
||||
searchHelper.isCheapEnoughToSearch(propertyName, (GlobalSearchScope)fileScope, ignoreFile, progress) == TOO_MANY_OCCURRENCES) {
|
||||
searchHelper.isCheapEnoughToSearch(propertyName, (GlobalSearchScope)fileScope, ignoreFile, progress) ==
|
||||
PsiSearchHelper.SearchCostResult.TOO_MANY_OCCURRENCES) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(project)).getFindUsagesManager();
|
||||
FindUsagesHandler handler = new JavaFindUsagesHandler(member, new JavaFindUsagesHandlerFactory(project));
|
||||
FindUsagesOptions findUsagesOptions = handler.getFindUsagesOptions().clone();
|
||||
findUsagesOptions.searchScope = useScope;
|
||||
findUsagesOptions.isSearchForTextOccurrences = true;
|
||||
return !findUsagesManager.isUsed(member, findUsagesOptions);
|
||||
|
||||
//FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(project)).getFindUsagesManager();
|
||||
//FindUsagesHandler handler = new JavaFindUsagesHandler(member, new JavaFindUsagesHandlerFactory(project));
|
||||
//FindUsagesOptions findUsagesOptions = handler.getFindUsagesOptions().clone();
|
||||
//findUsagesOptions.searchScope = useScope;
|
||||
//findUsagesOptions.isSearchForTextOccurrences = true;
|
||||
//boolean old = !findUsagesManager.isUsed(member, findUsagesOptions);
|
||||
|
||||
//if (true) {
|
||||
if (ReferencesSearch.search(member, useScope, true).findFirst() != null) return false;
|
||||
return !(useScope instanceof GlobalSearchScope) || !foundUsageInText(member, (GlobalSearchScope)useScope);
|
||||
//}
|
||||
//return old;
|
||||
}
|
||||
|
||||
private static boolean isEnumValuesMethodUsed(PsiMember member, ProgressIndicator progress, GlobalUsageHelper helper) {
|
||||
private static boolean foundUsageInText(PsiMember member, GlobalSearchScope scope) {
|
||||
PsiSearchHelper helper = PsiSearchHelper.SERVICE.getInstance(member.getProject());
|
||||
|
||||
return !helper.processUsagesInNonJavaFiles(member, member.getName(), new PsiNonJavaFileReferenceProcessor() {
|
||||
@Override
|
||||
public boolean process(final PsiFile psiFile, final int startOffset, final int endOffset) {
|
||||
return false;
|
||||
}
|
||||
}, scope);
|
||||
}
|
||||
|
||||
private static boolean isEnumValuesMethodUsed(@NotNull Project project,
|
||||
@NotNull PsiFile containingFile,
|
||||
@NotNull PsiMember member,
|
||||
@NotNull ProgressIndicator progress,
|
||||
@NotNull GlobalUsageHelper helper) {
|
||||
final PsiClass containingClass = member.getContainingClass();
|
||||
if (containingClass == null || !(containingClass instanceof PsiClassImpl)) return true;
|
||||
final PsiMethod valuesMethod = ((PsiClassImpl)containingClass).getValuesMethod();
|
||||
return valuesMethod == null || isMethodReferenced(valuesMethod, progress, helper);
|
||||
return valuesMethod == null || isMethodReferenced(project, containingFile, valuesMethod, progress, helper);
|
||||
}
|
||||
|
||||
private static boolean canBeReferencedViaWeirdNames(PsiMember member) {
|
||||
private static boolean canBeReferencedViaWeirdNames(@NotNull PsiMember member, @NotNull PsiFile containingFile) {
|
||||
if (member instanceof PsiClass) return false;
|
||||
PsiFile containingFile = member.getContainingFile();
|
||||
if (!(containingFile instanceof PsiJavaFile)) return true; // Groovy field can be referenced from Java by getter
|
||||
if (member instanceof PsiField) return false; //Java field cannot be referenced by anything but its name
|
||||
if (member instanceof PsiMethod) {
|
||||
@@ -680,11 +674,12 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private HighlightInfo processClass(@NotNull PsiClass aClass,
|
||||
private HighlightInfo processClass(@NotNull Project project,
|
||||
@NotNull PsiClass aClass,
|
||||
@NotNull PsiIdentifier identifier,
|
||||
@NotNull ProgressIndicator progress,
|
||||
@NotNull GlobalUsageHelper helper) {
|
||||
if (isClassUsed(aClass, progress, helper)) return null;
|
||||
if (isClassUsed(project, myFile, aClass, progress, helper)) return null;
|
||||
|
||||
String pattern;
|
||||
HighlightDisplayKey highlightDisplayKey;
|
||||
@@ -711,30 +706,39 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
|
||||
highlightDisplayKey = myDeadCodeKey;
|
||||
highlightInfoType = myDeadCodeInfoType;
|
||||
}
|
||||
return formatUnusedSymbolHighlightInfo(pattern, aClass, "classes", highlightDisplayKey, highlightInfoType, identifier);
|
||||
return formatUnusedSymbolHighlightInfo(myProject, pattern, aClass, "classes", highlightDisplayKey, highlightInfoType, identifier
|
||||
);
|
||||
}
|
||||
|
||||
public static boolean isClassUsed(PsiClass aClass, ProgressIndicator progress, GlobalUsageHelper helper) {
|
||||
if (aClass == null) return true;
|
||||
public static boolean isClassUsed(@NotNull Project project,
|
||||
@NotNull PsiFile containingFile,
|
||||
@NotNull PsiClass aClass,
|
||||
@NotNull ProgressIndicator progress,
|
||||
@NotNull GlobalUsageHelper helper) {
|
||||
Boolean result = helper.unusedClassCache.get(aClass);
|
||||
if (result == null) {
|
||||
result = isReallyUsed(aClass, progress, helper);
|
||||
result = isReallyUsed(project, containingFile, aClass, progress, helper);
|
||||
helper.unusedClassCache.put(aClass, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static boolean isReallyUsed(PsiClass aClass, ProgressIndicator progress, GlobalUsageHelper helper) {
|
||||
if (isImplicitUsage(aClass, progress) || helper.isLocallyUsed(aClass)) return true;
|
||||
private static boolean isReallyUsed(@NotNull Project project,
|
||||
@NotNull PsiFile containingFile,
|
||||
@NotNull PsiClass aClass,
|
||||
@NotNull ProgressIndicator progress,
|
||||
@NotNull GlobalUsageHelper helper) {
|
||||
if (isImplicitUsage(project, aClass, progress) || helper.isLocallyUsed(aClass)) return true;
|
||||
if (helper.isCurrentFileAlreadyChecked()) {
|
||||
if (aClass.getContainingClass() != null && aClass.hasModifierProperty(PsiModifier.PRIVATE) ||
|
||||
aClass.getParent() instanceof PsiDeclarationStatement ||
|
||||
aClass instanceof PsiTypeParameter) return false;
|
||||
}
|
||||
return !weAreSureThereAreNoUsages(aClass, progress, helper);
|
||||
return !weAreSureThereAreNoUsages(project, containingFile, aClass, progress, helper);
|
||||
}
|
||||
|
||||
private static HighlightInfo formatUnusedSymbolHighlightInfo(@NotNull @PropertyKey(resourceBundle = JavaErrorMessages.BUNDLE) String pattern,
|
||||
private static HighlightInfo formatUnusedSymbolHighlightInfo(@NotNull final Project project,
|
||||
@NotNull @PropertyKey(resourceBundle = JavaErrorMessages.BUNDLE) String pattern,
|
||||
@NotNull final PsiNameIdentifierOwner aClass,
|
||||
@NotNull final String element,
|
||||
@NotNull HighlightDisplayKey highlightDisplayKey,
|
||||
@@ -743,12 +747,13 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
|
||||
String symbolName = aClass.getName();
|
||||
String message = JavaErrorMessages.message(pattern, symbolName);
|
||||
final HighlightInfo highlightInfo = createUnusedSymbolInfo(identifier, message, highlightInfoType);
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, new SafeDeleteFix(aClass), highlightDisplayKey);
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createSafeDeleteFix(aClass), highlightDisplayKey);
|
||||
SpecialAnnotationsUtilBase.createAddToSpecialAnnotationFixes((PsiModifierListOwner)aClass, new Processor<String>() {
|
||||
@Override
|
||||
public boolean process(final String annoName) {
|
||||
QuickFixAction
|
||||
.registerQuickFixAction(highlightInfo, UnusedSymbolLocalInspection.createQuickFix(annoName, element, aClass.getProject()));
|
||||
.registerQuickFixAction(highlightInfo,
|
||||
QuickFixFactory.getInstance().createAddToDependencyInjectionAnnotationsFix(project, annoName, element));
|
||||
return true;
|
||||
}
|
||||
});
|
||||
@@ -758,7 +763,7 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
|
||||
@Nullable
|
||||
private HighlightInfo processImport(@NotNull PsiImportStatementBase importStatement, @NotNull HighlightDisplayKey unusedImportKey) {
|
||||
// jsp include directive hack
|
||||
if (importStatement instanceof JspxImportStatement && ((JspxImportStatement)importStatement).isForeignFileImport()) return null;
|
||||
if (importStatement.isForeignFileImport()) return null;
|
||||
|
||||
if (PsiUtilCore.hasErrorElementChild(importStatement)) return null;
|
||||
|
||||
@@ -799,43 +804,12 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass
|
||||
HighlightInfo.newHighlightInfo(JavaHighlightInfoTypes.UNUSED_IMPORT).range(importStatement).descriptionAndTooltip(description)
|
||||
.create();
|
||||
|
||||
QuickFixAction.registerQuickFixAction(info, new OptimizeImportsFix(), unusedImportKey);
|
||||
QuickFixAction.registerQuickFixAction(info, new EnableOptimizeImportsOnTheFlyFix(), unusedImportKey);
|
||||
QuickFixAction.registerQuickFixAction(info, QuickFixFactory.getInstance().createOptimizeImportsFix(), unusedImportKey);
|
||||
QuickFixAction.registerQuickFixAction(info, QuickFixFactory.getInstance().createEnableOptimizeImportsOnTheFlyFix(), unusedImportKey);
|
||||
myHasRedundantImports = true;
|
||||
return info;
|
||||
}
|
||||
|
||||
private boolean timeToOptimizeImports() {
|
||||
if (!CodeInsightSettings.getInstance().OPTIMIZE_IMPORTS_ON_THE_FLY) return false;
|
||||
|
||||
DaemonCodeAnalyzerEx codeAnalyzer = DaemonCodeAnalyzerEx.getInstanceEx(myProject);
|
||||
PsiFile file = PsiDocumentManager.getInstance(myProject).getPsiFile(myDocument);
|
||||
// dont optimize out imports in JSP since it can be included in other JSP
|
||||
if (file == null || !codeAnalyzer.isHighlightingAvailable(file) || !(file instanceof PsiJavaFile) || file instanceof ServerPageFile) return false;
|
||||
|
||||
if (!codeAnalyzer.isErrorAnalyzingFinished(file)) return false;
|
||||
boolean errors = containsErrorsPreventingOptimize(file);
|
||||
|
||||
return !errors && DaemonListeners.canChangeFileSilently(myFile);
|
||||
}
|
||||
|
||||
private boolean containsErrorsPreventingOptimize(@NotNull PsiFile file) {
|
||||
// ignore unresolved imports errors
|
||||
PsiImportList importList = ((PsiJavaFile)file).getImportList();
|
||||
final TextRange importsRange = importList == null ? TextRange.EMPTY_RANGE : importList.getTextRange();
|
||||
boolean hasErrorsExceptUnresolvedImports = !DaemonCodeAnalyzerEx
|
||||
.processHighlights(myDocument, myProject, HighlightSeverity.ERROR, 0, myDocument.getTextLength(), new Processor<HighlightInfo>() {
|
||||
@Override
|
||||
public boolean process(HighlightInfo error) {
|
||||
int infoStart = error.getActualStartOffset();
|
||||
int infoEnd = error.getActualEndOffset();
|
||||
|
||||
return importsRange.containsRange(infoStart, infoEnd) && error.type.equals(HighlightInfoType.WRONG_REF);
|
||||
}
|
||||
});
|
||||
|
||||
return hasErrorsExceptUnresolvedImports;
|
||||
}
|
||||
|
||||
private static boolean isIntentionalPrivateConstructor(@NotNull PsiMethod method, PsiClass containingClass) {
|
||||
return method.isConstructor() &&
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.daemon.HighlightDisplayKey;
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class UnusedSymbolLocalInspectionBase extends AbstractBaseJavaLocalInspectionTool implements CustomSuppressableInspectionTool {
|
||||
@NonNls public static final String SHORT_NAME = HighlightInfoType.UNUSED_SYMBOL_SHORT_NAME;
|
||||
@NonNls public static final String DISPLAY_NAME = HighlightInfoType.UNUSED_SYMBOL_DISPLAY_NAME;
|
||||
@NonNls public static final String UNUSED_PARAMETERS_SHORT_NAME = "UnusedParameters";
|
||||
|
||||
public boolean LOCAL_VARIABLE = true;
|
||||
public boolean FIELD = true;
|
||||
public boolean METHOD = true;
|
||||
public boolean CLASS = true;
|
||||
public boolean PARAMETER = true;
|
||||
public boolean REPORT_PARAMETER_FOR_PUBLIC_METHODS = true;
|
||||
|
||||
@Override
|
||||
public boolean isSuppressedFor(@NotNull PsiElement element) {
|
||||
return isSuppressedFor(element, this);
|
||||
}
|
||||
public static boolean isSuppressedFor(@NotNull PsiElement element, @NotNull LocalInspectionTool tool) {
|
||||
return BaseJavaBatchLocalInspectionTool.isSuppressedFor(element, tool);
|
||||
}
|
||||
@Override
|
||||
public SuppressIntentionAction[] getSuppressActions(final PsiElement element) {
|
||||
String shortName = getShortName();
|
||||
HighlightDisplayKey key = HighlightDisplayKey.find(shortName);
|
||||
if (key == null) {
|
||||
throw new AssertionError("HighlightDisplayKey.find(" + shortName + ") is null. Inspection: "+getClass());
|
||||
}
|
||||
SuppressQuickFix[] batchSuppressActions = BatchSuppressManager.SERVICE.getInstance().createBatchSuppressActions(key);
|
||||
return SuppressIntentionActionFromFix.convertBatchToSuppressIntentionActions(batchSuppressActions);
|
||||
}
|
||||
}
|
||||
+28
-16
@@ -19,18 +19,22 @@ import com.intellij.codeHighlighting.MainHighlightingPassFactory;
|
||||
import com.intellij.codeHighlighting.Pass;
|
||||
import com.intellij.codeHighlighting.TextEditorHighlightingPass;
|
||||
import com.intellij.codeHighlighting.TextEditorHighlightingPassRegistrar;
|
||||
import com.intellij.codeInsight.daemon.ProblemHighlightFilter;
|
||||
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.HighlightVisitorImpl;
|
||||
import com.intellij.codeInspection.InspectionProfile;
|
||||
import com.intellij.codeInspection.unusedImport.UnusedImportLocalInspection;
|
||||
import com.intellij.openapi.components.AbstractProjectComponent;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
|
||||
import com.intellij.psi.JspPsiUtil;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.intellij.psi.jsp.JspFile;
|
||||
import com.intellij.psi.jsp.JspSpiUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -42,7 +46,7 @@ import java.util.Arrays;
|
||||
*/
|
||||
public class PostHighlightingPassFactory extends AbstractProjectComponent implements MainHighlightingPassFactory {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.PostHighlightingPassFactory");
|
||||
private static final Key<Long> LAST_POST_PASS_TIMESTAMP = Key.create("LAST_POST_PASS_TIMESTAMP");
|
||||
|
||||
public PostHighlightingPassFactory(Project project, TextEditorHighlightingPassRegistrar highlightingPassRegistrar, HighlightVisitorImpl hvi) {
|
||||
super(project);
|
||||
highlightingPassRegistrar.registerTextEditorHighlightingPass(this, new int[]{Pass.UPDATE_ALL,}, null, true, Pass.POST_UPDATE_ALL);
|
||||
@@ -65,26 +69,34 @@ public class PostHighlightingPassFactory extends AbstractProjectComponent implem
|
||||
@Nullable
|
||||
public TextEditorHighlightingPass createHighlightingPass(@NotNull PsiFile file, @NotNull final Editor editor) {
|
||||
TextRange textRange = FileStatusMap.getDirtyTextRange(editor, Pass.UPDATE_ALL);
|
||||
if (textRange == null) {
|
||||
Long lastStamp = file.getUserData(LAST_POST_PASS_TIMESTAMP);
|
||||
long currentStamp = PsiModificationTracker.SERVICE.getInstance(myProject).getModificationCount();
|
||||
if (lastStamp != null && lastStamp == currentStamp || !ProblemHighlightFilter.shouldHighlightFile(file)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (textRange == null && PostHighlightingPass.isUpToDate(file)) return null;
|
||||
|
||||
return new PostHighlightingPass(myProject, file, editor, editor.getDocument(), new DefaultHighlightInfoProcessor());
|
||||
return create(file, editor.getDocument(), editor, new DefaultHighlightInfoProcessor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextEditorHighlightingPass createMainHighlightingPass(@NotNull PsiFile file,
|
||||
@NotNull Document document,
|
||||
@NotNull HighlightInfoProcessor highlightInfoProcessor) {
|
||||
return new PostHighlightingPass(myProject, file, null, document, highlightInfoProcessor);
|
||||
return create(file, document, null, highlightInfoProcessor);
|
||||
}
|
||||
|
||||
public static void markFileUpToDate(@NotNull PsiFile file) {
|
||||
long lastStamp = PsiModificationTracker.SERVICE.getInstance(file.getProject()).getModificationCount();
|
||||
file.putUserData(LAST_POST_PASS_TIMESTAMP, lastStamp);
|
||||
private PostHighlightingPass create(@NotNull PsiFile file,
|
||||
@NotNull Document document, Editor editor,
|
||||
@NotNull HighlightInfoProcessor highlightInfoProcessor) {
|
||||
HighlightDisplayKey unusedImportKey = HighlightDisplayKey.find(UnusedImportLocalInspection.SHORT_NAME);
|
||||
return new PostHighlightingPass(myProject, file, editor, document, highlightInfoProcessor, isUnusedImportEnabled(unusedImportKey, file));
|
||||
}
|
||||
|
||||
private static boolean isUnusedImportEnabled(HighlightDisplayKey unusedImportKey, @NotNull PsiFile file) {
|
||||
InspectionProfile profile = InspectionProjectProfileManager.getInstance(file.getProject()).getInspectionProfile();
|
||||
boolean unusedImportEnabled = profile.isToolEnabled(unusedImportKey, file);
|
||||
if (unusedImportEnabled && JspPsiUtil.isInJspFile(file)) {
|
||||
final JspFile jspFile = JspPsiUtil.getJspFile(file);
|
||||
if (jspFile != null) {
|
||||
unusedImportEnabled = !JspSpiUtil.isIncludedOrIncludesSomething(jspFile);
|
||||
}
|
||||
}
|
||||
return unusedImportEnabled;
|
||||
}
|
||||
}
|
||||
|
||||
+204
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 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.
|
||||
@@ -15,30 +15,60 @@
|
||||
*/
|
||||
package com.intellij.codeInsight.intention.impl.config;
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightSettings;
|
||||
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
|
||||
import com.intellij.codeInsight.daemon.QuickFixActionRegistrar;
|
||||
import com.intellij.codeInsight.daemon.QuickFixBundle;
|
||||
import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerEx;
|
||||
import com.intellij.codeInsight.daemon.impl.DaemonListeners;
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.IncreaseLanguageLevelFix;
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.ReplacePrimitiveWithBoxedTypeAction;
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.*;
|
||||
import com.intellij.codeInsight.daemon.quickFix.CreateClassOrPackageFix;
|
||||
import com.intellij.codeInsight.daemon.quickFix.CreateFieldOrPropertyFix;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.codeInsight.intention.IntentionManager;
|
||||
import com.intellij.codeInsight.intention.QuickFixFactory;
|
||||
import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement;
|
||||
import com.intellij.codeInspection.LocalQuickFixOnPsiElement;
|
||||
import com.intellij.codeInspection.*;
|
||||
import com.intellij.codeInspection.ex.EntryPointsManagerBase;
|
||||
import com.intellij.codeInspection.unusedParameters.UnusedParametersInspection;
|
||||
import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection;
|
||||
import com.intellij.codeInspection.util.SpecialAnnotationsUtil;
|
||||
import com.intellij.diagnostic.AttachmentFactory;
|
||||
import com.intellij.diagnostic.LogMessageEx;
|
||||
import com.intellij.lang.annotation.HighlightSeverity;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.command.undo.UndoManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.PropertyMemberType;
|
||||
import com.intellij.psi.util.ClassKind;
|
||||
import com.intellij.psi.util.PropertyMemberType;
|
||||
import com.intellij.refactoring.changeSignature.ChangeSignatureGestureDetector;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.Processor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author cdr
|
||||
*/
|
||||
public class QuickFixFactoryImpl extends QuickFixFactory {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.intention.impl.config.QuickFixFactoryImpl");
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public LocalQuickFixAndIntentionActionOnPsiElement createModifierListFix(@NotNull PsiModifierList modifierList,
|
||||
@@ -561,9 +591,177 @@ public class QuickFixFactoryImpl extends QuickFixFactory {
|
||||
PullAsAbstractUpFix.registerQuickFix(method, registrar);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public IntentionAction createCreateAnnotationMethodFromUsageFix(PsiNameValuePair pair) {
|
||||
public IntentionAction createCreateAnnotationMethodFromUsageFix(@NotNull PsiNameValuePair pair) {
|
||||
return new CreateAnnotationMethodFromUsageFix(pair);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public IntentionAction createOptimizeImportsFix() {
|
||||
final OptimizeImportsFix fix = new OptimizeImportsFix();
|
||||
|
||||
return new IntentionAction() {
|
||||
@NotNull
|
||||
@Override
|
||||
public String getText() {
|
||||
return fix.getText();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
return fix.getFamilyName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
|
||||
return timeToOptimizeImports(file) && fix.isAvailable(project, editor, file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException {
|
||||
invokeOnTheFlyImportOptimizer(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
fix.invoke(project, editor, file);
|
||||
}
|
||||
}, file, editor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startInWriteAction() {
|
||||
return fix.startInWriteAction();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerFixesForUnusedParameter(@NotNull PsiParameter parameter, @NotNull Object highlightInfo) {
|
||||
Project myProject = parameter.getProject();
|
||||
InspectionProfile profile = InspectionProjectProfileManager.getInstance(myProject).getInspectionProfile();
|
||||
UnusedParametersInspection unusedParametersInspection =
|
||||
(UnusedParametersInspection)profile.getUnwrappedTool(UnusedSymbolLocalInspectionBase.UNUSED_PARAMETERS_SHORT_NAME, parameter);
|
||||
LOG.assertTrue(ApplicationManager.getApplication().isUnitTestMode() || unusedParametersInspection != null);
|
||||
List<IntentionAction> options = new ArrayList<IntentionAction>();
|
||||
HighlightDisplayKey myUnusedSymbolKey = HighlightDisplayKey.find(UnusedSymbolLocalInspection.SHORT_NAME);
|
||||
options.addAll(IntentionManager.getInstance().getStandardIntentionOptions(myUnusedSymbolKey, parameter));
|
||||
if (unusedParametersInspection != null) {
|
||||
SuppressQuickFix[] batchSuppressActions = unusedParametersInspection.getBatchSuppressActions(parameter);
|
||||
Collections.addAll(options, SuppressIntentionActionFromFix.convertBatchToSuppressIntentionActions(batchSuppressActions));
|
||||
}
|
||||
//need suppress from Unused Parameters but settings from Unused Symbol
|
||||
QuickFixAction.registerQuickFixAction((HighlightInfo)highlightInfo, new RemoveUnusedParameterFix(parameter),
|
||||
options, HighlightDisplayKey.getDisplayNameByKey(myUnusedSymbolKey));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public IntentionAction createAddToDependencyInjectionAnnotationsFix(@NotNull Project project,
|
||||
@NotNull String qualifiedName,
|
||||
@NotNull String element) {
|
||||
final EntryPointsManagerBase entryPointsManager = EntryPointsManagerBase.getInstance(project);
|
||||
return SpecialAnnotationsUtil.createAddToSpecialAnnotationsListIntentionAction(
|
||||
QuickFixBundle.message("fix.unused.symbol.injection.text", element, qualifiedName),
|
||||
QuickFixBundle.message("fix.unused.symbol.injection.family"),
|
||||
entryPointsManager.ADDITIONAL_ANNOTATIONS, qualifiedName);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public IntentionAction createCreateGetterOrSetterFix(boolean createGetter, boolean createSetter, @NotNull PsiField field) {
|
||||
return new CreateGetterOrSetterFix(createGetter, createSetter, field);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public IntentionAction createRenameToIgnoredFix(@NotNull PsiNamedElement namedElement) {
|
||||
return new RenameToIgnoredFix(namedElement);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public IntentionAction createEnableOptimizeImportsOnTheFlyFix() {
|
||||
return new EnableOptimizeImportsOnTheFlyFix();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public IntentionAction createSafeDeleteFix(@NotNull PsiElement element) {
|
||||
if (element instanceof PsiMethod) {
|
||||
PsiMethod method = (PsiMethod)element;
|
||||
PsiClass containingClass = method.getContainingClass();
|
||||
if (method.getReturnType() != null || containingClass != null && Comparing.strEqual(containingClass.getName(), method.getName())) {
|
||||
//ignore methods with deleted return types as they are always marked as unused without any reason
|
||||
ChangeSignatureGestureDetector.getInstance(method.getProject()).dismissForElement(method);
|
||||
}
|
||||
}
|
||||
return new SafeDeleteFix(element);
|
||||
}
|
||||
|
||||
public static void invokeOnTheFlyImportOptimizer(@NotNull final Runnable runnable,
|
||||
@NotNull final PsiFile file,
|
||||
@NotNull final Editor editor) {
|
||||
final long stamp = editor.getDocument().getModificationStamp();
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (file.getProject().isDisposed() || editor.isDisposed() || editor.getDocument().getModificationStamp() != stamp) return;
|
||||
//no need to optimize imports on the fly during undo/redo
|
||||
final UndoManager undoManager = UndoManager.getInstance(editor.getProject());
|
||||
if (undoManager.isUndoInProgress() || undoManager.isRedoInProgress()) return;
|
||||
PsiDocumentManager.getInstance(file.getProject()).commitAllDocuments();
|
||||
String beforeText = file.getText();
|
||||
final long oldStamp = editor.getDocument().getModificationStamp();
|
||||
CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ApplicationManager.getApplication().runWriteAction(runnable);
|
||||
}
|
||||
});
|
||||
if (oldStamp != editor.getDocument().getModificationStamp()) {
|
||||
String afterText = file.getText();
|
||||
if (Comparing.strEqual(beforeText, afterText)) {
|
||||
LOG.error(
|
||||
LogMessageEx.createEvent("Import optimizer hasn't optimized any imports", file.getViewProvider().getVirtualFile().getPath(),
|
||||
AttachmentFactory.createAttachment(file.getViewProvider().getVirtualFile())));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static boolean timeToOptimizeImports(@NotNull PsiFile file) {
|
||||
if (!CodeInsightSettings.getInstance().OPTIMIZE_IMPORTS_ON_THE_FLY) return false;
|
||||
|
||||
DaemonCodeAnalyzerEx codeAnalyzer = DaemonCodeAnalyzerEx.getInstanceEx(file.getProject());
|
||||
// dont optimize out imports in JSP since it can be included in other JSP
|
||||
if (file == null || !codeAnalyzer.isHighlightingAvailable(file) || !(file instanceof PsiJavaFile) || file instanceof ServerPageFile) return false;
|
||||
|
||||
if (!codeAnalyzer.isErrorAnalyzingFinished(file)) return false;
|
||||
boolean errors = containsErrorsPreventingOptimize(file);
|
||||
|
||||
return !errors && DaemonListeners.canChangeFileSilently(file);
|
||||
}
|
||||
|
||||
private static boolean containsErrorsPreventingOptimize(@NotNull PsiFile file) {
|
||||
Document document = PsiDocumentManager.getInstance(file.getProject()).getDocument(file);
|
||||
if (document == null) return true;
|
||||
// ignore unresolved imports errors
|
||||
PsiImportList importList = ((PsiJavaFile)file).getImportList();
|
||||
final TextRange importsRange = importList == null ? TextRange.EMPTY_RANGE : importList.getTextRange();
|
||||
boolean hasErrorsExceptUnresolvedImports = !DaemonCodeAnalyzerEx
|
||||
.processHighlights(document, file.getProject(), HighlightSeverity.ERROR, 0, document.getTextLength(), new Processor<HighlightInfo>() {
|
||||
@Override
|
||||
public boolean process(HighlightInfo error) {
|
||||
int infoStart = error.getActualStartOffset();
|
||||
int infoEnd = error.getActualEndOffset();
|
||||
|
||||
return importsRange.containsRange(infoStart, infoEnd) && error.type.equals(HighlightInfoType.WRONG_REF);
|
||||
}
|
||||
});
|
||||
|
||||
return hasErrorsExceptUnresolvedImports;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 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.
|
||||
@@ -43,7 +43,6 @@ import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.refactoring.changeSignature.ChangeSignatureProcessor;
|
||||
import com.intellij.refactoring.changeSignature.ParameterInfoImpl;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -54,8 +53,6 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class UnusedParametersInspection extends GlobalJavaBatchInspectionTool {
|
||||
@NonNls public static final String SHORT_NAME = "UnusedParameters";
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public CommonProblemDescriptor[] checkElement(@NotNull final RefEntity refEntity,
|
||||
@@ -229,7 +226,7 @@ public class UnusedParametersInspection extends GlobalJavaBatchInspectionTool {
|
||||
@Override
|
||||
@NotNull
|
||||
public String getShortName() {
|
||||
return SHORT_NAME;
|
||||
return UnusedSymbolLocalInspectionBase.UNUSED_PARAMETERS_SHORT_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
-32
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 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.
|
||||
@@ -17,20 +17,14 @@
|
||||
package com.intellij.codeInspection.unusedSymbol;
|
||||
|
||||
import com.intellij.codeInsight.daemon.GroupNames;
|
||||
import com.intellij.codeInsight.daemon.QuickFixBundle;
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.codeInspection.BaseJavaLocalInspectionTool;
|
||||
import com.intellij.codeInspection.UnusedSymbolLocalInspectionBase;
|
||||
import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection;
|
||||
import com.intellij.codeInspection.ex.EntryPointsManager;
|
||||
import com.intellij.codeInspection.ex.EntryPointsManagerBase;
|
||||
import com.intellij.codeInspection.ex.PairedUnfairLocalInspectionTool;
|
||||
import com.intellij.codeInspection.util.SpecialAnnotationsUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectUtil;
|
||||
import com.intellij.psi.PsiModifierListOwner;
|
||||
import org.intellij.lang.annotations.Pattern;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -44,18 +38,7 @@ import java.awt.event.ActionListener;
|
||||
* User: anna
|
||||
* Date: 17-Feb-2006
|
||||
*/
|
||||
public class UnusedSymbolLocalInspection extends BaseJavaLocalInspectionTool implements PairedUnfairLocalInspectionTool {
|
||||
@NonNls public static final String SHORT_NAME = HighlightInfoType.UNUSED_SYMBOL_SHORT_NAME;
|
||||
@NonNls public static final String DISPLAY_NAME = HighlightInfoType.UNUSED_SYMBOL_DISPLAY_NAME;
|
||||
|
||||
public boolean LOCAL_VARIABLE = true;
|
||||
public boolean FIELD = true;
|
||||
public boolean METHOD = true;
|
||||
public boolean CLASS = true;
|
||||
public boolean PARAMETER = true;
|
||||
public boolean REPORT_PARAMETER_FOR_PUBLIC_METHODS = true;
|
||||
|
||||
|
||||
public class UnusedSymbolLocalInspection extends UnusedSymbolLocalInspectionBase implements PairedUnfairLocalInspectionTool {
|
||||
@Override
|
||||
@NotNull
|
||||
public String getGroupDisplayName() {
|
||||
@@ -154,16 +137,4 @@ public class UnusedSymbolLocalInspection extends BaseJavaLocalInspectionTool imp
|
||||
public JComponent createOptionsPanel() {
|
||||
return new OptionsPanel().getPanel();
|
||||
}
|
||||
|
||||
public static IntentionAction createQuickFix(@NonNls String qualifiedName, @Nls String element, Project project) {
|
||||
final EntryPointsManagerBase entryPointsManager = EntryPointsManagerBase.getInstance(project);
|
||||
return SpecialAnnotationsUtil.createAddToSpecialAnnotationsListIntentionAction(
|
||||
QuickFixBundle.message("fix.unused.symbol.injection.text", element, qualifiedName),
|
||||
QuickFixBundle.message("fix.unused.symbol.injection.family"),
|
||||
entryPointsManager.ADDITIONAL_ANNOTATIONS, qualifiedName);
|
||||
}
|
||||
|
||||
public static boolean isInjected(final PsiModifierListOwner modifierListOwner) {
|
||||
return EntryPointsManagerBase.getInstance(modifierListOwner.getProject()).isEntryPoint(modifierListOwner);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 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.
|
||||
@@ -61,4 +61,6 @@ public interface PsiImportStatementBase extends PsiElement {
|
||||
*/
|
||||
@Nullable
|
||||
PsiElement resolve();
|
||||
|
||||
boolean isForeignFileImport();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 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.
|
||||
@@ -63,4 +63,9 @@ public abstract class PsiImportStatementBaseImpl extends JavaStubPsiElement<PsiI
|
||||
final PsiJavaCodeReferenceElement reference = getImportReference();
|
||||
return reference == null ? null : reference.resolve();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isForeignFileImport() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 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.
|
||||
@@ -22,6 +22,5 @@ import com.intellij.psi.PsiImportStatement;
|
||||
* @author peter
|
||||
*/
|
||||
public interface JspxImportStatement extends PsiImportStatement {
|
||||
boolean isForeignFileImport();
|
||||
PsiFile getDeclarationFile();
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 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.
|
||||
+49
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 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.
|
||||
@@ -30,16 +30,22 @@ import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.codeInspection.InspectionProfile;
|
||||
import com.intellij.codeInspection.ProblemHighlightType;
|
||||
import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection;
|
||||
import com.intellij.diagnostic.AttachmentFactory;
|
||||
import com.intellij.diagnostic.LogMessageEx;
|
||||
import com.intellij.lang.annotation.Annotation;
|
||||
import com.intellij.lang.annotation.AnnotationHolder;
|
||||
import com.intellij.lang.annotation.AnnotationSession;
|
||||
import com.intellij.lang.annotation.HighlightSeverity;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.command.undo.UndoManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ProjectFileIndex;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
@@ -75,6 +81,8 @@ import java.util.*;
|
||||
* @author ilyas
|
||||
*/
|
||||
public class GroovyPostHighlightingPass extends TextEditorHighlightingPass {
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.plugins.groovy.codeInspection.local.GroovyPostHighlightingPass");
|
||||
|
||||
private final GroovyFile myFile;
|
||||
private final Editor myEditor;
|
||||
private volatile Set<GrImportStatement> myUnusedImports;
|
||||
@@ -133,19 +141,21 @@ public class GroovyPostHighlightingPass extends TextEditorHighlightingPass {
|
||||
|
||||
if (deadCodeEnabled &&
|
||||
element instanceof GrNamedElement && element instanceof PsiModifierListOwner &&
|
||||
!PostHighlightingPass.isImplicitUsage((PsiModifierListOwner)element, progress) &&
|
||||
!PostHighlightingPass.isImplicitUsage(((PsiModifierListOwner)element).getProject(), (PsiModifierListOwner)element, progress) &&
|
||||
!GroovySuppressableInspectionTool.isElementToolSuppressedIn(element, GroovyUnusedDeclarationInspection.SHORT_NAME)) {
|
||||
PsiElement nameId = ((GrNamedElement)element).getNameIdentifierGroovy();
|
||||
if (nameId.getNode().getElementType() == GroovyTokenTypes.mIDENT) {
|
||||
String name = ((GrNamedElement)element).getName();
|
||||
if (element instanceof GrTypeDefinition && !PostHighlightingPass.isClassUsed((GrTypeDefinition)element, progress, usageHelper)) {
|
||||
if (element instanceof GrTypeDefinition && !PostHighlightingPass.isClassUsed(myProject,
|
||||
((GrTypeDefinition)element).getContainingFile(), (GrTypeDefinition)element, progress, usageHelper
|
||||
)) {
|
||||
HighlightInfo highlightInfo = PostHighlightingPass.createUnusedSymbolInfo(nameId, "Class " + name + " is unused", HighlightInfoType.UNUSED_SYMBOL);
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, new SafeDeleteFix(element), unusedDefKey);
|
||||
ContainerUtil.addIfNotNull(unusedDeclarations, highlightInfo);
|
||||
}
|
||||
else if (element instanceof GrMethod) {
|
||||
GrMethod method = (GrMethod)element;
|
||||
if (!PostHighlightingPass.isMethodReferenced(method, progress, usageHelper)) {
|
||||
if (!PostHighlightingPass.isMethodReferenced(method.getProject(), method.getContainingFile(), method, progress, usageHelper)) {
|
||||
String message = (method.isConstructor() ? "Constructor" : "Method") + " " + name + " is unused";
|
||||
HighlightInfo highlightInfo = PostHighlightingPass.createUnusedSymbolInfo(nameId, message, HighlightInfoType.UNUSED_SYMBOL);
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, new SafeDeleteFix(method), unusedDefKey);
|
||||
@@ -222,7 +232,7 @@ public class GroovyPostHighlightingPass extends TextEditorHighlightingPass {
|
||||
}
|
||||
|
||||
private static boolean isFieldUnused(GrField field, ProgressIndicator progress, GlobalUsageHelper usageHelper) {
|
||||
if (!PostHighlightingPass.isFieldUnused(field, progress, usageHelper)) return false;
|
||||
if (!PostHighlightingPass.isFieldUnused(field.getProject(), field.getContainingFile(), field, progress, usageHelper)) return false;
|
||||
final GrAccessorMethod[] getters = field.getGetters();
|
||||
final GrAccessorMethod setter = field.getSetter();
|
||||
|
||||
@@ -300,7 +310,7 @@ public class GroovyPostHighlightingPass extends TextEditorHighlightingPass {
|
||||
|
||||
final Runnable optimize = myOptimizeRunnable;
|
||||
if (optimize != null && timeToOptimizeImports()) {
|
||||
PostHighlightingPass.invokeOnTheFlyImportOptimizer(new Runnable() {
|
||||
invokeOnTheFlyImportOptimizer(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
optimize.run();
|
||||
@@ -309,6 +319,39 @@ public class GroovyPostHighlightingPass extends TextEditorHighlightingPass {
|
||||
}
|
||||
}
|
||||
|
||||
public static void invokeOnTheFlyImportOptimizer(@NotNull final Runnable runnable,
|
||||
@NotNull final PsiFile file,
|
||||
@NotNull final Editor editor) {
|
||||
final long stamp = editor.getDocument().getModificationStamp();
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (file.getProject().isDisposed() || editor.isDisposed() || editor.getDocument().getModificationStamp() != stamp) return;
|
||||
//no need to optimize imports on the fly during undo/redo
|
||||
final UndoManager undoManager = UndoManager.getInstance(editor.getProject());
|
||||
if (undoManager.isUndoInProgress() || undoManager.isRedoInProgress()) return;
|
||||
PsiDocumentManager.getInstance(file.getProject()).commitAllDocuments();
|
||||
String beforeText = file.getText();
|
||||
final long oldStamp = editor.getDocument().getModificationStamp();
|
||||
CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ApplicationManager.getApplication().runWriteAction(runnable);
|
||||
}
|
||||
});
|
||||
if (oldStamp != editor.getDocument().getModificationStamp()) {
|
||||
String afterText = file.getText();
|
||||
if (Comparing.strEqual(beforeText, afterText)) {
|
||||
LOG.error(
|
||||
LogMessageEx.createEvent("Import optimizer hasn't optimized any imports", file.getViewProvider().getVirtualFile().getPath(),
|
||||
AttachmentFactory.createAttachment(file.getViewProvider().getVirtualFile())));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private static TextRange calculateRangeToUse(GrImportStatement unusedImport) {
|
||||
final TextRange range = unusedImport.getTextRange();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user