Merge remote-tracking branch 'origin/master'

This commit is contained in:
Dmitry Trofimov
2014-06-18 11:15:33 +02:00
57 changed files with 967 additions and 541 deletions
@@ -262,4 +262,7 @@ public abstract class QuickFixFactory {
@NotNull Collection<String> missedElements);
@NotNull
public abstract IntentionAction createSurroundWithQuotesAnnotationParameterValueFix(@NotNull PsiAnnotationMemberValue value, @NotNull PsiType expectedType);
@NotNull
public abstract IntentionAction addMethodQualifierFix(@NotNull PsiMethodCallExpression methodCall);
}
@@ -26,18 +26,8 @@ import org.jetbrains.annotations.Nullable;
* - work with PSI or document only and
* - don't provide {@link com.intellij.codeInsight.intention.IntentionAction} for quick fixes/suppression, making do with {@link LocalQuickFix} only.
*/
public abstract class BaseJavaBatchLocalInspectionTool extends AbstractBaseJavaLocalInspectionTool implements BatchSuppressableTool {
@NotNull
@Override
public SuppressQuickFix[] getBatchSuppressActions(@Nullable PsiElement element) {
return BatchSuppressManager.SERVICE.getInstance().createBatchSuppressActions(HighlightDisplayKey.find(getShortName()));
}
@Override
public boolean isSuppressedFor(@NotNull PsiElement element) {
return isSuppressedFor(element, this);
}
public abstract class BaseJavaBatchLocalInspectionTool extends AbstractBaseJavaLocalInspectionTool {
@Deprecated
public static boolean isSuppressedFor(@NotNull PsiElement element, @NotNull LocalInspectionTool tool) {
BatchSuppressManager manager = BatchSuppressManager.SERVICE.getInstance();
String alternativeId;
@@ -42,11 +42,7 @@ public abstract class BaseJavaLocalInspectionTool extends AbstractBaseJavaLocalI
return SuppressManager.getInstance().createSuppressActions(key);
}
@Override
public boolean isSuppressedFor(@NotNull PsiElement element) {
return isSuppressedFor(element, this);
}
@Deprecated
public static boolean isSuppressedFor(@NotNull PsiElement element, @NotNull LocalInspectionTool tool) {
return BaseJavaBatchLocalInspectionTool.isSuppressedFor(element, tool);
}
@@ -26,7 +26,7 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class GlobalJavaBatchInspectionTool extends GlobalInspectionTool implements BatchSuppressableTool {
public abstract class GlobalJavaBatchInspectionTool extends GlobalInspectionTool {
@Override
public boolean queryExternalUsagesRequests(@NotNull final InspectionManager manager,
@NotNull final GlobalInspectionContext globalContext,
@@ -38,14 +38,4 @@ public abstract class GlobalJavaBatchInspectionTool extends GlobalInspectionTool
return false;
}
@NotNull
@Override
public SuppressQuickFix[] getBatchSuppressActions(@Nullable PsiElement element) {
return BatchSuppressManager.SERVICE.getInstance().createBatchSuppressActions(HighlightDisplayKey.find(getShortName()));
}
@Override
public boolean isSuppressedFor(@NotNull final PsiElement element) {
return BatchSuppressManager.SERVICE.getInstance().isSuppressedFor(element, getShortName());
}
}
@@ -26,7 +26,7 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class GlobalJavaInspectionTool extends GlobalInspectionTool implements CustomSuppressableInspectionTool {
public abstract class GlobalJavaInspectionTool extends GlobalInspectionTool {
@Override
public boolean queryExternalUsagesRequests(@NotNull final InspectionManager manager,
@NotNull final GlobalInspectionContext globalContext,
@@ -38,10 +38,10 @@ public abstract class GlobalJavaInspectionTool extends GlobalInspectionTool impl
return false;
}
@NotNull
@Override
@Nullable
public SuppressIntentionAction[] getSuppressActions(final PsiElement element) {
return SuppressManager.getInstance().createSuppressActions(HighlightDisplayKey.find(getShortName()));
public SuppressQuickFix[] getBatchSuppressActions(@Nullable PsiElement element) {
return BatchSuppressManager.SERVICE.getInstance().createBatchSuppressActions(HighlightDisplayKey.find(getShortName()));
}
@Override
@@ -670,6 +670,7 @@ public class HighlightMethodUtil {
registerChangeParameterClassFix(methodCall, list, highlightInfo);
if (methodCandidates.length == 0) {
QuickFixAction.registerQuickFixAction(highlightInfo, fixRange, QUICK_FIX_FACTORY.createStaticImportMethodFix(methodCall));
QuickFixAction.registerQuickFixAction(highlightInfo, fixRange, QUICK_FIX_FACTORY.addMethodQualifierFix(methodCall));
}
for (IntentionAction action : QUICK_FIX_FACTORY.getVariableTypeFromCallFixes(methodCall, list)) {
QuickFixAction.registerQuickFixAction(highlightInfo, fixRange, action);
@@ -602,4 +602,10 @@ public class EmptyQuickFixFactory extends QuickFixFactory {
@NotNull PsiType expectedType) {
return QuickFixes.EMPTY_FIX;
}
@NotNull
@Override
public IntentionAction addMethodQualifierFix(@NotNull PsiMethodCallExpression methodCall) {
return QuickFixes.EMPTY_FIX;
}
}
@@ -583,7 +583,14 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
if (dfaLeft instanceof DfaVariableValue) {
DfaVariableValue dfaVar = (DfaVariableValue)dfaLeft;
if (isUnknownState(dfaVar)) return true;
if (!dfaRelation.isInstanceOf()) {
if (((DfaTypeValue)dfaRight).isNotNull() && isNull(dfaVar)) {
return isNegated;
}
return true;
}
if (isNegated) {
DfaVariableState newState = getVariableState(dfaVar).withNotInstanceofValue((DfaTypeValue)dfaRight);
if (newState != null) {
@@ -52,7 +52,6 @@ public class DfaRelationValue extends DfaValue {
}
public DfaRelationValue createRelation(DfaValue dfaLeft, DfaValue dfaRight, IElementType relation, boolean negated) {
if (dfaRight instanceof DfaTypeValue && INSTANCEOF_KEYWORD != relation) return null;
if (PLUS == relation) return null;
if (dfaLeft instanceof DfaVariableValue || dfaLeft instanceof DfaBoxedValue || dfaLeft instanceof DfaUnboxedValue
@@ -169,6 +168,10 @@ public class DfaRelationValue extends DfaValue {
return myRelation == EQEQ && myIsNegated || myRelation == GT && !myIsNegated || myRelation == GE && myIsNegated;
}
public boolean isInstanceOf() {
return myRelation == INSTANCEOF_KEYWORD;
}
@NonNls public String toString() {
return (isNegated() ? "not " : "") + myLeftOperand + " " + myRelation + " " + myRightOperand;
}
@@ -15,14 +15,11 @@
*/
package com.intellij.codeInspection.unusedSymbol;
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
import com.intellij.codeInspection.*;
import com.intellij.psi.PsiElement;
import com.intellij.codeInspection.BaseJavaLocalInspectionTool;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
public class UnusedSymbolLocalInspectionBase extends AbstractBaseJavaLocalInspectionTool implements CustomSuppressableInspectionTool {
public class UnusedSymbolLocalInspectionBase extends BaseJavaLocalInspectionTool {
@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";
@@ -33,22 +30,4 @@ public class UnusedSymbolLocalInspectionBase extends AbstractBaseJavaLocalInspec
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);
}
}
@@ -0,0 +1,162 @@
/*
* 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.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.PopupStep;
import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
import com.intellij.psi.*;
import com.intellij.ui.popup.list.ListPopupImpl;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.ObjectUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.TestOnly;
import javax.swing.*;
import java.util.ArrayList;
import java.util.List;
/**
* @author Dmitry Batkovich
*/
public class AddMethodQualifierFix implements IntentionAction {
private static final boolean UNIT_TEST_MODE = ApplicationManager.getApplication().isUnitTestMode();
private final SmartPsiElementPointer<PsiMethodCallExpression> myMethodCall;
private List<PsiVariable> myCandidates = null;
public AddMethodQualifierFix(final PsiMethodCallExpression methodCallExpression) {
myMethodCall = SmartPointerManager.getInstance(methodCallExpression.getProject()).createSmartPsiElementPointer(methodCallExpression);
}
@NotNull
@Override
public String getText() {
String text = QuickFixBundle.message("add.method.qualifier.fix.text", myCandidates.size() > 1 ? "" : myCandidates.get(0).getName());
if (myCandidates.size() > 1) {
text += "...";
}
return text;
}
@NotNull
@Override
public String getFamilyName() {
return getText();
}
@Override
public boolean isAvailable(@NotNull final Project project, final Editor editor, final PsiFile file) {
final PsiMethodCallExpression element = myMethodCall.getElement();
if (element == null || !element.isValid()) {
return false;
}
if (myCandidates == null) {
findCandidates();
}
return myCandidates.size() != 0;
}
private void findCandidates() {
myCandidates = new ArrayList<PsiVariable>();
final PsiMethodCallExpression methodCallElement = myMethodCall.getElement();
final String methodName = methodCallElement.getMethodExpression().getReferenceName();
if (methodName == null) {
return;
}
for (final PsiVariable var : CreateFromUsageUtils.guessMatchingVariables(methodCallElement)) {
final PsiType type = var.getType();
if (!(type instanceof PsiClassType)) {
continue;
}
final PsiClass resolvedClass = ((PsiClassType)type).resolve();
if (resolvedClass == null) {
continue;
}
if (resolvedClass.findMethodsByName(methodName, true).length > 0) {
myCandidates.add(var);
}
}
}
@TestOnly
public List<PsiVariable> getCandidates() {
return myCandidates;
}
@Override
public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException {
if (myCandidates.size() == 1 || UNIT_TEST_MODE) {
qualify(myCandidates.get(0), editor);
}
else {
chooseAndQualify(editor);
}
}
private void chooseAndQualify(final Editor editor) {
final BaseListPopupStep<PsiVariable> step =
new BaseListPopupStep<PsiVariable>(QuickFixBundle.message("add.qualifier"), myCandidates) {
@Override
public PopupStep onChosen(final PsiVariable selectedValue, final boolean finalChoice) {
if (selectedValue != null && finalChoice) {
WriteCommandAction.runWriteCommandAction(selectedValue.getProject(), new Runnable() {
@Override
public void run() {
qualify(selectedValue, editor);
}
});
}
return FINAL_CHOICE;
}
@NotNull
@Override
public String getTextFor(final PsiVariable value) {
return ObjectUtils.assertNotNull(value.getName());
}
@Override
public Icon getIconFor(final PsiVariable aValue) {
return aValue.getIcon(0);
}
};
final ListPopupImpl popup = new ListPopupImpl(step);
popup.showInBestPositionFor(editor);
}
private void qualify(final PsiVariable qualifier, final Editor editor) {
final String qualifierPresentableText = qualifier.getName();
final PsiMethodCallExpression oldExpression = myMethodCall.getElement();
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(qualifier.getProject());
final PsiExpression expression = elementFactory
.createExpressionFromText(qualifierPresentableText + "." + oldExpression.getMethodExpression().getReferenceName() + "()", null);
final PsiElement replacedExpression = oldExpression.replace(expression);
editor.getCaretModel().moveToOffset(replacedExpression.getTextOffset() + replacedExpression.getTextLength());
}
@Override
public boolean startInWriteAction() {
return true;
}
}
@@ -762,6 +762,12 @@ public class QuickFixFactoryImpl extends QuickFixFactory {
return new SurroundWithQuotesAnnotationParameterValueFix(value, expectedType);
}
@NotNull
@Override
public IntentionAction addMethodQualifierFix(@NotNull PsiMethodCallExpression methodCall) {
return new AddMethodQualifierFix(methodCall);
}
private static boolean timeToOptimizeImports(@NotNull PsiFile file) {
if (!CodeInsightSettings.getInstance().OPTIMIZE_IMPORTS_ON_THE_FLY) return false;
@@ -0,0 +1,56 @@
/*
* 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.psi.codeStyle.arrangement;
import com.intellij.psi.PsiField;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class FieldDependenciesManager {
private final Map<PsiField, Set<PsiField>> myFieldDependencies;
private final Map<PsiField, ArrangementEntryDependencyInfo> myFieldInfosMap = ContainerUtil.newHashMap();
public FieldDependenciesManager(@NotNull Map<PsiField, Set<PsiField>> fieldDependencies, @NotNull Map<PsiField, JavaElementArrangementEntry> fields) {
myFieldDependencies = fieldDependencies;
for (PsiField field : fields.keySet()) {
JavaElementArrangementEntry entry = fields.get(field);
myFieldInfosMap.put(field, new ArrangementEntryDependencyInfo(entry));
}
}
@NotNull
public List<ArrangementEntryDependencyInfo> getRoots() {
List<ArrangementEntryDependencyInfo> list = ContainerUtil.newArrayList();
for (Map.Entry<PsiField, Set<PsiField>> entry : myFieldDependencies.entrySet()) {
ArrangementEntryDependencyInfo currentInfo = myFieldInfosMap.get(entry.getKey());
for (PsiField usedInInitialization : entry.getValue()) {
ArrangementEntryDependencyInfo fieldInfo = myFieldInfosMap.get(usedInInitialization);
if (fieldInfo != null)
currentInfo.addDependentEntryInfo(fieldInfo);
}
list.add(currentInfo);
}
return list;
}
}
@@ -27,8 +27,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.HashMap;
import java.util.HashSet;
/**
* @author Denis Zhdanov
@@ -36,28 +34,22 @@ import java.util.HashSet;
*/
public class JavaArrangementParseInfo {
@NotNull private final List<JavaElementArrangementEntry> myEntries = new ArrayList<JavaElementArrangementEntry>();
private final List<JavaElementArrangementEntry> myEntries = new ArrayList<JavaElementArrangementEntry>();
@NotNull private final Map<Pair<String/* property name */, String/* class name */>, JavaArrangementPropertyInfo> myProperties
= new HashMap<Pair<String, String>, JavaArrangementPropertyInfo>();
private final Map<Pair<String/* property name */, String/* class name */>, JavaArrangementPropertyInfo> myProperties = new HashMap<Pair<String, String>, JavaArrangementPropertyInfo>();
@NotNull private final List<ArrangementEntryDependencyInfo> myMethodDependencyRoots
= new ArrayList<ArrangementEntryDependencyInfo>();
private final List<ArrangementEntryDependencyInfo> myMethodDependencyRoots = new ArrayList<ArrangementEntryDependencyInfo>();
private final Map<PsiMethod /* anchor */, Set<PsiMethod /* dependencies */>> myMethodDependencies = new HashMap<PsiMethod, Set<PsiMethod>>();
@NotNull private final Map<PsiMethod /* anchor */, Set<PsiMethod /* dependencies */>> myMethodDependencies
= new HashMap<PsiMethod, Set<PsiMethod>>();
private final Map<PsiMethod, JavaElementArrangementEntry> myMethodEntriesMap = new HashMap<PsiMethod, JavaElementArrangementEntry>();
private final Map<PsiClass, List<Pair<PsiMethod/*overridden*/, PsiMethod/*overriding*/>>> myOverriddenMethods = new LinkedHashMap<PsiClass, List<Pair<PsiMethod, PsiMethod>>>();
@NotNull private final Map<PsiMethod, JavaElementArrangementEntry> myMethodEntriesMap =
new HashMap<PsiMethod, JavaElementArrangementEntry>();
@NotNull private final Map<PsiClass, List<Pair<PsiMethod/*overridden*/, PsiMethod/*overriding*/>>> myOverriddenMethods
= new LinkedHashMap<PsiClass, List<Pair<PsiMethod, PsiMethod>>>();
@NotNull private final Set<PsiMethod> myTmpMethodDependencyRoots = new LinkedHashSet<PsiMethod>();
@NotNull private final Set<PsiMethod> myDependentMethods = new HashSet<PsiMethod>();
private final Set<PsiMethod> myTmpMethodDependencyRoots = new LinkedHashSet<PsiMethod>();
private final Set<PsiMethod> myDependentMethods = new HashSet<PsiMethod>();
private boolean myRebuildMethodDependencies;
@NotNull private FieldDependenciesManager myFieldDependenciesManager = new FieldDependenciesManager();
private final HashMap<PsiField, JavaElementArrangementEntry> myFields = ContainerUtil.newLinkedHashMap();
private final Map<PsiField, Set<PsiField>> myFieldDependencies = ContainerUtil.newHashMap();
@NotNull
public List<JavaElementArrangementEntry> getEntries() {
@@ -96,8 +88,7 @@ public class JavaArrangementParseInfo {
@Nullable
private ArrangementEntryDependencyInfo buildMethodDependencyInfo(@NotNull final PsiMethod method,
@NotNull Map<PsiMethod, ArrangementEntryDependencyInfo> cache)
{
@NotNull Map<PsiMethod, ArrangementEntryDependencyInfo> cache) {
JavaElementArrangementEntry entry = myMethodEntriesMap.get(method);
if (entry == null) {
return null;
@@ -158,7 +149,7 @@ public class JavaArrangementParseInfo {
}
public void onFieldEntryCreated(@NotNull PsiField field, @NotNull JavaElementArrangementEntry entry) {
myFieldDependenciesManager.registerFieldAndEntry(field, entry);
myFields.put(field, entry);
}
public void onOverriddenMethod(@NotNull PsiMethod baseMethod, @NotNull PsiMethod overridingMethod) {
@@ -201,7 +192,7 @@ public class JavaArrangementParseInfo {
result.add(info);
}
}
return result;
}
@@ -226,49 +217,16 @@ public class JavaArrangementParseInfo {
}
public void registerFieldInitializationDependency(@NotNull PsiField fieldToInitialize, @NotNull PsiField usedInInitialization) {
myFieldDependenciesManager.registerInitializationDependency(fieldToInitialize, usedInInitialization);
Set<PsiField> fields = myFieldDependencies.get(fieldToInitialize);
if (fields == null) {
fields = ContainerUtil.newHashSet();
myFieldDependencies.put(fieldToInitialize, fields);
}
fields.add(usedInInitialization);
}
@NotNull
public List<ArrangementEntryDependencyInfo> getFieldDependencyRoots() {
return myFieldDependenciesManager.getRoots();
}
private static class FieldDependenciesManager {
private final Map<PsiField, Set<PsiField>> myFieldDependencies = ContainerUtil.newHashMap();
private final Map<PsiField, ArrangementEntryDependencyInfo> myFieldInfosMap = ContainerUtil.newHashMap();
public void registerFieldAndEntry(@NotNull PsiField field, @NotNull JavaElementArrangementEntry entry) {
myFieldInfosMap.put(field, new ArrangementEntryDependencyInfo(entry));
}
public void registerInitializationDependency(@NotNull PsiField fieldToInitialize, @NotNull PsiField usedInInitialization) {
Set<PsiField> fields = myFieldDependencies.get(fieldToInitialize);
if (fields == null) {
fields = new HashSet<PsiField>();
myFieldDependencies.put(fieldToInitialize, fields);
}
fields.add(usedInInitialization);
}
@NotNull
public List<ArrangementEntryDependencyInfo> getRoots() {
List<ArrangementEntryDependencyInfo> list = ContainerUtil.newArrayList();
for (Map.Entry<PsiField, Set<PsiField>> entry : myFieldDependencies.entrySet()) {
ArrangementEntryDependencyInfo currentInfo = myFieldInfosMap.get(entry.getKey());
for (PsiField usedInInitialization : entry.getValue()) {
ArrangementEntryDependencyInfo fieldInfo = myFieldInfosMap.get(usedInInitialization);
if (fieldInfo != null)
currentInfo.addDependentEntryInfo(fieldInfo);
}
list.add(currentInfo);
}
return list;
}
return new FieldDependenciesManager(myFieldDependencies, myFields).getRoots();
}
}
@@ -0,0 +1,26 @@
public class A {
Project p;
MyElement fieldElement;
static MyElement staticElement;
public A() {
MyElement localElement1 = getElement();
getProje<caret>ct();
MyElement localElement2 = getElement();
}
interface Project {
}
interface MyElement {
Project getProject();
}
}
@@ -0,0 +1,20 @@
public class A {
Project p;
MyElement fieldElement;
static MyElement staticElement;
public void m() {
fieldElement.getProject();
}
interface Project {
}
interface MyElement {
Project getProject();
}
}
@@ -0,0 +1,20 @@
public class A {
Project p;
MyElement fieldElement;
static MyElement staticElement;
public void m() {
getProje<caret>ct();
}
interface Project {
}
interface MyElement {
Project getProject();
}
}
@@ -0,0 +1,36 @@
import java.lang.Object;
public class A {
Project p;
MyElement fieldElement;
static MyElement staticElement;
public void m(MyElement paramElement) {
Object o = new Object() {
private final MyElement nestedField;
public void targetMethod(MyElement nestedParamElement) {
final MyElement localElement1 = getElement();
getProje<caret>ct ();
MyElement localElement2 = getElement();
}
}
}
interface Project {
}
interface MyElement {
Project getProject();
}
}
@@ -0,0 +1,26 @@
public class A {
Project p;
MyElement fieldElement;
static MyElement staticElement;
public void targetMethod(MyElement paramElement) {
MyElement localElement1 = getElement();
getProje<caret>ct();
MyElement localElement2 = getElement();
}
interface Project {
}
interface MyElement {
Project getProject();
}
}
@@ -0,0 +1,26 @@
public class A {
Project p;
MyElement fieldElement;
static MyElement staticElement;
static {
MyElement localElement1 = getElement();
getProje<caret>ct();
MyElement localElement2 = getElement();
}
interface Project {
}
interface MyElement {
Project getProject();
}
}
@@ -0,0 +1,26 @@
public class A {
Project p;
MyElement fieldElement;
static MyElement staticElement;
public static void targetMethod(MyElement paramElement) {
MyElement localElement1 = getElement();
getProje<caret>ct();
MyElement localElement2 = getElement();
}
interface Project {
}
interface MyElement {
Project getProject();
}
}
@@ -0,0 +1,14 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
class Bar3 {
public void foo(@Nullable Object element) {
final String elementType = element != null ? element.toString() : null;
if (elementType == "") {
System.out.println(element.hashCode());
}
}
}
@@ -0,0 +1,16 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
class Bar3 {
public void foo(@Nullable Object element) {
final String elementType = element != null ? element.toString() : null;
if (elementType == nullableString()) {
System.out.println(<warning descr="Method invocation 'element.hashCode()' may produce 'java.lang.NullPointerException'">element.hashCode()</warning>);
}
}
@Nullable String nullableString() { return null; }
}
@@ -0,0 +1,16 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
class Bar3 {
public void foo(@Nullable Object element) {
final String elementType = element != null ? element.toString() : null;
if (elementType == someString()) {
System.out.println(<warning descr="Method invocation 'element.hashCode()' may produce 'java.lang.NullPointerException'">element.hashCode()</warning>);
}
}
String someString() { return <warning descr="'null' is returned by the method which is not declared as @Nullable">null</warning>; }
}
@@ -0,0 +1,104 @@
/*
* 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.codeInsight.daemon.quickFix;
import com.intellij.JavaTestUtil;
import com.intellij.codeInsight.daemon.impl.quickfix.AddMethodQualifierFix;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.psi.PsiNamedElement;
import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.Nullable;
import java.util.*;
/**
* @author Dmitry Batkovich
*/
public class AddMethodQualifierTest extends JavaCodeInsightFixtureTestCase {
@Override
protected String getTestDataPath() {
return JavaTestUtil.getJavaTestDataPath() + "/codeInsight/daemonCodeAnalyzer/quickFix/addMethodCallQualifier/";
}
public void testNonStaticMethod() {
doTest("fieldElement", "staticElement", "localElement1", "paramElement");
}
public void testStaticMethod() {
doTest("staticElement", "localElement1", "paramElement");
}
public void testNestedMethod() {
doTest("fieldElement", "localElement1", "nestedField", "nestedParamElement", "staticElement", "paramElement");
}
public void testConstructor() {
doTest("fieldElement", "staticElement", "localElement1");
}
public void testStaticInitializer() {
doTest("staticElement", "localElement1");
}
public void testFix() {
doTestFix();
}
private void doTestFix() {
myFixture.configureByFile(getTestName(false) + "Before.java");
final AddMethodQualifierFix quickFix = getQuickFix();
assertNotNull(quickFix);
myFixture.launchAction(quickFix);
myFixture.checkResultByFile(getTestName(false) + "After.java");
}
private void doTest(final String... candidatesNames) {
myFixture.configureByFile(getTestName(false) + ".java");
final AddMethodQualifierFix addMethodQualifierFix = getQuickFix();
if (candidatesNames.length == 0) {
assertNull(addMethodQualifierFix);
return;
}
assertNotNull(addMethodQualifierFix);
final Set<String> actualCandidatesNames = new TreeSet<String>(ContainerUtil.map(addMethodQualifierFix.getCandidates(), new Function<PsiNamedElement, String>() {
@Override
public String fun(final PsiNamedElement psiNamedElement) {
final String name = psiNamedElement.getName();
assertNotNull(name);
return name;
}
}));
final Set<String> expectedCandidatesNames = new TreeSet<String>(ContainerUtil.list(candidatesNames));
assertEquals(expectedCandidatesNames, actualCandidatesNames);
}
@Nullable
private AddMethodQualifierFix getQuickFix() {
final List<IntentionAction> availableIntentions = myFixture.getAvailableIntentions();
AddMethodQualifierFix addMethodQualifierFix = null;
for (final IntentionAction availableIntention : availableIntentions) {
if (availableIntention instanceof AddMethodQualifierFix) {
addMethodQualifierFix = (AddMethodQualifierFix)availableIntention;
break;
}
}
return addMethodQualifierFix;
}
}
@@ -71,6 +71,9 @@ public class DataFlowInspectionTest extends LightCodeInsightFixtureTestCase {
public void testGeneratedEquals() throws Throwable { doTest(); }
public void testIDEA84489() throws Throwable { doTest(); }
public void testComparingNullToNotNull() { doTest(); }
public void testComparingNullableToNullable() { doTest(); }
public void testComparingNullableToUnknown() { doTest(); }
public void testComparingToNotNullShouldNotAffectNullity() throws Throwable { doTest(); }
public void testComparingToNullableShouldNotAffectNullity() throws Throwable { doTest(); }
public void testStringTernaryAlwaysTrue() throws Throwable { doTest(); }
@@ -21,6 +21,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.util.ResourceUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.xmlb.SerializationFilter;
@@ -46,7 +47,7 @@ import java.util.Set;
* @since 28-Nov-2005
*/
@SuppressWarnings("JavadocReference")
public abstract class InspectionProfileEntry {
public abstract class InspectionProfileEntry implements BatchSuppressableTool{
public static final String GENERAL_GROUP_NAME = InspectionsBundle.message("inspection.general.tools.group.name");
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.InspectionProfileEntry");
@@ -56,6 +57,42 @@ public abstract class InspectionProfileEntry {
private static final Object BLACK_LIST_LOCK = new Object();
private Boolean myUseNewSerializer = null;
@NonNls
@Nullable
public String getAlternativeID() {
return null;
}
@Override
public boolean isSuppressedFor(@NotNull PsiElement element) {
InspectionSuppressor suppressor = LanguageInspectionSuppressors.INSTANCE.forLanguage(element.getLanguage());
if (suppressor != null) {
String toolId = getSuppressId();
if (suppressor.isSuppressedFor(element, toolId)) {
return true;
}
final String alternativeId = getAlternativeID();
return alternativeId != null && !alternativeId.equals(toolId) && suppressor.isSuppressedFor(element, alternativeId);
}
return false;
}
protected String getSuppressId() {
return getShortName();
}
@NotNull
@Override
public SuppressQuickFix[] getBatchSuppressActions(@Nullable PsiElement element) {
if (element != null) {
InspectionSuppressor suppressor = LanguageInspectionSuppressors.INSTANCE.forLanguage(element.getLanguage());
if (suppressor != null) {
return suppressor.getSuppressActions(element, getShortName());
}
}
return SuppressQuickFix.EMPTY_ARRAY;
}
public void cleanup(Project project) {
}
@@ -71,6 +71,11 @@ public abstract class LocalInspectionTool extends InspectionProfileEntry {
return getShortName();
}
@Override
protected String getSuppressId() {
return getID();
}
@NonNls
@Nullable
public String getAlternativeID() {
@@ -830,33 +830,23 @@ public class HighlightInfo implements Segment {
throw new AssertionError("unknown tool: " + toolWrapper+"; key: "+myKey);
}
SuppressQuickFix[] suppressFixes = null;
if (wrappedTool instanceof CustomSuppressableInspectionTool) {
suppressFixes = SuppressQuickFix.EMPTY_ARRAY;
final IntentionAction[] suppressActions = ((CustomSuppressableInspectionTool)wrappedTool).getSuppressActions(element);
if (suppressActions != null) {
ContainerUtil.addAll(newOptions, suppressActions);
}
}
if (wrappedTool instanceof BatchSuppressableTool) {
suppressFixes = ((BatchSuppressableTool)wrappedTool).getBatchSuppressActions(element);
}
if (suppressFixes == null) {
final InspectionSuppressor suppressor = LanguageInspectionSuppressors.INSTANCE.forLanguage(element.getLanguage());
if (suppressor != null) {
suppressFixes = suppressor.getSuppressActions(element, wrappedTool.getShortName());
} else {
SuppressQuickFix[] suppressFixes = wrappedTool.getBatchSuppressActions(element);
if (suppressFixes.length > 0) {
ContainerUtil.addAll(newOptions, ContainerUtil.map(suppressFixes, new Function<SuppressQuickFix, IntentionAction>() {
@Override
public IntentionAction fun(SuppressQuickFix fix) {
return SuppressIntentionActionFromFix.convertBatchToSuppressIntentionAction(fix);
}
}));
}
}
if (suppressFixes != null) {
ContainerUtil.addAll(newOptions, ContainerUtil.map(suppressFixes, new Function<SuppressQuickFix, IntentionAction>() {
@Override
public IntentionAction fun(SuppressQuickFix fix) {
return SuppressIntentionActionFromFix.convertBatchToSuppressIntentionAction(fix);
}
}));
}
}
if (myProblemGroup instanceof SuppressableProblemGroup) {
final IntentionAction[] suppressActions = ((SuppressableProblemGroup)myProblemGroup).getSuppressActions(element);
@@ -194,24 +194,6 @@ public class SuppressionUtil extends SuppressionUtilCore {
}
public static boolean inspectionResultSuppressed(@NotNull PsiElement place, @NotNull LocalInspectionTool tool) {
if (tool instanceof CustomSuppressableInspectionTool) {
return ((CustomSuppressableInspectionTool)tool).isSuppressedFor(place);
}
if (tool instanceof BatchSuppressableTool) {
return ((BatchSuppressableTool)tool).isSuppressedFor(place);
}
final InspectionSuppressor suppressor = LanguageInspectionSuppressors.INSTANCE.forLanguage(place.getLanguage());
if (suppressor != null) {
return suppressor.isSuppressedFor(place, tool.getID());
}
String alternativeId;
String id;
return isSuppressed(place, id = tool.getID()) ||
(alternativeId = tool.getAlternativeID()) != null &&
!alternativeId.equals(id) &&
isSuppressed(place, alternativeId);
return tool.isSuppressedFor(place);
}
}
@@ -90,16 +90,13 @@ public class InspectionManagerEx extends InspectionManagerBase {
if (tool instanceof CustomSuppressableInspectionTool) {
return ((CustomSuppressableInspectionTool)tool).getSuppressActions(null);
}
if (tool instanceof BatchSuppressableTool) {
LocalQuickFix[] actions = ((BatchSuppressableTool)tool).getBatchSuppressActions(null);
return ContainerUtil.map2Array(actions, SuppressIntentionAction.class, new Function<LocalQuickFix, SuppressIntentionAction>() {
@Override
public SuppressIntentionAction fun(final LocalQuickFix fix) {
return SuppressIntentionActionFromFix.convertBatchToSuppressIntentionAction((SuppressQuickFix)fix);
}
});
}
return null;
LocalQuickFix[] actions = tool.getBatchSuppressActions(null);
return ContainerUtil.map2Array(actions, SuppressIntentionAction.class, new Function<LocalQuickFix, SuppressIntentionAction>() {
@Override
public SuppressIntentionAction fun(final LocalQuickFix fix) {
return SuppressIntentionActionFromFix.convertBatchToSuppressIntentionAction((SuppressQuickFix)fix);
}
});
}
@@ -0,0 +1,67 @@
/*
* 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.ide.actions;
import com.intellij.ide.PowerSaveMode;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationGroup;
import com.intellij.notification.NotificationListener;
import com.intellij.notification.NotificationType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.startup.StartupActivity;
import org.jetbrains.annotations.NotNull;
import javax.swing.event.HyperlinkEvent;
/**
* @author peter
*/
public class PowerSaveModeNotifier implements StartupActivity {
private static final NotificationGroup POWER_SAVE_MODE = NotificationGroup.balloonGroup("Power Save Mode");
private static final String IGNORE_POWER_SAVE_MODE = "ignore.power.save.mode";
@Override
public void runActivity(@NotNull Project project) {
if (PowerSaveMode.isEnabled()) {
notifyOnPowerSaveMode(project);
}
}
static void notifyOnPowerSaveMode(Project project) {
if (PropertiesComponent.getInstance().getBoolean(IGNORE_POWER_SAVE_MODE, false)) {
return;
}
String message = "Code insight and other background tasks are disabled." +
"<br/><a href=\"ignore\">Do not show again</a>" +
"<br/><a href=\"turnOff\">Disable Power Save Mode</a>";
POWER_SAVE_MODE.createNotification("Power save mode is on", message, NotificationType.WARNING, new NotificationListener() {
@Override
public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) {
final String description = event.getDescription();
if ("ignore".equals(description)) {
PropertiesComponent.getInstance().setValue(IGNORE_POWER_SAVE_MODE, "true");
notification.expire();
}
else if ("turnOff".equals(description)) {
PowerSaveMode.setEnabled(false);
notification.expire();
}
}
}).notify(project);
}
}
@@ -17,6 +17,7 @@ package com.intellij.ide.actions;
import com.intellij.ide.PowerSaveMode;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.ToggleAction;
import com.intellij.openapi.project.DumbAware;
@@ -32,5 +33,8 @@ public class TogglePowerSaveAction extends ToggleAction implements DumbAware {
@Override
public void setSelected(AnActionEvent e, boolean state) {
PowerSaveMode.setEnabled(state);
if (state) {
PowerSaveModeNotifier.notifyOnPowerSaveMode(e.getData(CommonDataKeys.PROJECT));
}
}
}
@@ -59,7 +59,7 @@ public class PushedFilePropertiesUpdater {
private final Project myProject;
private final FilePropertyPusher[] myPushers;
private final FilePropertyPusher[] myFilePushers;
private final Queue<DumbModeTask> myTasks = new ConcurrentLinkedQueue<DumbModeTask>();
private final Queue<Runnable> myTasks = new ConcurrentLinkedQueue<Runnable>();
private final MessageBusConnection myConnection;
public static PushedFilePropertiesUpdater getInstance(Project project) {
@@ -84,7 +84,6 @@ public class PushedFilePropertiesUpdater {
myConnection.subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootAdapter() {
@Override
public void rootsChanged(final ModuleRootEvent event) {
pushAll(myPushers);
for (FilePropertyPusher pusher : myPushers) {
pusher.afterRootsChanged(project);
}
@@ -123,8 +122,6 @@ public class PushedFilePropertiesUpdater {
}
public void initializeProperties() {
pushAll(myPushers);
for (final FilePropertyPusher pusher : myPushers) {
pusher.initExtra(myProject, myProject.getMessageBus(), new FilePropertyPusher.Engine() {
@Override
@@ -140,13 +137,18 @@ public class PushedFilePropertiesUpdater {
}
}
public void pushAllPropertiesNow() {
performPushTasks();
doPushAll(myPushers);
}
private void schedulePushRecursively(final VirtualFile dir, final FilePropertyPusher... pushers) {
if (pushers.length == 0) return;
final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
if (!fileIndex.isInContent(dir)) return;
queueTask(new DumbModeTask() {
queueTask(new Runnable() {
@Override
public void performInDumbMode(@NotNull final ProgressIndicator indicator) {
public void run() {
doPushRecursively(dir, pushers, fileIndex);
}
});
@@ -162,25 +164,25 @@ public class PushedFilePropertiesUpdater {
});
}
private void queueTask(DumbModeTask task) {
private void queueTask(Runnable task) {
myTasks.offer(task);
DumbService.getInstance(myProject).queueTask(new DumbModeTask() {
@Override
public void performInDumbMode(@NotNull ProgressIndicator indicator) {
performPushTasks(indicator);
performPushTasks();
}
});
}
public void performPushTasks(ProgressIndicator indicator) {
private void performPushTasks() {
boolean hadTasks = false;
while (true) {
DumbModeTask task = myTasks.poll();
Runnable task = myTasks.poll();
if (task == null) {
break;
}
hadTasks = true;
task.performInDumbMode(indicator);
task.run();
}
if (hadTasks && !myProject.isDisposed()) {
@@ -213,9 +215,9 @@ public class PushedFilePropertiesUpdater {
}
public void pushAll(final FilePropertyPusher... pushers) {
queueTask(new DumbModeTask() {
queueTask(new Runnable() {
@Override
public void performInDumbMode(@NotNull ProgressIndicator indicator) {
public void run() {
doPushAll(pushers);
}
});
@@ -51,7 +51,7 @@ public class UnindexedFilesUpdater extends DumbModeTask {
}
private void updateUnindexedFiles(ProgressIndicator indicator) {
PushedFilePropertiesUpdater.getInstance(myProject).performPushTasks(indicator);
PushedFilePropertiesUpdater.getInstance(myProject).pushAllPropertiesNow();
indicator.setIndeterminate(true);
indicator.setText(IdeBundle.message("progress.indexing.scanning"));
@@ -268,6 +268,8 @@ public class JBScrollPane extends JScrollPane {
}
private static boolean isOverlaidScrollbar(@Nullable JScrollBar scrollbar) {
if (!ButtonlessScrollBarUI.isMacOverlayScrollbarSupported()) return false;
ScrollBarUI vsbUI = scrollbar == null ? null : scrollbar.getUI();
return vsbUI instanceof ButtonlessScrollBarUI && !((ButtonlessScrollBarUI)vsbUI).alwaysShowTrack();
}
@@ -84,6 +84,7 @@ public class FormBuilder {
final int index = UIUtil.getDisplayMnemonicIndex(labelText);
if (index != -1) {
label.setDisplayedMnemonic(labelText.charAt(index + 1));
label.setDisplayedMnemonicIndex(index);
}
label.setLabelFor(component);
@@ -62,7 +62,6 @@ public class SystemHealthMonitor extends ApplicationComponent.Adapter {
public void initComponent() {
checkJvm();
startDiskSpaceMonitoring();
checkPowerSaveMode();
}
private void checkJvm() {
@@ -210,25 +209,4 @@ public class SystemHealthMonitor extends ApplicationComponent.Adapter {
}, 1, TimeUnit.SECONDS);
}
private void checkPowerSaveMode() {
if (PowerSaveMode.isEnabled()) {
final String ignoreKey = "ignore.power.save.mode";
String message = "Power save mode is on. Code insight and other background tasks are disabled." +
"<br/><a href=\"ignore\">Do not show again</a>" +
"<br/><a href=\"turnOff\">Disable Power Save Mode</a>";
showNotification(ignoreKey, message, new HyperlinkAdapter() {
@Override
protected void hyperlinkActivated(HyperlinkEvent e) {
final String description = e.getDescription();
if ("ignore".equals(description)) {
myProperties.setValue(ignoreKey, "true");
}
else if ("turnOff".equals(description)) {
PowerSaveMode.setEnabled(false);
}
}
});
}
}
}
@@ -15,6 +15,7 @@
*/
package com.intellij.openapi.project;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.caches.CacheUpdater;
import com.intellij.ide.caches.FileContent;
import com.intellij.openapi.application.Application;
@@ -40,7 +41,7 @@ import java.util.Set;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean;
public class CacheUpdateRunner {
public class CacheUpdateRunner extends DumbModeTask {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.project.CacheUpdateRunner");
private static final Key<Boolean> FAILED_TO_INDEX = Key.create("FAILED_TO_INDEX");
private static final int PROC_COUNT = Runtime.getRuntime().availableProcessors();
@@ -58,15 +59,11 @@ public class CacheUpdateRunner {
return new ArrayList<CacheUpdater>(myUpdaters).toString();
}
public int queryNeededFiles(@NotNull ProgressIndicator indicator) {
private int queryNeededFiles(@NotNull ProgressIndicator indicator) {
// can be queried twice in DumbService
return getSession(indicator).getFilesToUpdate().size();
}
public int getNumberOfPendingUpdateJobs(@NotNull ProgressIndicator indicator) {
return getSession(indicator).getNumberOfPendingUpdateJobs();
}
@NotNull
private CacheUpdateSession getSession(@NotNull ProgressIndicator indicator) {
CacheUpdateSession session = mySession;
@@ -76,7 +73,7 @@ public class CacheUpdateRunner {
return session;
}
public void processFiles(@NotNull final ProgressIndicator indicator, boolean processInReadAction) {
private void processFiles(@NotNull final ProgressIndicator indicator, boolean processInReadAction) {
try {
Collection<VirtualFile> files = mySession.getFilesToUpdate();
@@ -134,7 +131,7 @@ public class CacheUpdateRunner {
}
}
public void updatingDone() {
private void updatingDone() {
try {
mySession.updatingDone();
}
@@ -217,6 +214,21 @@ public class CacheUpdateRunner {
return false;
}
@Override
public void performInDumbMode(@NotNull ProgressIndicator indicator) {
indicator.checkCanceled();
indicator.setIndeterminate(true);
indicator.setText(IdeBundle.message("progress.indexing.scanning"));
int count = queryNeededFiles(indicator);
indicator.setIndeterminate(false);
indicator.setText(IdeBundle.message("progress.indexing.updating"));
if (count > 0) {
processFiles(indicator, true);
}
updatingDone();
}
private static class MyRunnable implements Runnable {
private final ProgressIndicatorBase myInnerIndicator;
private final FileContentQueue myQueue;
@@ -17,7 +17,6 @@ package com.intellij.openapi.project;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.caches.CacheUpdater;
import com.intellij.ide.caches.FileContent;
import com.intellij.ide.util.DelegatingProgressIndicator;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.Application;
@@ -29,8 +28,8 @@ import com.intellij.openapi.progress.*;
import com.intellij.openapi.progress.util.ProgressIndicatorBase;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.ShutDownTracker;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.AppIconScheme;
import com.intellij.openapi.wm.IdeFrame;
import com.intellij.openapi.wm.WindowManager;
@@ -48,21 +47,15 @@ import org.jetbrains.annotations.TestOnly;
import javax.swing.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
public class DumbServiceImpl extends DumbService {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.project.DumbServiceImpl");
private volatile boolean myDumb = false;
private final DumbModeListener myPublisher;
private final Queue<IndexUpdateRunnable> myUpdatesQueue = new Queue<IndexUpdateRunnable>(5);
private final Queue<DumbModeTask> myUpdatesQueue = new Queue<DumbModeTask>(5);
private final Queue<Runnable> myRunWhenSmartQueue = new Queue<Runnable>(5);
private final Project myProject;
private final CacheUpdateRunner NULL_ACTION;
@SuppressWarnings({"MethodOverridesStaticMethodOfSuperclass"})
public static DumbServiceImpl getInstance(@NotNull Project project) {
@@ -71,45 +64,12 @@ public class DumbServiceImpl extends DumbService {
@Override
public void queueTask(final DumbModeTask task) {
CacheUpdater wrapper = new CacheUpdater() {
@Override
public int getNumberOfPendingUpdateJobs() {
return 0;
}
@NotNull
@Override
public VirtualFile[] queryNeededFiles(@NotNull ProgressIndicator indicator) {
task.performInDumbMode(indicator);
return new VirtualFile[0];
}
@Override
public void processFile(@NotNull FileContent fileContent) {
}
@Override
public void updatingDone() {
}
@Override
public void canceled() {
}
@Override
public String toString() {
return task.toString();
}
};
queueCacheUpdateInDumbMode(Arrays.asList(wrapper));
scheduleCacheUpdate(task, true);
}
public DumbServiceImpl(Project project, MessageBus bus) {
myProject = project;
myPublisher = bus.syncPublisher(DUMB_MODE);
NULL_ACTION = new CacheUpdateRunner(project, Collections.<CacheUpdater>emptyList());
}
@Override
@@ -145,87 +105,48 @@ public class DumbServiceImpl extends DumbService {
}
}
@SuppressWarnings("deprecation")
public void queueCacheUpdate(@NotNull Collection<CacheUpdater> updaters) {
scheduleCacheUpdate(updaters, false);
scheduleCacheUpdate(new CacheUpdateRunner(myProject, new ArrayList<CacheUpdater>(updaters)), false);
}
@SuppressWarnings("deprecation")
public void queueCacheUpdateInDumbMode(@NotNull Collection<CacheUpdater> updaters) {
scheduleCacheUpdate(updaters, true);
scheduleCacheUpdate(new CacheUpdateRunner(myProject, new ArrayList<CacheUpdater>(updaters)), true);
}
private void scheduleCacheUpdate(@NotNull Collection<CacheUpdater> updaters, boolean forceDumbMode) {
// prevent concurrent modifications
final CacheUpdateRunner runner = new CacheUpdateRunner(myProject, new ArrayList<CacheUpdater>(updaters));
private void scheduleCacheUpdate(@NotNull final DumbModeTask task, boolean forceDumbMode) {
final Application application = ApplicationManager.getApplication();
if (application.isUnitTestMode() || application.isHeadlessEnvironment()) {
// no dumb mode for tests
EmptyProgressIndicator i = new EmptyProgressIndicator();
final int size = runner.queryNeededFiles(i);
if (application.isUnitTestMode() ||
application.isHeadlessEnvironment() ||
!forceDumbMode && !myDumb && application.isReadAccessAllowed()) {
final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
if (indicator != null) {
indicator.pushState();
}
try {
HeavyProcessLatch.INSTANCE.processStarted();
if (size > 0) {
runner.processFiles(i, false);
}
runner.updatingDone();
task.performInDumbMode(indicator != null ? indicator : new EmptyProgressIndicator());
}
finally {
HeavyProcessLatch.INSTANCE.processFinished();
if (indicator != null) {
indicator.popState();
}
}
return;
}
if (!forceDumbMode && !myDumb && application.isReadAccessAllowed()) {
// if there are not so many files to process, process them on the spot without entering dumb mode
final ProgressIndicator currentIndicator = ProgressManager.getInstance().getProgressIndicator();
final ProgressIndicator indicator;
if (currentIndicator != null) {
indicator = currentIndicator;
currentIndicator.pushState();
}
else {
indicator = new EmptyProgressIndicator();
}
try {
final int size = runner.queryNeededFiles(indicator);
if (size + runner.getNumberOfPendingUpdateJobs(indicator) < 50) {
// If not that many files found, process them on the spot, avoiding entering dumb mode
// Consider number of pending tasks as well, because they may take noticeable time to process even if the number of files is small
try {
HeavyProcessLatch.INSTANCE.processStarted();
if (size > 0) {
runner.processFiles(indicator, false);
}
runner.updatingDone();
}
finally {
HeavyProcessLatch.INSTANCE.processFinished();
}
return;
}
}
finally {
if (currentIndicator != null) {
currentIndicator.popState();
}
}
}
final IndexUpdateRunnable updateRunnable = new IndexUpdateRunnable(runner);
UIUtil.invokeLaterIfNeeded(new DumbAwareRunnable() {
@Override
public void run() {
if (myProject.isDisposed()) {
return;
}
myUpdatesQueue.addLast(task);
// ok to test and set the flag like this, because the change is always done from dispatch thread
if (myDumb) {
myUpdatesQueue.addLast(updateRunnable);
}
else {
if (!myDumb) {
// always change dumb status inside write action.
// This will ensure all active read actions are completed before the app goes dumb
boolean startSuccess =
@@ -239,14 +160,13 @@ public class DumbServiceImpl extends DumbService {
catch (Throwable e) {
LOG.error(e);
}
finally {
try {
updateRunnable.run();
}
catch (Throwable e) {
LOG.error("Failed to start background index update task", e);
return false;
}
try {
startBackgroundProcess();
}
catch (Throwable e) {
LOG.error("Failed to start background index update task", e);
return false;
}
return true;
}
@@ -365,140 +285,101 @@ public class DumbServiceImpl extends DumbService {
}, modalityState, myProject.getDisposed());
}
private class IndexUpdateRunnable implements Runnable {
private final CacheUpdateRunner myAction;
private void startBackgroundProcess() {
ProgressManager.getInstance().run(new Task.Backgroundable(myProject, IdeBundle.message("progress.indexing"), false) {
public IndexUpdateRunnable(@NotNull CacheUpdateRunner action) {
myAction = action;
@Override
public void run(@NotNull final ProgressIndicator indicator) {
if (indicator instanceof ProgressIndicatorEx) {
((ProgressIndicatorEx)indicator).addStateDelegate(new AppIconProgress());
}
final ProgressIndicator proxy = new DelegatingProgressIndicator(indicator);
final ShutDownTracker shutdownTracker = ShutDownTracker.getInstance();
final Thread self = Thread.currentThread();
try {
HeavyProcessLatch.INSTANCE.processStarted();
shutdownTracker.registerStopperThread(self);
runTasks(proxy);
}
catch (RuntimeException e) {
LOG.error(e);
throw e;
}
finally {
shutdownTracker.unregisterStopperThread(self);
HeavyProcessLatch.INSTANCE.processFinished();
}
}
private void runTasks(ProgressIndicator indicator) {
while (true) {
DumbModeTask task = getNextTask();
if (task == null) break;
try {
if (ApplicationManager.getApplication().isInternal()) LOG.info("Running dumb mode task: " + task);
indicator.checkCanceled();
indicator.setIndeterminate(true);
indicator.setText(IdeBundle.message("progress.indexing.scanning"));
task.performInDumbMode(indicator);
}
catch (ProcessCanceledException ignored) {
}
catch (Throwable unexpected) {
LOG.error(unexpected);
}
}
}
});
}
@Nullable
private DumbModeTask getNextTask() {
final Ref<DumbModeTask> nextTask = Ref.create();
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
if (myProject.isDisposed()) return;
if (myUpdatesQueue.isEmpty()) {
updateFinished();
} else {
nextTask.set(myUpdatesQueue.pullFirst());
}
}
});
return nextTask.get();
}
private class AppIconProgress extends ProgressIndicatorBase {
double lastFraction;
@Override
public void setFraction(final double fraction) {
if (fraction - lastFraction < 0.01d) return;
lastFraction = fraction;
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
AppIcon.getInstance().setProgress(myProject, "indexUpdate", AppIconScheme.Progress.INDEXING, fraction, true);
}
});
}
@Override
public void run() {
ProgressManager.getInstance().run(new Task.Backgroundable(myProject, IdeBundle.message("progress.indexing"), false) {
public void finish(@NotNull TaskInfo task) {
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run(@NotNull final ProgressIndicator indicator) {
if (indicator instanceof ProgressIndicatorEx) {
((ProgressIndicatorEx)indicator).addStateDelegate(new ProgressIndicatorBase() {
double lastFraction;
@Override
public void setFraction(final double fraction) {
if (fraction - lastFraction < 0.01d) return;
lastFraction = fraction;
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
AppIcon.getInstance().setProgress(myProject, "indexUpdate", AppIconScheme.Progress.INDEXING, fraction, true);
}
});
}
@Override
public void finish(@NotNull TaskInfo task) {
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
AppIcon appIcon = AppIcon.getInstance();
if (appIcon.hideProgress(myProject, "indexUpdate")) {
appIcon.requestAttention(myProject, false);
appIcon.setOkBadge(myProject, true);
}
}
});
}
});
}
final ProgressIndicator proxy = new DelegatingProgressIndicator(indicator);
final ShutDownTracker shutdownTracker = ShutDownTracker.getInstance();
final Thread self = Thread.currentThread();
try {
HeavyProcessLatch.INSTANCE.processStarted();
shutdownTracker.registerStopperThread(self);
runAction(proxy, myAction);
}
catch (RuntimeException e) {
LOG.error(e);
throw e;
}
finally {
shutdownTracker.unregisterStopperThread(self);
HeavyProcessLatch.INSTANCE.processFinished();
}
}
private void runAction(ProgressIndicator indicator, CacheUpdateRunner updateRunner) {
while (updateRunner != null) {
try {
if (ApplicationManager.getApplication().isInternal()) LOG.info("Running dumb mode task: " + updateRunner);
indicator.checkCanceled();
indicator.setIndeterminate(true);
indicator.setText(IdeBundle.message("progress.indexing.scanning"));
int count = updateRunner.queryNeededFiles(indicator);
indicator.setIndeterminate(false);
indicator.setText(IdeBundle.message("progress.indexing.updating"));
if (count > 0) {
updateRunner.processFiles(indicator, true);
}
updateRunner.updatingDone();
}
catch (ProcessCanceledException ignored) {
}
catch (Throwable unexpected) {
LOG.error(unexpected);
}
updateRunner = getNextUpdateRunner();
}
}
@Nullable
private CacheUpdateRunner getNextUpdateRunner() {
final BlockingQueue<CacheUpdateRunner> actionQueue = new LinkedBlockingQueue<CacheUpdateRunner>();
UIUtil.invokeLaterIfNeeded(new DumbAwareRunnable() {
@Override
public void run() {
IndexUpdateRunnable nextRunnable = getNextUpdateFromQueue();
try {
actionQueue.offer(nextRunnable == null ? NULL_ACTION : nextRunnable.myAction);
}
finally {
if (nextRunnable == null) {
updateFinished();
}
}
}
});
// try to obtain the next action or terminate if no actions left
while (!myProject.isDisposed()) {
try {
CacheUpdateRunner ref = actionQueue.poll(500L, TimeUnit.MILLISECONDS);
if (ref != null) {
return ref == NULL_ACTION ? null : ref;
}
}
catch (InterruptedException e) {
LOG.info(e);
}
}
return null;
}
@Nullable
private IndexUpdateRunnable getNextUpdateFromQueue() {
try {
return myUpdatesQueue.isEmpty()? null : myUpdatesQueue.pullFirst();
}
catch (Throwable e) {
LOG.info(e);
return null;
public void run() {
AppIcon appIcon = AppIcon.getInstance();
if (appIcon.hideProgress(myProject, "indexUpdate")) {
appIcon.requestAttention(myProject, false);
appIcon.setOkBadge(myProject, true);
}
}
});
}
}
}
@@ -283,6 +283,7 @@
serviceImplementation="com.intellij.ide.TypePresentationServiceImpl"/>
<postStartupActivity implementation="com.intellij.ide.TipOfTheDayManager"/>
<postStartupActivity implementation="com.intellij.ide.actions.PowerSaveModeNotifier"/>
<postStartupActivity implementation="com.intellij.openapi.actionSystem.impl.ActionPreloader"/>
<postStartupActivity id="OpenFilesActivity" implementation="com.intellij.openapi.fileEditor.impl.OpenFilesActivity"/>
@@ -22,7 +22,7 @@ public class OneElementFMap<V> implements KeyFMap {
private final Key myKey;
private final V myValue;
public OneElementFMap(Key key, @NotNull V value) {
public OneElementFMap(@NotNull Key key, @NotNull V value) {
myKey = key;
myValue = value;
}
@@ -71,7 +71,7 @@ public class OneElementFMap<V> implements KeyFMap {
OneElementFMap map = (OneElementFMap)o;
if (!myKey.equals(map.myKey)) return false;
if (myKey != map.myKey) return false;
if (!myValue.equals(map.myValue)) return false;
return true;
@@ -24,7 +24,7 @@ class PairElementsFMap implements KeyFMap {
private final Object value1;
private final Object value2;
PairElementsFMap(Key key1, @NotNull Object value1, Key key2, @NotNull Object value2) {
PairElementsFMap(@NotNull Key key1, @NotNull Object value1, @NotNull Key key2, @NotNull Object value2) {
this.key1 = key1;
this.value1 = value1;
this.key2 = key2;
@@ -17,7 +17,6 @@ package com.intellij.util.ui.tree;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.util.containers.ComparatorUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -49,7 +48,6 @@ public class WideSelectionTreeUI extends BasicTreeUI {
@NotNull private final Condition<Integer> myWideSelectionCondition;
private boolean myWideSelection;
private boolean myOldRepaintAllRowValue;
private boolean invertLineColor;
private boolean myForceDontPaintLines = false;
private boolean mySkinny = false;
@@ -281,17 +279,15 @@ public class WideSelectionTreeUI extends BasicTreeUI {
final boolean isExpanded,
final boolean hasBeenExpanded,
final boolean isLeaf) {
if (!shouldPaintLines()) return;
if (!UIUtil.isUnderAquaBasedLookAndFeel() && !UIUtil.isUnderDarcula() && !UIUtil.isUnderIntelliJLaF()) {
if (UIUtil.isUnderAlloyIDEALookAndFeel()) {
invertLineColor = tree.getSelectionModel().isRowSelected(row) && tree.hasFocus();
}
if (shouldPaintLines()) {
super.paintHorizontalPartOfLeg(g, clipBounds, insets, bounds, path, row, isExpanded, hasBeenExpanded, isLeaf);
invertLineColor = false;
}
}
private boolean shouldPaintLines() {
if (UIUtil.isUnderAquaBasedLookAndFeel() || UIUtil.isUnderDarcula() || UIUtil.isUnderIntelliJLaF()) {
return false;
}
return myForceDontPaintLines || !"None".equals(tree.getClientProperty("JTree.lineStyle"));
}
@@ -302,41 +298,26 @@ public class WideSelectionTreeUI extends BasicTreeUI {
@Override
protected void paintVerticalPartOfLeg(final Graphics g, final Rectangle clipBounds, final Insets insets, final TreePath path) {
if (!UIUtil.isUnderAquaBasedLookAndFeel() && !UIUtil.isUnderDarcula() && !UIUtil.isUnderIntelliJLaF() && shouldPaintLines()) {
invertLineColor = UIUtil.isUnderAlloyIDEALookAndFeel() && tree.hasFocus() && tree.getSelectionModel().isPathSelected(path);
if (shouldPaintLines()) {
super.paintVerticalPartOfLeg(g, clipBounds, insets, path);
invertLineColor = false;
}
}
@Override
protected void paintVerticalLine(Graphics g, JComponent c, int x, int top, int bottom) {
if (!shouldPaintLines()) return;
if (tree.hasFocus() && UIUtil.isUnderAlloyIDEALookAndFeel()) {
int y0, y1 = top;
while (y1 < bottom) {
y0 = y1;
final int row = tree.getRowForPath(tree.getClosestPathForLocation(x, y0 + 1));
invertLineColor = tree.isRowSelected(row);
g.setColor(getHashColor());
final Rectangle bounds = tree.getRowBounds(row);
y1 = bounds.y + bounds.height;
super.paintVerticalLine(g, c, x, y0, Math.min(bottom, y1));
}
invertLineColor = false;
} else {
if (shouldPaintLines()) {
super.paintVerticalLine(g, c, x, top, bottom);
}
}
@Override
protected Color getHashColor() {
if (invertLineColor && !ComparatorUtil.equalsNullable(UIUtil.getTreeSelectionForeground(), UIUtil.getTreeForeground())) {
final Color c = UIUtil.getTreeSelectionForeground();
if (c != null) {
return c.darker();
}
}
//if (invertLineColor && !ComparatorUtil.equalsNullable(UIUtil.getTreeSelectionForeground(), UIUtil.getTreeForeground())) {
// final Color c = UIUtil.getTreeSelectionForeground();
// if (c != null) {
// return c.darker();
// }
//}
return super.getHashColor();
}
@@ -27,6 +27,7 @@ import com.intellij.ui.PopupHandler;
import com.intellij.ui.TreeSpeedSearch;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.Convertor;
import com.intellij.util.containers.TransferToEDTQueue;
import com.intellij.util.ui.TextTransferable;
import com.intellij.xdebugger.XSourcePosition;
import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider;
@@ -56,6 +57,8 @@ import java.util.List;
* @author nik
*/
public class XDebuggerTree extends DnDAwareTree implements DataProvider, Disposable {
private final TransferToEDTQueue<Runnable> myLaterInvocator = TransferToEDTQueue.createRunnableMerger("XDebuggerTree later invocator", 100);
private static final DataKey<XDebuggerTree> XDEBUGGER_TREE_KEY = DataKey.create("xdebugger.tree");
private static final Convertor<TreePath, String> SPEED_SEARCH_CONVERTER = new Convertor<TreePath, String>() {
@Override
@@ -324,4 +327,8 @@ public class XDebuggerTree extends DnDAwareTree implements DataProvider, Disposa
public static XDebuggerTree getTree(DataContext context) {
return XDEBUGGER_TREE_KEY.getData(context);
}
public TransferToEDTQueue<Runnable> getLaterInvocator() {
return myLaterInvocator;
}
}
@@ -189,4 +189,8 @@ public abstract class XDebuggerTreeNode implements TreeNode, TreeSpeedSearch.Pat
component.append(link.getLinkText(), link.getTextAttributes(), link);
}
}
void invokeNodeUpdate(Runnable runnable) {
myTree.getLaterInvocator().offer(runnable);
}
}
@@ -22,7 +22,6 @@ import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.SortedList;
import com.intellij.xdebugger.frame.*;
import com.intellij.xdebugger.impl.settings.XDebuggerSettingsManager;
import com.intellij.xdebugger.impl.ui.DebuggerUIUtil;
import com.intellij.xdebugger.impl.ui.XDebuggerUIConstants;
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree;
import org.jetbrains.annotations.NotNull;
@@ -75,7 +74,7 @@ public abstract class XValueContainerNode<ValueContainer extends XValueContainer
@Override
public void addChildren(@NotNull final XValueChildrenList children, final boolean last) {
DebuggerUIUtil.invokeLater(new Runnable() {
invokeNodeUpdate(new Runnable() {
@Override
public void run() {
if (myValueChildren == null) {
@@ -125,7 +124,7 @@ public abstract class XValueContainerNode<ValueContainer extends XValueContainer
@Override
public void tooManyChildren(final int remaining) {
DebuggerUIUtil.invokeLater(new Runnable() {
invokeNodeUpdate(new Runnable() {
@Override
public void run() {
setTemporaryMessageNode(MessageTreeNode.createEllipsisNode(myTree, XValueContainerNode.this, remaining));
@@ -162,7 +161,7 @@ public abstract class XValueContainerNode<ValueContainer extends XValueContainer
@Override
public void setMessage(@NotNull final String message,
final Icon icon, @NotNull final SimpleTextAttributes attributes, @Nullable final XDebuggerTreeNodeHyperlink link) {
DebuggerUIUtil.invokeLater(new Runnable() {
invokeNodeUpdate(new Runnable() {
@Override
public void run() {
setMessageNodes(MessageTreeNode.createMessages(myTree, XValueContainerNode.this, message, link,
@@ -94,12 +94,18 @@ public final class XValueNodePresentationConfigurator {
node.applyPresentation(icon, presentation, hasChildren);
}
else {
application.invokeLater(new Runnable() {
Runnable updater = new Runnable() {
@Override
public void run() {
node.applyPresentation(icon, presentation, hasChildren);
}
});
};
if (node instanceof XDebuggerTreeNode) {
((XDebuggerTreeNode)node).invokeNodeUpdate(updater);
}
else {
application.invokeLater(updater);
}
}
}
@@ -44,14 +44,7 @@ import java.util.regex.Matcher;
/**
* @author peter
*/
public abstract class GroovySuppressableInspectionTool extends LocalInspectionTool implements BatchSuppressableTool {
@NotNull
@Override
public SuppressQuickFix[] getBatchSuppressActions(@Nullable PsiElement element) {
return getSuppressActions(getShortName());
}
public abstract class GroovySuppressableInspectionTool extends LocalInspectionTool {
public static SuppressQuickFix[] getSuppressActions(String name) {
final HighlightDisplayKey displayKey = HighlightDisplayKey.find(name);
return new SuppressQuickFix[] {
@@ -61,11 +54,6 @@ public abstract class GroovySuppressableInspectionTool extends LocalInspectionTo
};
}
@Override
public boolean isSuppressedFor(@NotNull final PsiElement element) {
return isElementToolSuppressedIn(element, getID());
}
public static boolean isElementToolSuppressedIn(final PsiElement place, final String toolId) {
return getElementToolSuppressedIn(place, toolId) != null;
}
@@ -15,9 +15,7 @@
*/
package com.jetbrains.rest.inspections;
import com.intellij.codeInspection.CustomSuppressableInspectionTool;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.SuppressIntentionAction;
import com.intellij.codeInspection.*;
import com.intellij.psi.PsiElement;
import com.jetbrains.rest.RestBundle;
import org.jetbrains.annotations.Nls;
@@ -27,7 +25,7 @@ import org.jetbrains.annotations.Nullable;
/**
* User : catherine
*/
public abstract class RestInspection extends LocalInspectionTool implements CustomSuppressableInspectionTool {
public abstract class RestInspection extends LocalInspectionTool {
@Nls
@NotNull
@Override
@@ -46,9 +44,10 @@ public abstract class RestInspection extends LocalInspectionTool implements Cust
return true;
}
@NotNull
@Override
public SuppressIntentionAction[] getSuppressActions(@Nullable PsiElement element) {
return null;
public SuppressQuickFix[] getBatchSuppressActions(@Nullable PsiElement element) {
return SuppressQuickFix.EMPTY_ARRAY;
}
@Override
@@ -21,7 +21,7 @@ import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.intellij.codeInspection.LocalInspectionToolSession;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.codeInspection.SuppressIntentionAction;
import com.intellij.codeInspection.SuppressQuickFix;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.util.TextRange;
@@ -230,9 +230,10 @@ public class PyDocstringInspection extends PyInspection {
}
}
@NotNull
@Override
public SuppressIntentionAction[] getSuppressActions(@Nullable PsiElement element) {
List<SuppressIntentionAction> result = new ArrayList<SuppressIntentionAction>();
public SuppressQuickFix[] getBatchSuppressActions(@Nullable PsiElement element) {
List<SuppressQuickFix> result = new ArrayList<SuppressQuickFix>();
if (element != null) {
if (PsiTreeUtil.getParentOfType(element, PyFunction.class) != null) {
result.add(new PySuppressInspectionFix(getShortName().replace("Inspection", ""), "Suppress for function", PyFunction.class));
@@ -241,6 +242,6 @@ public class PyDocstringInspection extends PyInspection {
result.add(new PySuppressInspectionFix(getShortName().replace("Inspection", ""), "Suppress for class", PyClass.class));
}
}
return result.toArray(new SuppressIntentionAction[result.size()]);
return result.toArray(new SuppressQuickFix[result.size()]);
}
}
@@ -15,10 +15,7 @@
*/
package com.jetbrains.python.inspections;
import com.intellij.codeInspection.CustomSuppressableInspectionTool;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.SuppressIntentionAction;
import com.intellij.codeInspection.SuppressionUtil;
import com.intellij.codeInspection.*;
import com.intellij.psi.PsiComment;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
@@ -41,7 +38,7 @@ import java.util.regex.Pattern;
/**
* @author yole
*/
public abstract class PyInspection extends LocalInspectionTool implements CustomSuppressableInspectionTool {
public abstract class PyInspection extends LocalInspectionTool {
@Nls
@NotNull
@Override
@@ -60,12 +57,13 @@ public abstract class PyInspection extends LocalInspectionTool implements Custom
return true;
}
@NotNull
@Override
public SuppressIntentionAction[] getSuppressActions(@Nullable final PsiElement element) {
List<SuppressIntentionAction> result = new ArrayList<SuppressIntentionAction>();
public SuppressQuickFix[] getBatchSuppressActions(@Nullable PsiElement element) {
List<SuppressQuickFix> result = new ArrayList<SuppressQuickFix>();
result.add(new PySuppressInspectionFix(getSuppressId(), "Suppress for statement", PyStatement.class) {
@Override
protected PsiElement getContainer(PsiElement context) {
public PsiElement getContainer(PsiElement context) {
if (PsiTreeUtil.getParentOfType(context, PyStatementList.class, false, ScopeOwner.class) != null ||
PsiTreeUtil.getParentOfType(context, PyFunction.class, PyClass.class) == null) {
return super.getContainer(context);
@@ -75,7 +73,7 @@ public abstract class PyInspection extends LocalInspectionTool implements Custom
});
result.add(new PySuppressInspectionFix(getSuppressId(), "Suppress for function", PyFunction.class));
result.add(new PySuppressInspectionFix(getSuppressId(), "Suppress for class", PyClass.class));
return result.toArray(new SuppressIntentionAction[result.size()]);
return result.toArray(new SuppressQuickFix[result.size()]);
}
@Override
@@ -131,7 +129,7 @@ public abstract class PyInspection extends LocalInspectionTool implements Custom
return m.matches() && SuppressionUtil.isInspectionToolIdMentioned(m.group(1), getSuppressId());
}
private String getSuppressId() {
protected String getSuppressId() {
return getShortName().replace("Inspection", "");
}
}
@@ -15,6 +15,7 @@
*/
package com.jetbrains.python.inspections.quickfix;
import com.intellij.codeInsight.daemon.impl.actions.AbstractBatchSuppressByNoInspectionCommentFix;
import com.intellij.codeInsight.daemon.impl.actions.AbstractSuppressByNoInspectionCommentFix;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
@@ -23,7 +24,7 @@ import com.jetbrains.python.psi.PyElement;
/**
* @author yole
*/
public class PySuppressInspectionFix extends AbstractSuppressByNoInspectionCommentFix {
public class PySuppressInspectionFix extends AbstractBatchSuppressByNoInspectionCommentFix {
private final Class<? extends PyElement> myContainerClass;
public PySuppressInspectionFix(final String ID, final String text, final Class<? extends PyElement> containerClass) {
@@ -33,7 +34,7 @@ public class PySuppressInspectionFix extends AbstractSuppressByNoInspectionComme
}
@Override
protected PsiElement getContainer(PsiElement context) {
public PsiElement getContainer(PsiElement context) {
return PsiTreeUtil.getParentOfType(context, myContainerClass);
}
}
@@ -259,8 +259,8 @@ public class PyPIPackageUtil {
return packages;
}
public Collection<String> getPackageNames() throws IOException {
Map<String, String> pyPIPackages = loadAndGetPackages();
public Collection<String> getPackageNames() {
Map<String, String> pyPIPackages = getPyPIPackages();
ArrayList<String> list = Lists.newArrayList(pyPIPackages.keySet());
Collections.sort(list);
return list;
@@ -30,8 +30,10 @@ import com.jetbrains.python.packaging.PyRequirement;
import com.jetbrains.python.sdk.PythonSdkType;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.util.*;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* @author yole
@@ -51,13 +53,7 @@ public class PyPackageUsagesCollector extends AbstractApplicationUsagesCollector
public void run() {
List<PyRequirement> requirements = PyPackageManagerImpl.getRequirements(m);
if (requirements != null) {
Collection<String> packages;
try {
packages = new HashSet<String>(PyPIPackageUtil.INSTANCE.getPackageNames());
}
catch (IOException e) {
return;
}
Collection<String> packages = new HashSet<String>(PyPIPackageUtil.INSTANCE.getPackageNames());
for (PyRequirement requirement : requirements) {
String name = requirement.getName();
if (packages.contains(name)) {
@@ -281,4 +281,6 @@ wrap.array.to.arrays.as.list.single.parameter.text=Wrap using ''Arrays.asList''
annotations.fix=Annotations
add.missing.annotation.parameters.fix=Add missing annotation parameters - {0}
add.missing.annotation.single.parameter.fix=Add missing annotation parameter ''{0}''
add.missing.annotation.single.parameter.fix=Add missing annotation parameter ''{0}''
add.method.qualifier.fix.text=Add Qualifier {0} to Method
@@ -40,7 +40,7 @@ import java.awt.*;
import java.util.Set;
public class SpellCheckingInspection extends LocalInspectionTool implements BatchSuppressableTool {
public class SpellCheckingInspection extends LocalInspectionTool {
public static final String SPELL_CHECKING_INSPECTION_TOOL_NAME = "SpellCheckingInspection";
@Override
@@ -66,12 +66,8 @@ public class SpellCheckingInspection extends LocalInspectionTool implements Batc
if(strategy instanceof SuppressibleSpellcheckingStrategy) {
return ((SuppressibleSpellcheckingStrategy)strategy).getSuppressActions(element, getShortName());
}
final InspectionSuppressor suppressor = LanguageInspectionSuppressors.INSTANCE.forLanguage(language);
if (suppressor != null) {
return suppressor.getSuppressActions(element, getShortName());
}
}
return SuppressQuickFix.EMPTY_ARRAY;
return super.getBatchSuppressActions(element);
}
private static SpellcheckingStrategy getSpellcheckingStrategy(@NotNull PsiElement element, @NotNull Language language) {
@@ -90,8 +86,7 @@ public class SpellCheckingInspection extends LocalInspectionTool implements Batc
if (strategy instanceof SuppressibleSpellcheckingStrategy) {
return ((SuppressibleSpellcheckingStrategy)strategy).isSuppressedFor(element, getShortName());
}
final InspectionSuppressor suppressor = LanguageInspectionSuppressors.INSTANCE.forLanguage(language);
return suppressor != null && suppressor.isSuppressedFor(element, getShortName());
return super.isSuppressedFor(element);
}
@Override