This commit is contained in:
Alexey Kudravtsev
2016-10-24 15:11:30 +03:00
parent b05aa30957
commit cf5b631d63
6 changed files with 40 additions and 95 deletions
@@ -16,16 +16,14 @@
package com.intellij.codeInspection;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Conditions;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import static com.intellij.openapi.util.Conditions.*;
public abstract class AbstractBaseJavaLocalInspectionTool extends LocalInspectionTool {
private static final Condition<PsiElement> PROBLEM_ELEMENT_CONDITION =
and(instanceOf(PsiFile.class, PsiClass.class, PsiMethod.class, PsiField.class), notInstanceOf(PsiTypeParameter.class));
private static final Condition<PsiElement> PROBLEM_ELEMENT_CONDITION = Conditions.and(Conditions.instanceOf(PsiFile.class, PsiClass.class, PsiMethod.class, PsiField.class), Conditions.notInstanceOf(PsiTypeParameter.class));
/**
* Override this to report problems at method level.
@@ -33,7 +31,7 @@ public abstract class AbstractBaseJavaLocalInspectionTool extends LocalInspectio
* @param method to check.
* @param manager InspectionManager to ask for ProblemDescriptors from.
* @param isOnTheFly true if called during on the fly editor highlighting. Called from Inspect Code action otherwise.
* @return <code>null</code> if no problems found or not applicable at method level.
* @return {@code null} if no problems found or not applicable at method level.
*/
@Nullable
public ProblemDescriptor[] checkMethod(@NotNull PsiMethod method, @NotNull InspectionManager manager, boolean isOnTheFly) {
@@ -46,7 +44,7 @@ public abstract class AbstractBaseJavaLocalInspectionTool extends LocalInspectio
* @param aClass to check.
* @param manager InspectionManager to ask for ProblemDescriptors from.
* @param isOnTheFly true if called during on the fly editor highlighting. Called from Inspect Code action otherwise.
* @return <code>null</code> if no problems found or not applicable at class level.
* @return {@code null} if no problems found or not applicable at class level.
*/
@Nullable
public ProblemDescriptor[] checkClass(@NotNull PsiClass aClass, @NotNull InspectionManager manager, boolean isOnTheFly) {
@@ -59,27 +57,13 @@ public abstract class AbstractBaseJavaLocalInspectionTool extends LocalInspectio
* @param field to check.
* @param manager InspectionManager to ask for ProblemDescriptors from.
* @param isOnTheFly true if called during on the fly editor highlighting. Called from Inspect Code action otherwise.
* @return <code>null</code> if no problems found or not applicable at field level.
* @return {@code null} if no problems found or not applicable at field level.
*/
@Nullable
public ProblemDescriptor[] checkField(@NotNull PsiField field, @NotNull InspectionManager manager, boolean isOnTheFly) {
return null;
}
/**
* Override this to report problems at file level.
*
* @param file to check.
* @param manager InspectionManager to ask for ProblemDescriptors from.
* @param isOnTheFly true if called during on the fly editor highlighting. Called from Inspect Code action otherwise.
* @return <code>null</code> if no problems found or not applicable at file level.
*/
@Override
@Nullable
public ProblemDescriptor[] checkFile(@NotNull PsiFile file, @NotNull InspectionManager manager, boolean isOnTheFly) {
return null;
}
@Override
@NotNull
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
@@ -15,10 +15,8 @@
*/
package com.intellij.codeInspection;
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Base java local inspection which provides batch suppress actions, i.e. actions which don't need UI components to run (e.g. Editor).
@@ -39,8 +39,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -56,23 +54,17 @@ public class UncheckedWarningLocalInspectionBase extends BaseJavaBatchLocalInspe
public boolean IGNORE_UNCHECKED_CAST;
public boolean IGNORE_UNCHECKED_OVERRIDING;
protected static JCheckBox createSetting(final String cbText,
final boolean option,
final Pass<JCheckBox> pass) {
@NotNull
static JCheckBox createSetting(@NotNull String cbText, final boolean option, @NotNull Pass<JCheckBox> pass) {
final JCheckBox uncheckedCb = new JCheckBox(cbText, option);
uncheckedCb.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
pass.pass(uncheckedCb);
}
});
uncheckedCb.addActionListener(e -> pass.pass(uncheckedCb));
return uncheckedCb;
}
public static LocalQuickFix[] getChangeVariableTypeFixes(@NotNull PsiVariable parameter, PsiType itemType, LocalQuickFix[] generifyFixes) {
private static LocalQuickFix[] getChangeVariableTypeFixes(@NotNull PsiVariable parameter, @Nullable PsiType itemType, LocalQuickFix[] generifyFixes) {
if (itemType instanceof PsiMethodReferenceType) return generifyFixes;
final List<LocalQuickFix> result = new ArrayList<>();
LOG.assertTrue(parameter.isValid());
final List<LocalQuickFix> result = new ArrayList<>();
if (itemType != null) {
for (ChangeVariableTypeQuickFixProvider fixProvider : Extensions.getExtensions(ChangeVariableTypeQuickFixProvider.EP_NAME)) {
for (IntentionAction action : fixProvider.getFixes(parameter, itemType)) {
@@ -180,7 +172,7 @@ public class UncheckedWarningLocalInspectionBase extends BaseJavaBatchLocalInspe
@NotNull private final LanguageLevel myLanguageLevel;
private final LocalQuickFix[] myGenerifyFixes;
public UncheckedWarningsVisitor(boolean onTheFly, @NotNull LanguageLevel level) {
UncheckedWarningsVisitor(boolean onTheFly, @NotNull LanguageLevel level) {
myOnTheFly = onTheFly;
myLanguageLevel = level;
myGenerifyFixes = onTheFly ? createFixes() : LocalQuickFix.EMPTY_ARRAY;
@@ -300,8 +292,8 @@ public class UncheckedWarningLocalInspectionBase extends BaseJavaBatchLocalInspe
final PsiExpression iteratedValue = statement.getIteratedValue();
if (iteratedValue == null) return;
final PsiType itemType = JavaGenericsUtil.getCollectionItemType(iteratedValue);
checkRawToGenericsAssignment(parameter, iteratedValue, parameterType, itemType, true, myOnTheFly ? getChangeVariableTypeFixes(parameter, itemType,
myGenerifyFixes) : LocalQuickFix.EMPTY_ARRAY);
LocalQuickFix[] fixes = myOnTheFly ? getChangeVariableTypeFixes(parameter, itemType, myGenerifyFixes) : LocalQuickFix.EMPTY_ARRAY;
checkRawToGenericsAssignment(parameter, iteratedValue, parameterType, itemType, true, fixes);
}
@Override
@@ -155,11 +155,6 @@ public class PsiTreeUtil {
return parents;
}
@Nullable
public static PsiElement findCommonContext(@NotNull PsiElement... elements) {
return findCommonContext(Arrays.asList(elements));
}
@Nullable
public static PsiElement findCommonContext(@NotNull Collection<? extends PsiElement> elements) {
if (elements.isEmpty()) return null;
@@ -386,10 +386,10 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
throw new IncorrectOperationException("Must not start inspections from within global read action");
}
final InspectionManager inspectionManager = InspectionManager.getInstance(getProject());
((RefManagerImpl)getRefManager()).initializeAnnotators();
final List<Tools> globalTools = new ArrayList<>();
final List<Tools> localTools = new ArrayList<>();
final List<Tools> globalSimpleTools = new ArrayList<>();
((RefManagerImpl)getRefManager()).initializeAnnotators();
initializeTools(globalTools, localTools, globalSimpleTools);
appendPairedInspectionsForUnfairTools(globalTools, globalSimpleTools, localTools);
@@ -408,7 +408,6 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
final Map<String, InspectionToolWrapper> map = getInspectionWrappersMap(localTools);
final BlockingQueue<PsiFile> filesToInspect = new ArrayBlockingQueue<>(1000);
final Queue<PsiFile> filesFailedToInspect = new LinkedBlockingQueue<>();
// use original progress indicator here since we don't want it to cancel on write action start
ProgressIndicator iteratingIndicator = new SensitiveProgressWrapper(progressIndicator);
Future<?> future = startIterateScopeInBackground(scope, localScopeFiles, headlessEnvironment, filesToInspect, iteratingIndicator);
@@ -428,6 +427,7 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
return true;
};
try {
final Queue<PsiFile> filesFailedToInspect = new LinkedBlockingQueue<>();
while (true) {
Disposable disposable = Disposer.newDisposable();
ProgressIndicator wrapper = new SensitiveProgressWrapper(progressIndicator);
@@ -548,17 +548,14 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
indicator.checkCanceled();
if (ProjectUtil.isProjectOrWorkspaceFile(file) || !fileIndex.isInContent(file)) return true;
PsiFile psiFile = ApplicationManager.getApplication().runReadAction(new Computable<PsiFile>() {
@Override
public PsiFile compute() {
if (getProject().isDisposed()) throw new ProcessCanceledException();
PsiFile psi = PsiManager.getInstance(getProject()).findFile(file);
Document document = psi == null ? null : shouldProcess(psi, headlessEnvironment, localScopeFiles);
if (document != null) {
return psi;
}
return null;
PsiFile psiFile = ApplicationManager.getApplication().runReadAction((Computable<PsiFile>)() -> {
if (getProject().isDisposed()) throw new ProcessCanceledException();
PsiFile psi = PsiManager.getInstance(getProject()).findFile(file);
Document document = psi == null ? null : shouldProcess(psi, headlessEnvironment, localScopeFiles);
if (document != null) {
return psi;
}
return null;
});
//do not inspect binary files
if (psiFile != null) {
@@ -745,17 +742,6 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
private ProblemDescriptionsProcessor getProblemDescriptionProcessor(@NotNull final GlobalInspectionToolWrapper toolWrapper,
@NotNull final Map<String, InspectionToolWrapper> wrappersMap) {
return new ProblemDescriptionsProcessor() {
@Nullable
@Override
public CommonProblemDescriptor[] getDescriptions(@NotNull RefEntity refEntity) {
return CommonProblemDescriptor.EMPTY_ARRAY;
}
@Override
public void ignoreElement(@NotNull RefEntity refEntity) {
}
@Override
public void addProblemElement(@Nullable RefEntity refEntity, @NotNull CommonProblemDescriptor... commonProblemDescriptors) {
for (CommonProblemDescriptor problemDescriptor : commonProblemDescriptors) {
@@ -787,7 +773,7 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
private static final TripleFunction<LocalInspectionTool,PsiElement,GlobalInspectionContext,RefElement> CONVERT =
(tool, elt, context) -> {
final PsiNamedElement problemElement = PsiTreeUtil.getNonStrictParentOfType(elt, PsiFile.class);
PsiNamedElement problemElement = PsiTreeUtil.getNonStrictParentOfType(elt, PsiFile.class);
RefElement refElement = context.getRefManager().getReference(problemElement);
if (refElement == null && problemElement != null) { // no need to lose collected results
@@ -867,12 +853,13 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
@Nullable final String commandName,
@Nullable final Runnable postRunnable,
final boolean modal) {
Task task = modal ? new Task.Modal(getProject(), "Inspect code...", true) {
String title = "Inspect Code...";
Task task = modal ? new Task.Modal(getProject(), title, true) {
@Override
public void run(@NotNull ProgressIndicator indicator) {
cleanup(scope, profile, postRunnable, commandName);
}
} : new Task.Backgroundable(getProject(), "Inspect code...", true) {
} : new Task.Backgroundable(getProject(), title, true) {
@Override
public void run(@NotNull ProgressIndicator indicator) {
cleanup(scope, profile, postRunnable, commandName);
@@ -888,18 +875,12 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
setCurrentScope(scope);
final int fileCount = scope.getFileCount();
final ProgressIndicator progressIndicator = ProgressManager.getInstance().getProgressIndicator();
final List<LocalInspectionToolWrapper> lTools = new ArrayList<>();
final SearchScope searchScope = scope.toSearchScope();
final TextRange range;
if (searchScope instanceof LocalSearchScope) {
final PsiElement[] elements = ((LocalSearchScope)searchScope).getScope();
range = elements.length == 1 ? ApplicationManager.getApplication().runReadAction(new Computable<TextRange>() {
@Override
public TextRange compute() {
return elements[0].getTextRange();
}
}) : null;
range = elements.length == 1 ? ApplicationManager.getApplication().runReadAction((Computable<TextRange>)elements[0]::getTextRange) : null;
}
else {
range = null;
@@ -908,12 +889,13 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
assert tools != null;
return tools.getTool().getTool() instanceof CleanupLocalInspectionTool;
});
List<ProblemDescriptor> descriptors = new ArrayList<>();
Set<PsiFile> files = new HashSet<>();
boolean includeDoNotShow = includeDoNotShow(profile);
final RefManagerImpl refManager = (RefManagerImpl)getRefManager();
refManager.inspectionReadActionStarted();
List<ProblemDescriptor> descriptors = new ArrayList<>();
Set<PsiFile> files = new HashSet<>();
try {
final List<LocalInspectionToolWrapper> lTools = new ArrayList<>();
scope.accept(new PsiElementVisitor() {
private int myCount;
@Override
@@ -54,16 +54,13 @@ public class TextOccurrencesUtil {
}
private static boolean processStringLiteralsContainingIdentifier(@NotNull String identifier, @NotNull SearchScope searchScope, PsiSearchHelper helper, final Processor<PsiElement> processor) {
TextOccurenceProcessor occurenceProcessor = new TextOccurenceProcessor() {
@Override
public boolean execute(@NotNull PsiElement element, int offsetInElement) {
final ParserDefinition definition = LanguageParserDefinitions.INSTANCE.forLanguage(element.getLanguage());
final ASTNode node = element.getNode();
if (definition != null && node != null && definition.getStringLiteralElements().contains(node.getElementType())) {
return processor.process(element);
}
return true;
TextOccurenceProcessor occurenceProcessor = (element, offsetInElement) -> {
final ParserDefinition definition = LanguageParserDefinitions.INSTANCE.forLanguage(element.getLanguage());
final ASTNode node = element.getNode();
if (definition != null && node != null && definition.getStringLiteralElements().contains(node.getElementType())) {
return processor.process(element);
}
return true;
};
return helper.processElementsWithWord(occurenceProcessor,
@@ -159,13 +156,10 @@ public class TextOccurrencesUtil {
private static UsageInfoFactory createUsageInfoFactory(final PsiElement element,
final String newQName) {
return new UsageInfoFactory() {
@Override
public UsageInfo createUsageInfo(@NotNull PsiElement usage, int startOffset, int endOffset) {
int start = usage.getTextRange().getStartOffset();
return NonCodeUsageInfo.create(usage.getContainingFile(), start + startOffset, start + endOffset, element,
newQName);
}
return (usage, startOffset, endOffset) -> {
int start = usage.getTextRange().getStartOffset();
return NonCodeUsageInfo.create(usage.getContainingFile(), start + startOffset, start + endOffset, element,
newQName);
};
}
}