mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
+11
-1
@@ -49,7 +49,11 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.jsp.jspJava.JspClass;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.LocalSearchScope;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.refactoring.typeMigration.TypeMigrationLabeler;
|
||||
import com.intellij.refactoring.typeMigration.TypeMigrationProcessor;
|
||||
import com.intellij.refactoring.typeMigration.TypeMigrationRules;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -401,7 +405,13 @@ public class HighlightClassUtil {
|
||||
if (aClass.isInterface()) {
|
||||
boolean isImplements = list.equals(aClass.getImplementsList());
|
||||
if (isImplements) {
|
||||
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, list, JavaErrorMessages.message("implements.after.interface"));
|
||||
final HighlightInfo highlightInfo =
|
||||
HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, list, JavaErrorMessages.message("implements.after.interface"));
|
||||
final PsiClassType[] referencedTypes = list.getReferencedTypes();
|
||||
if (referencedTypes.length > 0) {
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, new ChangeExtendsToImplementsFix(aClass, referencedTypes[0]));
|
||||
}
|
||||
return highlightInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+36
-27
@@ -23,6 +23,7 @@ import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.codeInsight.intention.QuickFixFactory;
|
||||
import com.intellij.openapi.project.IndexNotReadyException;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.controlFlow.*;
|
||||
import com.intellij.psi.search.LocalSearchScope;
|
||||
@@ -698,7 +699,11 @@ public class HighlightControlFlowUtil {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
String description = JavaErrorMessages.message("variable.must.be.final", context.getText());
|
||||
if (PsiUtil.getLanguageLevel(variable).isAtLeast(LanguageLevel.JDK_1_8) &&
|
||||
isEffectivelyFinal(variable, innerClass, context)) {
|
||||
return null;
|
||||
}
|
||||
final String description = JavaErrorMessages.message("variable.must.be.final", context.getText());
|
||||
|
||||
final HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, context, description);
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, new VariableAccessFromInnerClassFix(variable, innerClass));
|
||||
@@ -706,33 +711,11 @@ public class HighlightControlFlowUtil {
|
||||
} else {
|
||||
final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(context, PsiLambdaExpression.class);
|
||||
if (lambdaExpression != null && !PsiTreeUtil.isAncestor(lambdaExpression, variable, true)) {
|
||||
boolean effectivelyFinal;
|
||||
if (variable instanceof PsiParameter) {
|
||||
final PsiElement parent = variable.getParent();
|
||||
if (parent instanceof PsiParameterList && parent.getParent() == lambdaExpression) {
|
||||
return null;
|
||||
}
|
||||
effectivelyFinal = notAccessedForWriting(variable, new LocalSearchScope(((PsiParameter)variable).getDeclarationScope()));
|
||||
} else {
|
||||
final ControlFlow controlFlow;
|
||||
try {
|
||||
controlFlow = getControlFlow(PsiUtil.getVariableCodeBlock(variable, context));
|
||||
}
|
||||
catch (AnalysisCanceledException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (ControlFlowUtil.isVariableDefinitelyAssigned(variable, controlFlow)) {
|
||||
final Collection<ControlFlowUtil.VariableInfo> initializedTwice = ControlFlowUtil.getInitializedTwice(controlFlow);
|
||||
effectivelyFinal = !initializedTwice.contains(new ControlFlowUtil.VariableInfo(variable, null));
|
||||
if (effectivelyFinal) {
|
||||
effectivelyFinal = notAccessedForWriting(variable, new LocalSearchScope(lambdaExpression));
|
||||
}
|
||||
} else {
|
||||
effectivelyFinal = false;
|
||||
}
|
||||
final PsiElement parent = variable.getParent();
|
||||
if (parent instanceof PsiParameterList && parent.getParent() == lambdaExpression) {
|
||||
return null;
|
||||
}
|
||||
if (!effectivelyFinal ) {
|
||||
if (!isEffectivelyFinal(variable, lambdaExpression, context)) {
|
||||
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, context, "Variable used in lambda expression should be effectively final");
|
||||
}
|
||||
}
|
||||
@@ -740,6 +723,32 @@ public class HighlightControlFlowUtil {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean isEffectivelyFinal(PsiVariable variable, PsiElement scope, PsiJavaCodeReferenceElement context) {
|
||||
boolean effectivelyFinal;
|
||||
if (variable instanceof PsiParameter) {
|
||||
effectivelyFinal = notAccessedForWriting(variable, new LocalSearchScope(((PsiParameter)variable).getDeclarationScope()));
|
||||
} else {
|
||||
final ControlFlow controlFlow;
|
||||
try {
|
||||
controlFlow = getControlFlow(PsiUtil.getVariableCodeBlock(variable, context));
|
||||
}
|
||||
catch (AnalysisCanceledException e) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ControlFlowUtil.isVariableDefinitelyAssigned(variable, controlFlow)) {
|
||||
final Collection<ControlFlowUtil.VariableInfo> initializedTwice = ControlFlowUtil.getInitializedTwice(controlFlow);
|
||||
effectivelyFinal = !initializedTwice.contains(new ControlFlowUtil.VariableInfo(variable, null));
|
||||
if (effectivelyFinal) {
|
||||
effectivelyFinal = notAccessedForWriting(variable, new LocalSearchScope(scope));
|
||||
}
|
||||
} else {
|
||||
effectivelyFinal = false;
|
||||
}
|
||||
}
|
||||
return effectivelyFinal;
|
||||
}
|
||||
|
||||
private static boolean notAccessedForWriting(PsiVariable variable, final LocalSearchScope searchScope) {
|
||||
for (PsiReference reference : ReferencesSearch.search(variable, searchScope)) {
|
||||
final PsiElement element = reference.getElement();
|
||||
|
||||
+4
-4
@@ -17,9 +17,7 @@ package com.intellij.codeInsight.daemon.impl.quickfix;
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightUtilBase;
|
||||
import com.intellij.codeInsight.daemon.QuickFixBundle;
|
||||
import com.intellij.codeInsight.generation.ConstructorBodyGenerator;
|
||||
import com.intellij.codeInsight.generation.GenerateMembersUtil;
|
||||
import com.intellij.codeInsight.generation.PsiMethodMember;
|
||||
import com.intellij.codeInsight.generation.*;
|
||||
import com.intellij.codeInsight.intention.impl.BaseIntentionAction;
|
||||
import com.intellij.ide.util.MemberChooser;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
@@ -147,7 +145,9 @@ public class CreateConstructorMatchingSuperFix extends BaseIntentionAction {
|
||||
}
|
||||
derived = (PsiMethod)formatter.reformat(derived);
|
||||
derived = (PsiMethod)JavaCodeStyleManager.getInstance(project).shortenClassReferences(derived);
|
||||
derived = (PsiMethod)GenerateMembersUtil.insert(targetClass, derived, null, true);
|
||||
PsiGenerationInfo<PsiMethod> info = OverrideImplementUtil.createGenerationInfo(derived);
|
||||
info.insert(targetClass, null, true);
|
||||
derived = info.getPsiMember();
|
||||
}
|
||||
if (derived != null) {
|
||||
editor.getCaretModel().moveToOffset(derived.getTextRange().getStartOffset());
|
||||
|
||||
+18
-7
@@ -78,20 +78,31 @@ public class NullableStuffInspection extends BaseLocalInspectionTool {
|
||||
if (!PsiUtil.isLanguageLevel5OrHigher(expression) || !REPORT_NULLS_PASSED_TO_NON_ANNOTATED_METHOD) return;
|
||||
final PsiMethod psiMethod = expression.resolveMethod();
|
||||
if (psiMethod != null && (psiMethod.getManager().isInProject(psiMethod) || CodeStyleSettingsManager.getInstance().getCurrentSettings().USE_EXTERNAL_ANNOTATIONS)) {
|
||||
final NullableNotNullManager nullableNotNullManager = NullableNotNullManager.getInstance(holder.getProject());
|
||||
final PsiClass annotationsClass =
|
||||
JavaPsiFacade.getInstance(holder.getProject()).findClass(nullableNotNullManager.getDefaultNullable(), psiMethod.getResolveScope());
|
||||
if (annotationsClass == null) return;
|
||||
final PsiParameterList parameterList = psiMethod.getParameterList();
|
||||
final PsiParameter[] parameters = parameterList.getParameters();
|
||||
final PsiExpression[] expressions = expression.getArgumentList().getExpressions();
|
||||
for (int i = 0, expressionsLength = expressions.length; i < Math.min(expressionsLength, parameters.length); i++) {
|
||||
PsiExpression psiExpression = expressions[i];
|
||||
if (psiExpression.getType() == PsiType.NULL) {
|
||||
boolean nullablePassedAsParameter = false;
|
||||
if (psiExpression instanceof PsiMethodCallExpression) {
|
||||
final PsiMethod method = expression.resolveMethod();
|
||||
nullablePassedAsParameter = nullableNotNullManager.isNullable(method, false);
|
||||
} else if (psiExpression instanceof PsiReferenceExpression) {
|
||||
final PsiElement resolve = ((PsiReferenceExpression)psiExpression).resolve();
|
||||
if (resolve instanceof PsiModifierListOwner) {
|
||||
nullablePassedAsParameter = nullableNotNullManager.isNullable((PsiModifierListOwner)resolve, false);
|
||||
}
|
||||
}
|
||||
final PsiType exprType = psiExpression.getType();
|
||||
if (exprType == PsiType.NULL || nullablePassedAsParameter) {
|
||||
final PsiParameter parameter = parameters[i];
|
||||
if (!NullableNotNullManager.isNullable(parameter) && !NullableNotNullManager.isNotNull(parameter)) {
|
||||
final PsiClass annotationsClass =
|
||||
JavaPsiFacade.getInstance(holder.getProject()).findClass(NullableNotNullManager.getInstance(holder.getProject()).getDefaultNullable(),
|
||||
psiMethod.getResolveScope());
|
||||
if (annotationsClass != null) {
|
||||
holder.registerProblem(psiExpression, "Null is passed to parameter which is not yet @Nullable", new MyAddNullableAnnotationFix(parameter));
|
||||
}
|
||||
holder.registerProblem(psiExpression, "Nullable value is passed to parameter which is not yet @Nullable",
|
||||
new MyAddNullableAnnotationFix(parameter));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -356,7 +356,7 @@ public class RefMethodImpl extends RefJavaElementImpl implements RefMethod {
|
||||
}
|
||||
|
||||
public boolean hasSuperMethods() {
|
||||
return !getSuperMethods().isEmpty() || isLibraryOverride(new HashSet<RefMethod>());
|
||||
return !getSuperMethods().isEmpty() || isExternalOverride();
|
||||
}
|
||||
|
||||
public boolean isReferenced() {
|
||||
|
||||
+6
-2
@@ -30,6 +30,7 @@ import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.refactoring.changeSignature.ChangeSignatureProcessor;
|
||||
import com.intellij.refactoring.changeSignature.ParameterInfoImpl;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -56,16 +57,19 @@ public class UnusedReturnValue extends GlobalJavaInspectionTool{
|
||||
final RefMethod refMethod = (RefMethod)refEntity;
|
||||
|
||||
if (refMethod.isConstructor()) return null;
|
||||
if (refMethod.hasSuperMethods()) return null;
|
||||
if (!refMethod.getSuperMethods().isEmpty()) return null;
|
||||
if (refMethod.getInReferences().size() == 0) return null;
|
||||
|
||||
if (!refMethod.isReturnValueUsed()) {
|
||||
final PsiMethod psiMethod = (PsiMethod)refMethod.getElement();
|
||||
if (IGNORE_BUILDER_PATTERN && PropertyUtil.isSimplePropertySetter(psiMethod)) return null;
|
||||
|
||||
final boolean isNative = psiMethod.hasModifierProperty(PsiModifier.NATIVE);
|
||||
if (refMethod.isExternalOverride() && !isNative) return null;
|
||||
return new ProblemDescriptor[]{manager.createProblemDescriptor(psiMethod.getNavigationElement(),
|
||||
InspectionsBundle
|
||||
.message("inspection.unused.return.value.problem.descriptor"),
|
||||
getFix(processor), ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
|
||||
!isNative ? getFix(processor) : null, ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
|
||||
false)};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,6 +130,7 @@ public abstract class NonClasspathClassFinder extends PsiElementFinder {
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<String> getClassNames(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) {
|
||||
final List<VirtualFile> classRoots = getClassRoots();
|
||||
@@ -177,7 +178,7 @@ public abstract class NonClasspathClassFinder extends PsiElementFinder {
|
||||
@Override
|
||||
public boolean processPackageDirectories(@NotNull PsiPackage psiPackage,
|
||||
@NotNull GlobalSearchScope scope,
|
||||
Processor<PsiDirectory> consumer) {
|
||||
@NotNull Processor<PsiDirectory> consumer) {
|
||||
final List<VirtualFile> classRoots = getClassRoots();
|
||||
if (classRoots.isEmpty()) {
|
||||
return true;
|
||||
|
||||
@@ -106,6 +106,7 @@ public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>,
|
||||
for (ArrangementModifier modifier : visibility) {
|
||||
and(FIELD, modifier);
|
||||
}
|
||||
and(FIELD);
|
||||
and(CONSTRUCTOR);
|
||||
and(METHOD, STATIC);
|
||||
and(METHOD);
|
||||
|
||||
@@ -135,7 +135,7 @@ public abstract class JavaPsiFacade {
|
||||
* @param packageName the package name to check.
|
||||
* @return true if it is part of the package prefix, false otherwise.
|
||||
*/
|
||||
public abstract boolean isPartOfPackagePrefix(String packageName);
|
||||
public abstract boolean isPartOfPackagePrefix(@NotNull String packageName);
|
||||
|
||||
/**
|
||||
* Checks if the specified PSI element belongs to the specified package.
|
||||
@@ -155,5 +155,6 @@ public abstract class JavaPsiFacade {
|
||||
*/
|
||||
public abstract boolean arePackagesTheSame(@NotNull PsiElement element1, @NotNull PsiElement element2);
|
||||
|
||||
@NotNull
|
||||
public abstract Project getProject();
|
||||
}
|
||||
|
||||
@@ -97,11 +97,13 @@ public abstract class PsiElementFinder {
|
||||
return PsiClass.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Set<String> getClassNames(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) {
|
||||
return getClassNames(getClasses(psiPackage, scope));
|
||||
}
|
||||
|
||||
protected static Set<String> getClassNames(PsiClass[] classes) {
|
||||
@NotNull
|
||||
protected static Set<String> getClassNames(@NotNull PsiClass[] classes) {
|
||||
if (classes.length == 0) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
@@ -113,7 +115,7 @@ public abstract class PsiElementFinder {
|
||||
return names;
|
||||
}
|
||||
|
||||
public boolean processPackageDirectories(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope, Processor<PsiDirectory> consumer) {
|
||||
public boolean processPackageDirectories(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope, @NotNull Processor<PsiDirectory> consumer) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,9 +79,9 @@ public class TypesDistinctProver {
|
||||
return proveArrayTypeDistinct(((PsiWildcardType)type1).getManager().getProject(), (PsiArrayType)type2, type1);
|
||||
}
|
||||
}
|
||||
if (type1 instanceof PsiCapturedWildcardType) return provablyDistinct(((PsiCapturedWildcardType)type1).getWildcard(), type2, level +1);
|
||||
if (type1 instanceof PsiCapturedWildcardType) return provablyDistinct(((PsiCapturedWildcardType)type1).getWildcard(), type2, level);
|
||||
|
||||
if (type2 instanceof PsiWildcardType || type2 instanceof PsiCapturedWildcardType) return provablyDistinct(type2, type1, level +1);
|
||||
if (type2 instanceof PsiWildcardType || type2 instanceof PsiCapturedWildcardType) return provablyDistinct(type2, type1, level);
|
||||
|
||||
|
||||
final PsiClassType.ClassResolveResult classResolveResult1 = PsiUtil.resolveGenericsClassInType(type1);
|
||||
|
||||
@@ -22,6 +22,7 @@ package com.intellij.psi.impl;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFileFilter;
|
||||
import com.intellij.psi.JavaPsiFacade;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
|
||||
public abstract class JavaPsiFacadeEx extends JavaPsiFacade {
|
||||
@@ -30,5 +31,5 @@ public abstract class JavaPsiFacadeEx extends JavaPsiFacade {
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
public abstract void setAssertOnFileLoadingFilter(final VirtualFileFilter filter);
|
||||
public abstract void setAssertOnFileLoadingFilter(@NotNull VirtualFileFilter filter);
|
||||
}
|
||||
@@ -34,7 +34,7 @@ import com.intellij.psi.impl.source.resolve.FileContextUtil;
|
||||
import com.intellij.psi.impl.source.tree.JavaElementType;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.util.ConcurrencyUtil;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.SmartList;
|
||||
@@ -43,6 +43,7 @@ import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import com.intellij.util.messages.MessageBus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
@@ -51,7 +52,7 @@ import java.util.concurrent.ConcurrentMap;
|
||||
* @author max
|
||||
*/
|
||||
public class JavaPsiFacadeImpl extends JavaPsiFacadeEx {
|
||||
private ArrayList<PsiElementFinder> myElementFinders;
|
||||
private PsiElementFinder[] myElementFinders; //benign data race
|
||||
private final PsiNameHelper myNameHelper;
|
||||
private final PsiConstantEvaluationHelper myConstantEvaluationHelper;
|
||||
private final ConcurrentMap<String, PsiPackage> myPackageCache = new ConcurrentHashMap<String, PsiPackage>();
|
||||
@@ -102,9 +103,9 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx {
|
||||
ProgressIndicatorProvider.checkCanceled(); // We hope this method is being called often enough to cancel daemon processes smoothly
|
||||
|
||||
if (DumbService.getInstance(getProject()).isDumb()) {
|
||||
final List<PsiClass> classes = findClassesInDumbMode(qualifiedName, scope);
|
||||
if (!classes.isEmpty()) {
|
||||
return classes.get(0);
|
||||
PsiClass[] classes = findClassesInDumbMode(qualifiedName, scope);
|
||||
if (classes.length != 0) {
|
||||
return classes[0];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -118,42 +119,46 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private List<PsiClass> findClassesInDumbMode(String qualifiedName, GlobalSearchScope scope) {
|
||||
private PsiClass[] findClassesInDumbMode(@NotNull String qualifiedName, @NotNull GlobalSearchScope scope) {
|
||||
final String packageName = StringUtil.getPackageName(qualifiedName);
|
||||
final PsiPackage pkg = findPackage(packageName);
|
||||
final String className = StringUtil.getShortName(qualifiedName);
|
||||
if (pkg == null && packageName.length() < qualifiedName.length()) {
|
||||
final List<PsiClass> containingClasses = findClassesInDumbMode(packageName, scope);
|
||||
if (containingClasses.size() == 1) {
|
||||
return filterByName(className, containingClasses.get(0).getInnerClasses());
|
||||
PsiClass[] containingClasses = findClassesInDumbMode(packageName, scope);
|
||||
if (containingClasses.length == 1) {
|
||||
return filterByName(className, containingClasses[0].getInnerClasses());
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
return PsiClass.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
if (pkg == null || !pkg.containsClassNamed(className)) {
|
||||
return Collections.emptyList();
|
||||
return PsiClass.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
return filterByName(className, pkg.getClasses(scope));
|
||||
}
|
||||
|
||||
private static List<PsiClass> filterByName(String className, PsiClass[] classes) {
|
||||
final List<PsiClass> foundClasses = new SmartList<PsiClass>();
|
||||
@NotNull
|
||||
private static PsiClass[] filterByName(@NotNull String className, @NotNull PsiClass[] classes) {
|
||||
if (classes.length == 0) return PsiClass.EMPTY_ARRAY;
|
||||
if (classes.length == 1) {
|
||||
return className.equals(classes[0].getName()) ? classes : PsiClass.EMPTY_ARRAY;
|
||||
}
|
||||
List<PsiClass> foundClasses = new SmartList<PsiClass>();
|
||||
for (PsiClass psiClass : classes) {
|
||||
if (className.equals(psiClass.getName())) {
|
||||
foundClasses.add(psiClass);
|
||||
}
|
||||
}
|
||||
return foundClasses;
|
||||
return foundClasses.isEmpty() ? PsiClass.EMPTY_ARRAY : foundClasses.toArray(new PsiClass[foundClasses.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public PsiClass[] findClasses(@NotNull String qualifiedName, @NotNull GlobalSearchScope scope) {
|
||||
if (DumbService.getInstance(getProject()).isDumb()) {
|
||||
final List<PsiClass> classes = findClassesInDumbMode(qualifiedName, scope);
|
||||
return classes.toArray(new PsiClass[classes.size()]);
|
||||
return findClassesInDumbMode(qualifiedName, scope);
|
||||
}
|
||||
|
||||
List<PsiClass> classes = new SmartList<PsiClass>();
|
||||
@@ -165,8 +170,9 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx {
|
||||
return classes.toArray(new PsiClass[classes.size()]);
|
||||
}
|
||||
|
||||
private ArrayList<PsiElementFinder> finders() {
|
||||
ArrayList<PsiElementFinder> answer = myElementFinders;
|
||||
@NotNull
|
||||
private PsiElementFinder[] finders() {
|
||||
PsiElementFinder[] answer = myElementFinders;
|
||||
if (answer == null) {
|
||||
answer = calcFinders();
|
||||
myElementFinders = answer;
|
||||
@@ -175,11 +181,12 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx {
|
||||
return answer;
|
||||
}
|
||||
|
||||
private ArrayList<PsiElementFinder> calcFinders() {
|
||||
ArrayList<PsiElementFinder> elementFinders = new ArrayList<PsiElementFinder>();
|
||||
@NotNull
|
||||
private PsiElementFinder[] calcFinders() {
|
||||
List<PsiElementFinder> elementFinders = new ArrayList<PsiElementFinder>();
|
||||
elementFinders.add(new PsiElementFinderImpl());
|
||||
ContainerUtil.addAll(elementFinders, myProject.getExtensions(PsiElementFinder.EP_NAME));
|
||||
return elementFinders;
|
||||
return elementFinders.toArray(new PsiElementFinder[elementFinders.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -205,16 +212,18 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx {
|
||||
return null;
|
||||
}
|
||||
|
||||
private List<PsiElementFinder> filteredFinders() {
|
||||
@NotNull
|
||||
private PsiElementFinder[] filteredFinders() {
|
||||
DumbService dumbService = DumbService.getInstance(getProject());
|
||||
List<PsiElementFinder> finders = finders();
|
||||
PsiElementFinder[] finders = finders();
|
||||
if (dumbService.isDumb()) {
|
||||
finders = dumbService.filterByDumbAwareness(finders);
|
||||
List<PsiElementFinder> list = dumbService.filterByDumbAwareness(Arrays.asList(finders));
|
||||
finders = list.toArray(new PsiElementFinder[list.size()]);
|
||||
}
|
||||
return finders;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
@NotNull
|
||||
public PsiJavaParserFacade getParserFacade() {
|
||||
return getElementFactory(); // TODO: lighter implementation which doesn't mark all the elements as generated.
|
||||
@@ -232,7 +241,8 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx {
|
||||
return myNameHelper;
|
||||
}
|
||||
|
||||
public Set<String> getClassNames(PsiPackage psiPackage, GlobalSearchScope scope) {
|
||||
@NotNull
|
||||
public Set<String> getClassNames(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) {
|
||||
Set<String> result = new HashSet<String>();
|
||||
for (PsiElementFinder finder : filteredFinders()) {
|
||||
result.addAll(finder.getClassNames(psiPackage, scope));
|
||||
@@ -240,7 +250,8 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx {
|
||||
return result;
|
||||
}
|
||||
|
||||
public PsiClass[] getClasses(PsiPackage psiPackage, GlobalSearchScope scope) {
|
||||
@NotNull
|
||||
public PsiClass[] getClasses(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) {
|
||||
List<PsiClass> result = null;
|
||||
for (PsiElementFinder finder : filteredFinders()) {
|
||||
PsiClass[] classes = finder.getClasses(psiPackage, scope);
|
||||
@@ -252,7 +263,7 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx {
|
||||
return result == null ? PsiClass.EMPTY_ARRAY : result.toArray(new PsiClass[result.size()]);
|
||||
}
|
||||
|
||||
public boolean processPackageDirectories(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope, Processor<PsiDirectory> consumer) {
|
||||
public boolean processPackageDirectories(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope, @NotNull Processor<PsiDirectory> consumer) {
|
||||
for (PsiElementFinder finder : filteredFinders()) {
|
||||
if (!finder.processPackageDirectories(psiPackage, scope, consumer)) {
|
||||
return false;
|
||||
@@ -261,7 +272,8 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx {
|
||||
return true;
|
||||
}
|
||||
|
||||
public PsiPackage[] getSubPackages(PsiPackage psiPackage, GlobalSearchScope scope) {
|
||||
@NotNull
|
||||
public PsiPackage[] getSubPackages(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) {
|
||||
LinkedHashSet<PsiPackage> result = new LinkedHashSet<PsiPackage>();
|
||||
for (PsiElementFinder finder : filteredFinders()) {
|
||||
PsiPackage[] packages = finder.getSubPackages(psiPackage, scope);
|
||||
@@ -334,8 +346,8 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx {
|
||||
ContainerUtil.quickSort(list, new Comparator<PsiClass>() {
|
||||
@Override
|
||||
public int compare(PsiClass o1, PsiClass o2) {
|
||||
VirtualFile file2 = PsiUtil.getVirtualFile(o2);
|
||||
VirtualFile file1 = PsiUtil.getVirtualFile(o1);
|
||||
VirtualFile file2 = PsiUtilCore.getVirtualFile(o2);
|
||||
VirtualFile file1 = PsiUtilCore.getVirtualFile(o1);
|
||||
return scope.compare(file2, file1);
|
||||
}
|
||||
});
|
||||
@@ -343,6 +355,7 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx {
|
||||
return list.toArray(new PsiClass[list.size()]);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<String> getClassNames(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) {
|
||||
Set<String> names = null;
|
||||
@@ -362,7 +375,7 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processPackageDirectories(@NotNull PsiPackage psiPackage, @NotNull final GlobalSearchScope scope, final Processor<PsiDirectory> consumer) {
|
||||
public boolean processPackageDirectories(@NotNull PsiPackage psiPackage, @NotNull final GlobalSearchScope scope, @NotNull final Processor<PsiDirectory> consumer) {
|
||||
final PsiManager psiManager = PsiManager.getInstance(getProject());
|
||||
PackageIndex.getInstance(getProject()).getDirsByPackageName(psiPackage.getQualifiedName(), false).forEach(new ReadActionProcessor<VirtualFile>() {
|
||||
@Override
|
||||
@@ -378,7 +391,7 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx {
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isPartOfPackagePrefix(String packageName) {
|
||||
public boolean isPartOfPackagePrefix(@NotNull String packageName) {
|
||||
final Collection<String> packagePrefixes = myFileManager.getNonTrivialPackagePrefixes();
|
||||
for (final String subpackageName : packagePrefixes) {
|
||||
if (isSubpackageOf(subpackageName, packageName)) return true;
|
||||
@@ -386,7 +399,7 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isSubpackageOf(final String subpackageName, String packageName) {
|
||||
private static boolean isSubpackageOf(@NotNull String subpackageName, @NotNull String packageName) {
|
||||
return subpackageName.equals(packageName) ||
|
||||
subpackageName.startsWith(packageName) && subpackageName.charAt(packageName.length()) == '.';
|
||||
}
|
||||
@@ -423,6 +436,7 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx {
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Project getProject() {
|
||||
return myProject;
|
||||
}
|
||||
@@ -433,8 +447,9 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx {
|
||||
return PsiElementFactory.SERVICE.getInstance(myProject);
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
@Override
|
||||
public void setAssertOnFileLoadingFilter(final VirtualFileFilter filter) {
|
||||
public void setAssertOnFileLoadingFilter(@NotNull final VirtualFileFilter filter) {
|
||||
((PsiManagerImpl)PsiManager.getInstance(myProject)).setAssertOnFileLoadingFilter(filter);
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -145,9 +145,9 @@ public class PsiCatchSectionImpl extends CompositePsiElement implements PsiCatch
|
||||
if (catchBlock != null) {
|
||||
catchBlock.accept(new JavaRecursiveElementWalkingVisitor() {
|
||||
@Override
|
||||
public void visitAssignmentExpression(final PsiAssignmentExpression expression) {
|
||||
final PsiExpression left = expression.getLExpression();
|
||||
if (left instanceof PsiReferenceExpression && parameter.equals(((PsiReferenceExpression)left).resolve())) {
|
||||
public void visitReferenceExpression(PsiReferenceExpression expression) {
|
||||
super.visitReferenceExpression(expression);
|
||||
if (expression.resolve() == parameter && PsiUtil.isAccessedForWriting(expression)) {
|
||||
result[0] = false;
|
||||
stopWalking();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright 2000-2009 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.scope.processor;
|
||||
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.ResolveState;
|
||||
import com.intellij.psi.scope.ElementClassHint;
|
||||
import com.intellij.psi.scope.NameHint;
|
||||
import com.intellij.psi.scope.PsiScopeProcessor;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Dmitry Avdeev
|
||||
*/
|
||||
public class MethodResolveProcessor implements PsiScopeProcessor, ElementClassHint, NameHint {
|
||||
|
||||
private final String myNameHint;
|
||||
private final List<PsiMethod> myMethods = new ArrayList<PsiMethod>();
|
||||
|
||||
public MethodResolveProcessor() {
|
||||
myNameHint = null;
|
||||
}
|
||||
|
||||
public MethodResolveProcessor(final String name) {
|
||||
myNameHint = name;
|
||||
}
|
||||
|
||||
public PsiMethod[] getMethods() {
|
||||
return myMethods.toArray(new PsiMethod[myMethods.size()]);
|
||||
}
|
||||
|
||||
public boolean execute(@NotNull PsiElement element, ResolveState state) {
|
||||
if (element instanceof PsiMethod) {
|
||||
ContainerUtil.addIfNotNull(myMethods, (PsiMethod)element);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public <T> T getHint(@NotNull Key<T> hintKey) {
|
||||
if (hintKey == ElementClassHint.KEY) {
|
||||
return (T)this;
|
||||
}
|
||||
if (hintKey == NameHint.KEY && myNameHint != null) {
|
||||
return (T)this;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void handleEvent(Event event, Object associated) {
|
||||
}
|
||||
|
||||
public boolean shouldProcess(DeclarationKind kind) {
|
||||
return kind == DeclarationKind.METHOD;
|
||||
}
|
||||
|
||||
public static PsiMethod[] findMethod(PsiClass psiClass, String methodName) {
|
||||
MethodResolveProcessor processor = new MethodResolveProcessor(methodName);
|
||||
psiClass.processDeclarations(processor, ResolveState.initial(), null, psiClass);
|
||||
return processor.getMethods();
|
||||
}
|
||||
|
||||
public static PsiMethod[] getAllMethods(PsiClass psiClass) {
|
||||
MethodResolveProcessor processor = new MethodResolveProcessor();
|
||||
psiClass.processDeclarations(processor, ResolveState.initial(), null, psiClass);
|
||||
return processor.getMethods();
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getName(ResolveState state) {
|
||||
return myNameHint;
|
||||
}
|
||||
}
|
||||
+12
@@ -231,4 +231,16 @@ class IDEA91481 {
|
||||
class BeanBuilder<<warning descr="Type parameter 'T' is never used">T</warning>> {}
|
||||
class Bean {}
|
||||
class DirectBean extends Bean {}
|
||||
}
|
||||
|
||||
class IDEA89640 {
|
||||
interface X {}
|
||||
class Y<<warning descr="Type parameter 'T' is never used">T</warning> extends X> {}
|
||||
|
||||
public static void main(String[] args) {
|
||||
Y<? extends X> a = null;
|
||||
Y<? extends X> b = null;
|
||||
boolean flag = a != b;
|
||||
System.out.println(flag);
|
||||
}
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
// "Change 'implements Runnable' to 'extends Runnable'" "true"
|
||||
interface a extends Runnable {
|
||||
}
|
||||
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
// "Change 'implements Runnable' to 'extends Runnable'" "true"
|
||||
interface a implements <caret>Runnable {
|
||||
}
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
// "Make 'i' final" "false"
|
||||
import java.io.*;
|
||||
|
||||
class a {
|
||||
void f() {
|
||||
int i = 0;
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
int ii = <caret>i;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<problems>
|
||||
<problem>
|
||||
<file>Test.java</file>
|
||||
<line>2</line>
|
||||
<description>Return value of the method is never used</description>
|
||||
</problem>
|
||||
</problems>
|
||||
@@ -0,0 +1,7 @@
|
||||
class Test {
|
||||
private static native boolean isUnused();
|
||||
|
||||
public static void main(String[] args) {
|
||||
Test.isUnused();
|
||||
}
|
||||
}
|
||||
+11
-21
@@ -145,23 +145,18 @@ public class ArrangementRuleEditingModelImplTest extends AbstractArrangementRule
|
||||
|
||||
modelToChange.removeAndCondition(atom(PUBLIC));
|
||||
|
||||
assertSame(1, modelToChange.getRow());
|
||||
assertEquals(atom(FIELD), modelToChange.getCondition());
|
||||
|
||||
assertSame(3, siblingModel.getRow());
|
||||
assertEquals(and(atom(FIELD), atom(STATIC)), siblingModel.getCondition());
|
||||
|
||||
ArrangementTreeNode atomFieldNode = myRoot.getFirstChild();
|
||||
assertNotNull(atomFieldNode);
|
||||
assertEquals(atom(FIELD), atomFieldNode.getBackingCondition());
|
||||
ArrangementTreeNode fieldNode = myRoot.getFirstChild();
|
||||
assertNotNull(fieldNode);
|
||||
assertEquals(atom(FIELD), fieldNode.getBackingCondition());
|
||||
|
||||
ArrangementTreeNode layeredFieldNode = atomFieldNode.getNextSibling();
|
||||
assertNotNull(atomFieldNode);
|
||||
assertEquals(atom(FIELD), atomFieldNode.getBackingCondition());
|
||||
|
||||
ArrangementTreeNode staticNode = layeredFieldNode.getFirstChild();
|
||||
ArrangementTreeNode staticNode = fieldNode.getFirstChild();
|
||||
assertNotNull(staticNode);
|
||||
assertEquals(atom(STATIC), staticNode.getBackingCondition());
|
||||
|
||||
assertNull(staticNode.getNextNode());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -182,20 +177,15 @@ public class ArrangementRuleEditingModelImplTest extends AbstractArrangementRule
|
||||
assertSame(siblingModel, myRowMappings.get(2));
|
||||
assertEquals(and(atom(FIELD), atom(PUBLIC)), siblingModel.getCondition());
|
||||
|
||||
assertSame(modelToChange, myRowMappings.get(3));
|
||||
assertEquals(atom(FIELD), modelToChange.getCondition());
|
||||
ArrangementTreeNode fieldNode = myRoot.getFirstChild();
|
||||
assertNotNull(fieldNode);
|
||||
assertEquals(atom(FIELD), fieldNode.getBackingCondition());
|
||||
|
||||
ArrangementTreeNode compositeFieldNode = myRoot.getFirstChild();
|
||||
assertNotNull(compositeFieldNode);
|
||||
assertEquals(atom(FIELD), compositeFieldNode.getBackingCondition());
|
||||
|
||||
ArrangementTreeNode publicNode = compositeFieldNode.getFirstChild();
|
||||
ArrangementTreeNode publicNode = fieldNode.getFirstChild();
|
||||
assertNotNull(publicNode);
|
||||
assertEquals(atom(PUBLIC), publicNode.getBackingCondition());
|
||||
|
||||
ArrangementTreeNode atomFieldNode = compositeFieldNode.getNextSibling();
|
||||
assertNotNull(atomFieldNode);
|
||||
assertEquals(atom(FIELD), atomFieldNode.getBackingCondition());
|
||||
assertNull(publicNode.getNextNode());
|
||||
}
|
||||
|
||||
private void checkModelTreeNodesConsistency(@NotNull ArrangementRuleEditingModelImpl model) {
|
||||
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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.openapi.application.ApplicationManager;
|
||||
|
||||
/**
|
||||
* User: anna
|
||||
*/
|
||||
public class VariableAccessFromInnerClass18Test extends LightQuickFixTestCase {
|
||||
public void test() throws Exception {
|
||||
doAllTests();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getBasePath() {
|
||||
return "/codeInsight/daemonCodeAnalyzer/quickFix/mustBeFinal18";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void beforeActionStarted(String testName, String contents) {
|
||||
for (int i=0;i<10;i++) {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myEditor.getDocument().insertString(myEditor.getCaretModel().getOffset(), "//");
|
||||
}
|
||||
});
|
||||
|
||||
doHighlighting();
|
||||
delete();
|
||||
delete();
|
||||
doHighlighting();
|
||||
}
|
||||
}
|
||||
}
|
||||
+7
-22
@@ -1,33 +1,18 @@
|
||||
|
||||
package com.intellij.codeInsight.daemon.quickFix;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
|
||||
public class VariableAccessFromInnerClassTest extends LightQuickFixTestCase {
|
||||
public void test() throws Exception {
|
||||
doAllTests();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void beforeActionStarted(String testName, String contents) {
|
||||
for (int i=0;i<10;i++) {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myEditor.getDocument().insertString(myEditor.getCaretModel().getOffset(), "//");
|
||||
}
|
||||
});
|
||||
|
||||
doHighlighting();
|
||||
delete();
|
||||
delete();
|
||||
doHighlighting();
|
||||
}
|
||||
}
|
||||
public class VariableAccessFromInnerClassTest extends VariableAccessFromInnerClass18Test {
|
||||
|
||||
@Override
|
||||
protected String getBasePath() {
|
||||
return "/codeInsight/daemonCodeAnalyzer/quickFix/mustBeFinal";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LanguageLevel getLanguageLevel() {
|
||||
return LanguageLevel.JDK_1_7;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -268,7 +268,7 @@ public class InspectionProfileTest extends LightIdeaTestCase {
|
||||
for (ScopeToolState tool : tools) {
|
||||
InspectionProfileEntry entry = tool.getTool();
|
||||
assertTrue(entry instanceof InspectionToolWrapper);
|
||||
if (entry.isInitialized() && ((InspectionToolWrapper)entry).hasXmlMapping()) {
|
||||
if (entry.isInitialized()) {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,10 @@ public class UnusedReturnValueTest extends InspectionTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testNative() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testHierarchy() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
@@ -486,6 +486,10 @@ public abstract class VirtualFile extends UserDataHolderBase implements Modifica
|
||||
}
|
||||
|
||||
public void setCharset(final Charset charset) {
|
||||
setCharset(charset, null);
|
||||
}
|
||||
|
||||
public void setCharset(final Charset charset, @Nullable Runnable whenChanged) {
|
||||
final Charset old = getUserData(CHARSET_KEY);
|
||||
putUserData(CHARSET_KEY, charset);
|
||||
if (Comparing.equal(charset, old)) return;
|
||||
@@ -497,6 +501,7 @@ public abstract class VirtualFile extends UserDataHolderBase implements Modifica
|
||||
setBOM(bom);
|
||||
|
||||
if (old != null) { //do not send on detect
|
||||
if (whenChanged != null) whenChanged.run();
|
||||
VirtualFileManager.getInstance().notifyPropertyChanged(this, PROP_ENCODING, old, charset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.ref.Reference;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
@@ -46,7 +47,7 @@ public class JarHandlerBase {
|
||||
private static final long DEFAULT_TIMESTAMP = -1L;
|
||||
|
||||
private final TimedReference<JarFile> myJarFile = new TimedReference<JarFile>(null);
|
||||
private SoftReference<Map<String, EntryInfo>> myRelPathsToEntries = new SoftReference<Map<String, EntryInfo>>(null);
|
||||
private Reference<Map<String, EntryInfo>> myRelPathsToEntries = new SoftReference<Map<String, EntryInfo>>(null);
|
||||
private final Object lock = new Object();
|
||||
|
||||
protected final String myBasePath;
|
||||
@@ -59,7 +60,7 @@ public class JarHandlerBase {
|
||||
public EntryInfo(final String shortName, final EntryInfo parent, final boolean directory) {
|
||||
this.shortName = shortName;
|
||||
this.parent = parent;
|
||||
this.isDirectory = directory;
|
||||
isDirectory = directory;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +89,7 @@ public class JarHandlerBase {
|
||||
while (entries.hasMoreElements()) {
|
||||
JarFile.JarEntry entry = entries.nextElement();
|
||||
final String name = entry.getName();
|
||||
final boolean isDirectory = name.endsWith("/");
|
||||
final boolean isDirectory = StringUtil.endsWithChar(name, '/');
|
||||
getOrCreate(isDirectory ? name.substring(0, name.length() - 1) : name, isDirectory, map);
|
||||
}
|
||||
|
||||
@@ -105,17 +106,19 @@ public class JarHandlerBase {
|
||||
|
||||
@Nullable
|
||||
public JarFile getJar() {
|
||||
synchronized (lock) {
|
||||
JarFile jar = myJarFile.get();
|
||||
if (jar == null) {
|
||||
jar = createJarFile();
|
||||
if (jar != null) {
|
||||
myJarFile.set(jar);
|
||||
JarFile jar = myJarFile.get();
|
||||
if (jar == null) {
|
||||
synchronized (lock) {
|
||||
jar = myJarFile.get();
|
||||
if (jar == null) {
|
||||
jar = createJarFile();
|
||||
if (jar != null) {
|
||||
myJarFile.set(jar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return jar;
|
||||
}
|
||||
return jar;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -44,6 +44,7 @@ import com.intellij.testFramework.LightVirtualFile;
|
||||
import com.intellij.util.ConcurrencyUtil;
|
||||
import com.intellij.util.containers.ConcurrentSoftValueHashMap;
|
||||
import com.intellij.util.containers.ConcurrentWeakValueHashMap;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.messages.MessageBusConnection;
|
||||
import gnu.trove.THashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -416,7 +417,7 @@ public class FileManagerImpl implements FileManager {
|
||||
List<PsiFile> files = new ArrayList<PsiFile>();
|
||||
for (FileViewProvider provider : myVFileToViewProviderMap.values()) {
|
||||
if (provider instanceof SingleRootFileViewProvider) {
|
||||
files.add(((SingleRootFileViewProvider)provider).getCachedPsi(provider.getBaseLanguage()));
|
||||
ContainerUtil.addIfNotNull(files, ((SingleRootFileViewProvider)provider).getCachedPsi(provider.getBaseLanguage()));
|
||||
}
|
||||
}
|
||||
return files;
|
||||
|
||||
@@ -60,6 +60,7 @@ public abstract class CommandLineState implements RunnableState {
|
||||
return myEnvironment.getExecutionTarget();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ExecutionResult execute(@NotNull final Executor executor, @NotNull final ProgramRunner runner) throws ExecutionException {
|
||||
final ProcessHandler processHandler = startProcess();
|
||||
final ConsoleView console = createConsole(executor);
|
||||
|
||||
@@ -17,12 +17,13 @@
|
||||
package com.intellij.execution.ui;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public interface ObservableConsoleView {
|
||||
|
||||
void addChangeListener(ChangeListener listener, Disposable parent);
|
||||
void addChangeListener(@NotNull ChangeListener listener, @NotNull Disposable parent);
|
||||
|
||||
interface ChangeListener {
|
||||
void contentAdded(Collection<ConsoleViewContentType> types);
|
||||
|
||||
+5
@@ -110,6 +110,11 @@ public class ArrangementAndNodeComponent extends JPanel implements ArrangementNo
|
||||
myScreenBounds = bounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCanvasWidthChange(int width) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(boolean selected) {
|
||||
for (ArrangementNodeComponent component : myComponents) {
|
||||
|
||||
+5
@@ -169,6 +169,11 @@ public class ArrangementAtomNodeComponent implements ArrangementNodeComponent {
|
||||
myScreenBounds = screenBounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCanvasWidthChange(int width) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrangementNodeComponent getNodeComponentAt(@NotNull RelativePoint point) {
|
||||
return (myScreenBounds != null && myScreenBounds.contains(point.getScreenPoint())) ? this : null;
|
||||
|
||||
+24
-5
@@ -34,10 +34,14 @@ import java.awt.event.MouseEvent;
|
||||
* @since 9/12/12 5:39 PM
|
||||
*/
|
||||
public class ArrangementGroupingNodeComponent extends JPanel implements ArrangementNodeComponent {
|
||||
|
||||
|
||||
private static final int TOP_INSET = 3;
|
||||
|
||||
@NotNull private final ArrangementColorsService myColorsService = ServiceManager.getService(ArrangementColorsService.class);
|
||||
@NotNull private final ArrangementAtomMatchCondition myCondition;
|
||||
|
||||
@Nullable private Rectangle myScreenBounds;
|
||||
@NotNull private Dimension myPreferredSize;
|
||||
private boolean mySelected;
|
||||
|
||||
public ArrangementGroupingNodeComponent(@NotNull ArrangementNodeDisplayManager manager,
|
||||
@@ -46,9 +50,9 @@ public class ArrangementGroupingNodeComponent extends JPanel implements Arrangem
|
||||
myCondition = condition;
|
||||
String text = StringUtil.capitalize(StringUtil.pluralize(manager.getDisplayValue(myCondition.getValue())));
|
||||
setLayout(new GridBagLayout());
|
||||
add(new JLabel(String.format("<html><i>%s", text)), new GridBag().anchor(GridBagConstraints.CENTER).weightx(1).insets(0, 12, 0, 0));
|
||||
Dimension size = getPreferredSize();
|
||||
setPreferredSize(new Dimension(manager.getMaxGroupTextWidth() * 5, size.height * 2));
|
||||
GridBag constraints = new GridBag().anchor(GridBagConstraints.WEST).weightx(1).insets(TOP_INSET * 2, 20, 0, 0);
|
||||
add(new JLabel(String.format("<html><i>%s", text)), constraints);
|
||||
myPreferredSize = super.getPreferredSize();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -80,6 +84,21 @@ public class ArrangementGroupingNodeComponent extends JPanel implements Arrangem
|
||||
myScreenBounds = bounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCanvasWidthChange(int width) {
|
||||
if (width > 0 && myPreferredSize.width != width) {
|
||||
myPreferredSize = new Dimension(width - UIUtil.getTreeLeftChildIndent(), myPreferredSize.height);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
return myPreferredSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(boolean selected) {
|
||||
mySelected = selected;
|
||||
@@ -101,7 +120,7 @@ public class ArrangementGroupingNodeComponent extends JPanel implements Arrangem
|
||||
Rectangle bounds = getBounds();
|
||||
g.setColor(UIManager.getColor("Tree.hash"));
|
||||
int cornerX = UIUtil.getTreeLeftChildIndent();
|
||||
int y = 3;
|
||||
int y = TOP_INSET;
|
||||
g.drawLine(cornerX, y, bounds.width, y);
|
||||
g.drawLine(cornerX, y, cornerX, y + bounds.height);
|
||||
if (mySelected) {
|
||||
|
||||
+11
@@ -49,6 +49,17 @@ public interface ArrangementNodeComponent {
|
||||
|
||||
void setScreenBounds(@Nullable Rectangle bounds);
|
||||
|
||||
/**
|
||||
* Notifies current component that canvas (container where current component is painted) width has been changed.
|
||||
* <p/>
|
||||
* The intended usage is to allow component to draw something up to/at the right screen size.
|
||||
*
|
||||
* @param width new canvas width
|
||||
* @return <code>true</code> if current component's representation has been changed;
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
boolean onCanvasWidthChange(int width);
|
||||
|
||||
/**
|
||||
* Instructs current component that it should {@link #getUiComponent() draw} itself according to the given 'selected' state.
|
||||
*
|
||||
|
||||
+35
-2
@@ -74,6 +74,7 @@ public class ArrangementRuleTree {
|
||||
@NotNull private final ArrangementNodeComponentFactory myFactory;
|
||||
@NotNull private final List<Set<ArrangementMatchCondition>> myGroupingRules;
|
||||
|
||||
private int myCanvasWidth;
|
||||
private boolean myExplicitSelectionChange;
|
||||
private boolean mySkipSelectionChange;
|
||||
|
||||
@@ -199,6 +200,35 @@ public class ArrangementRuleTree {
|
||||
}
|
||||
}
|
||||
|
||||
public void updateCanvasWidth(final int width) {
|
||||
myCanvasWidth = width;
|
||||
myRenderers.forEachKey(new TIntProcedure() {
|
||||
@Override
|
||||
public boolean execute(int row) {
|
||||
doUpdateCanvasWidth(row);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void doUpdateCanvasWidth(int row) {
|
||||
if (myCanvasWidth <= 0) {
|
||||
return;
|
||||
}
|
||||
ArrangementNodeComponent component = myRenderers.get(row);
|
||||
if (component == null) {
|
||||
return;
|
||||
}
|
||||
if (!component.onCanvasWidthChange(myCanvasWidth)) {
|
||||
return;
|
||||
}
|
||||
|
||||
TreePath path = myTree.getPathForRow(row);
|
||||
if (path != null) {
|
||||
myTreeModel.nodeChanged((TreeNode)path.getLastPathComponent());
|
||||
}
|
||||
}
|
||||
|
||||
private void selectPreviousRule() {
|
||||
ArrangementTreeNode currentSelectionBottom = getCurrentSelectionBottom();
|
||||
|
||||
@@ -342,7 +372,7 @@ public class ArrangementRuleTree {
|
||||
@NotNull
|
||||
public List<ArrangementRuleEditingModelImpl> getActiveModels() {
|
||||
TreePath[] paths = mySelectionModel.getSelectionPaths();
|
||||
if (paths == null || paths.length != 1) {
|
||||
if (paths == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@@ -432,6 +462,7 @@ public class ArrangementRuleTree {
|
||||
ArrangementNodeComponent result = myRenderers.get(row);
|
||||
if (result == null || !result.getMatchCondition().equals(condition)) {
|
||||
myRenderers.put(row, result = myFactory.getComponent(condition, model));
|
||||
doUpdateCanvasWidth(row);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -619,7 +650,9 @@ public class ArrangementRuleTree {
|
||||
}
|
||||
|
||||
if (row < 0) {
|
||||
return myFactory.getComponent(node, null).getUiComponent();
|
||||
ArrangementNodeComponent component = myFactory.getComponent(node, null);
|
||||
doUpdateCanvasWidth(row);
|
||||
return component.getUiComponent();
|
||||
}
|
||||
ArrangementNodeComponent component = getNodeComponentAt(row, node, myModels.get(row));
|
||||
component.setSelected(selected);
|
||||
|
||||
+21
@@ -118,8 +118,29 @@ public abstract class ArrangementSettingsPanel extends CodeStyleAbstractPanel {
|
||||
setupKeyboardActions(actionManager, treeComponent);
|
||||
|
||||
setupScrollingHelper(treeComponent, scrollPane, editorPane);
|
||||
setupCanvasWidthUpdater(scrollPane);
|
||||
}
|
||||
|
||||
private void setupCanvasWidthUpdater(@NotNull JBScrollPane scrollPane) {
|
||||
final JViewport viewport = scrollPane.getViewport();
|
||||
viewport.addChangeListener(new ChangeListener() {
|
||||
|
||||
private int myWidth;
|
||||
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
Rectangle visibleRect = viewport.getVisibleRect();
|
||||
if (visibleRect == null || visibleRect.width <= 0) {
|
||||
return;
|
||||
}
|
||||
if (myWidth != visibleRect.width) {
|
||||
myWidth = visibleRect.width;
|
||||
myRuleTree.updateCanvasWidth(myWidth);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* The general idea is to configure UI in a way that it automatically changes tree viewport 'y' coordinate in order to make
|
||||
* target rule visible on rule editor opening.
|
||||
|
||||
+27
-28
@@ -100,7 +100,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
|
||||
private final FileStatusMap myFileStatusMap;
|
||||
private DaemonCodeAnalyzerSettings myLastSettings;
|
||||
|
||||
private IntentionHintComponent myLastIntentionHint; //guarded by this
|
||||
private volatile IntentionHintComponent myLastIntentionHint;
|
||||
private volatile boolean myDisposed; // the only possible transition: false -> true
|
||||
private volatile boolean myInitialized; // the only possible transition: false -> true
|
||||
|
||||
@@ -109,7 +109,6 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
|
||||
@NonNls private static final String URL_ATT = "url";
|
||||
private DaemonListeners myDaemonListeners;
|
||||
private final PassExecutorService myPassExecutorService;
|
||||
private int myModificationCount = 0;
|
||||
|
||||
private volatile boolean allowToInterrupt = true;
|
||||
private StatusBarUpdater myStatusBarUpdater;
|
||||
@@ -456,7 +455,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<TextEditorHighlightingPass> getPassesToShowProgressFor(Document document) {
|
||||
List<TextEditorHighlightingPass> getPassesToShowProgressFor(Document document) {
|
||||
List<TextEditorHighlightingPass> allPasses = myPassExecutorService.getAllSubmittedPasses();
|
||||
List<TextEditorHighlightingPass> result = new ArrayList<TextEditorHighlightingPass>(allPasses.size());
|
||||
for (TextEditorHighlightingPass pass : allPasses) {
|
||||
@@ -467,7 +466,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean isAllAnalysisFinished(@NotNull PsiFile file) {
|
||||
boolean isAllAnalysisFinished(@NotNull PsiFile file) {
|
||||
if (myDisposed) return false;
|
||||
Document document = PsiDocumentManager.getInstance(myProject).getCachedDocument(file);
|
||||
return document != null &&
|
||||
@@ -488,11 +487,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
|
||||
return myFileStatusMap;
|
||||
}
|
||||
|
||||
public synchronized int getModificationCount() {
|
||||
return myModificationCount;
|
||||
}
|
||||
|
||||
public synchronized boolean isRunning() {
|
||||
synchronized boolean isRunning() {
|
||||
return myUpdateProgress != null && !myUpdateProgress.isCanceled();
|
||||
}
|
||||
|
||||
@@ -509,7 +504,6 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
|
||||
|
||||
private synchronized void cancelUpdateProgress(final boolean start, @NonNls String reason) {
|
||||
PassExecutorService.log(myUpdateProgress, null, reason, start);
|
||||
myModificationCount++;
|
||||
|
||||
if (myUpdateProgress != null) {
|
||||
myUpdateProgress.cancel();
|
||||
@@ -541,12 +535,12 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
|
||||
});
|
||||
}
|
||||
|
||||
public static boolean processHighlightsOverlappingOutside(@NotNull Document document,
|
||||
@NotNull Project project,
|
||||
@Nullable("null means all") final HighlightSeverity minSeverity,
|
||||
final int startOffset,
|
||||
final int endOffset,
|
||||
@NotNull final Processor<HighlightInfo> processor) {
|
||||
static boolean processHighlightsOverlappingOutside(@NotNull Document document,
|
||||
@NotNull Project project,
|
||||
@Nullable("null means all") final HighlightSeverity minSeverity,
|
||||
final int startOffset,
|
||||
final int endOffset,
|
||||
@NotNull final Processor<HighlightInfo> processor) {
|
||||
LOG.assertTrue(ApplicationManager.getApplication().isReadAccessAllowed());
|
||||
|
||||
final SeverityRegistrar severityRegistrar = SeverityRegistrar.getInstance(project);
|
||||
@@ -634,13 +628,17 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
|
||||
return markup.getUserData(MARKERS_IN_EDITOR_DOCUMENT_KEY);
|
||||
}
|
||||
|
||||
public static void setLineMarkers(@NotNull Document document, List<LineMarkerInfo> lineMarkers, Project project) {
|
||||
static void setLineMarkers(@NotNull Document document, List<LineMarkerInfo> lineMarkers, Project project) {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
MarkupModel markup = DocumentMarkupModel.forDocument(document, project, true);
|
||||
markup.putUserData(MARKERS_IN_EDITOR_DOCUMENT_KEY, lineMarkers);
|
||||
}
|
||||
|
||||
public synchronized void setLastIntentionHint(@NotNull Project project, @NotNull PsiFile file, @NotNull Editor editor, @NotNull ShowIntentionsPass.IntentionsInfo intentions, boolean hasToRecreate) {
|
||||
void setLastIntentionHint(@NotNull Project project,
|
||||
@NotNull PsiFile file,
|
||||
@NotNull Editor editor,
|
||||
@NotNull ShowIntentionsPass.IntentionsInfo intentions,
|
||||
boolean hasToRecreate) {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
hideLastIntentionHint();
|
||||
IntentionHintComponent hintComponent = IntentionHintComponent.showIntentionHint(project, file, editor, intentions, false);
|
||||
@@ -650,15 +648,17 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
|
||||
myLastIntentionHint = hintComponent;
|
||||
}
|
||||
|
||||
public synchronized void hideLastIntentionHint() {
|
||||
if (myLastIntentionHint != null && myLastIntentionHint.isVisible()) {
|
||||
myLastIntentionHint.hide();
|
||||
void hideLastIntentionHint() {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
IntentionHintComponent hint = myLastIntentionHint;
|
||||
if (hint != null && hint.isVisible()) {
|
||||
hint.hide();
|
||||
myLastIntentionHint = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public synchronized IntentionHintComponent getLastIntentionHint() {
|
||||
IntentionHintComponent getLastIntentionHint() {
|
||||
return myLastIntentionHint;
|
||||
}
|
||||
|
||||
@@ -715,7 +715,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
|
||||
Runnable runnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
PassExecutorService.log(myUpdateProgress, null, "Update Runnable. myUpdateByTimerEnabled:",myUpdateByTimerEnabled," something disposed:",PowerSaveMode.isEnabled() || myDisposed || !myProject.isInitialized()," activeEditors:",myProject.isDisposed() ? null : myDaemonListeners.getSelectedEditors());
|
||||
PassExecutorService.log(getUpdateProgress(), null, "Update Runnable. myUpdateByTimerEnabled:",myUpdateByTimerEnabled," something disposed:",PowerSaveMode.isEnabled() || myDisposed || !myProject.isInitialized()," activeEditors:",myProject.isDisposed() ? null : myDaemonListeners.getSelectedEditors());
|
||||
if (!myUpdateByTimerEnabled) return;
|
||||
if (myDisposed) return;
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
@@ -786,6 +786,10 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
|
||||
}
|
||||
}
|
||||
|
||||
synchronized DaemonProgressIndicator getUpdateProgress() {
|
||||
return myUpdateProgress;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@TestOnly
|
||||
public static List<HighlightInfo> getFileLevelHighlights(@NotNull Project project, @NotNull PsiFile file ) {
|
||||
@@ -796,9 +800,4 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
|
||||
public void allowToInterrupt(boolean can) {
|
||||
allowToInterrupt = can;
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
public synchronized DaemonProgressIndicator getUpdateProgress() {
|
||||
return myUpdateProgress;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,7 +181,12 @@ class DaemonListeners implements Disposable {
|
||||
@Override
|
||||
public void editorReleased(@NotNull EditorFactoryEvent event) {
|
||||
// mem leak after closing last editor otherwise
|
||||
myDaemonCodeAnalyzer.hideLastIntentionHint();
|
||||
UIUtil.invokeLaterIfNeeded(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myDaemonCodeAnalyzer.hideLastIntentionHint();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
EditorFactory.getInstance().addEditorFactoryListener(editorFactoryListener, this);
|
||||
|
||||
+39
-41
@@ -131,47 +131,45 @@ public class InspectionToolRegistrar {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
private void printExtension(Class aClass, InspectionTool tool) {
|
||||
StringBuilder builder = new StringBuilder(tool instanceof GlobalInspectionToolWrapper ? "<globalInspection" : "<localInspection");
|
||||
if (tool instanceof LocalInspectionToolWrapper) {
|
||||
String id = ((LocalInspectionToolWrapper)tool).getID();
|
||||
if (!id.equals(tool.getShortName())) {
|
||||
builder.append(" suppressId=\"").append(id).append('"');
|
||||
}
|
||||
String alternativeID = ((LocalInspectionToolWrapper)tool).getAlternativeID();
|
||||
if (alternativeID != null) {
|
||||
builder.append(" alternativeId=\"").append(alternativeID).append('"');
|
||||
}
|
||||
}
|
||||
builder.append(" shortName=\"").append(tool.getShortName()).append('"');
|
||||
|
||||
CommonBundle.lastKey = null;
|
||||
String displayName = tool.getDisplayName();
|
||||
String lastBundle = CommonBundle.lastBundle;
|
||||
if (CommonBundle.lastKey != null) {
|
||||
builder.append(" bundle=\"").append(lastBundle).append("\" key=\"").append(CommonBundle.lastKey).append('"');
|
||||
}
|
||||
else {
|
||||
builder.append(" displayName=\"").append(displayName).append('"');
|
||||
}
|
||||
CommonBundle.lastKey = null;
|
||||
String groupName = tool.getGroupDisplayName();
|
||||
if (CommonBundle.lastKey != null) {
|
||||
if (lastBundle == null || !lastBundle.equals(CommonBundle.lastBundle) ) {
|
||||
builder.append(" groupBundle=\"").append(CommonBundle.lastBundle).append('"');
|
||||
}
|
||||
builder.append(" groupKey=\"").append(CommonBundle.lastKey).append('"');
|
||||
}
|
||||
else {
|
||||
builder.append(" groupName=\"").append(groupName).append('"');
|
||||
}
|
||||
builder.append(" enabledByDefault=\"" + tool.isEnabledByDefault() + "\" ");
|
||||
builder.append(" level=\"").append(tool.getDefaultLevel()).append('"');
|
||||
builder.append(" implementationClass=\"" + aClass.getName() + "\"/>");
|
||||
System.out.println(builder);
|
||||
}
|
||||
*/
|
||||
//private static void printExtension(Class aClass, InspectionTool tool) {
|
||||
// StringBuilder builder = new StringBuilder(tool instanceof GlobalInspectionToolWrapper ? "<globalInspection" : "<localInspection");
|
||||
// if (tool instanceof LocalInspectionToolWrapper) {
|
||||
// String id = ((LocalInspectionToolWrapper)tool).getID();
|
||||
// if (!id.equals(tool.getShortName())) {
|
||||
// builder.append(" suppressId=\"").append(id).append('"');
|
||||
// }
|
||||
// String alternativeID = ((LocalInspectionToolWrapper)tool).getAlternativeID();
|
||||
// if (alternativeID != null) {
|
||||
// builder.append(" alternativeId=\"").append(alternativeID).append('"');
|
||||
// }
|
||||
// }
|
||||
// builder.append(" shortName=\"").append(tool.getShortName()).append('"');
|
||||
//
|
||||
// CommonBundle.lastKey = null;
|
||||
// String displayName = tool.getDisplayName();
|
||||
// String lastBundle = CommonBundle.lastBundle;
|
||||
// if (CommonBundle.lastKey != null) {
|
||||
// builder.append(" bundle=\"").append(lastBundle).append("\" key=\"").append(CommonBundle.lastKey).append('"');
|
||||
// }
|
||||
// else {
|
||||
// builder.append(" displayName=\"").append(displayName).append('"');
|
||||
// }
|
||||
// CommonBundle.lastKey = null;
|
||||
// String groupName = tool.getGroupDisplayName();
|
||||
// if (CommonBundle.lastKey != null) {
|
||||
// if (lastBundle == null || !lastBundle.equals(CommonBundle.lastBundle) ) {
|
||||
// builder.append(" groupBundle=\"").append(CommonBundle.lastBundle).append('"');
|
||||
// }
|
||||
// builder.append(" groupKey=\"").append(CommonBundle.lastKey).append('"');
|
||||
// }
|
||||
// else {
|
||||
// builder.append(" groupName=\"").append(groupName).append('"');
|
||||
// }
|
||||
// builder.append(" enabledByDefault=\"" + tool.isEnabledByDefault() + "\" ");
|
||||
// builder.append(" level=\"").append(tool.getDefaultLevel()).append('"');
|
||||
// builder.append(" implementationClass=\"" + aClass.getName() + "\"/>");
|
||||
// System.out.println(builder);
|
||||
//}
|
||||
|
||||
private Factory<InspectionToolWrapper> registerInspectionTool(final Class aClass, boolean store) {
|
||||
if (LocalInspectionTool.class.isAssignableFrom(aClass)) {
|
||||
|
||||
@@ -27,7 +27,6 @@ import com.intellij.openapi.util.WriteExternalException;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.net.URL;
|
||||
@@ -194,11 +193,6 @@ public abstract class InspectionToolWrapper<T extends InspectionProfileEntry, E
|
||||
return getTool().getMainToolId();
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
public boolean hasXmlMapping() {
|
||||
return myEP != null;
|
||||
}
|
||||
|
||||
public E getExtension() {
|
||||
return myEP;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Show console when standard out changes"/>
|
||||
<text resource-bundle="messages/ExecutionBundle" key="logs.show.console.on.stdout"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="b4310" class="javax.swing.JCheckBox" binding="myShowConsoleOnStdErrCb" default-binding="true">
|
||||
@@ -56,7 +56,7 @@
|
||||
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Show console when standard error changes"/>
|
||||
<text resource-bundle="messages/ExecutionBundle" key="logs.show.console.on.stderr"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
|
||||
@@ -1512,7 +1512,7 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addChangeListener(final ChangeListener listener, final Disposable parent) {
|
||||
public void addChangeListener(@NotNull final ChangeListener listener, @NotNull final Disposable parent) {
|
||||
myListeners.add(listener);
|
||||
Disposer.register(parent, new Disposable() {
|
||||
@Override
|
||||
|
||||
+7
-6
@@ -105,7 +105,7 @@ public abstract class InspectionToolsConfigurable extends BaseConfigurable imple
|
||||
final ModifiableModel model = SingleInspectionProfilePanel.createNewProfile(-1, getSelectedObject(), myWholePanel, "", existingProfileNames);
|
||||
if (model != null) {
|
||||
addProfile((InspectionProfileImpl)model);
|
||||
myDeletedProfiles.remove(model.getName());
|
||||
myDeletedProfiles.remove(getProfilePrefix(model) + model.getName());
|
||||
myDeleteButton.setEnabled(true);
|
||||
}
|
||||
}
|
||||
@@ -115,7 +115,7 @@ public abstract class InspectionToolsConfigurable extends BaseConfigurable imple
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
final InspectionProfileImpl selectedProfile = (InspectionProfileImpl)myProfiles.getSelectedItem();
|
||||
((DefaultComboBoxModel)myProfiles.getModel()).removeElement(selectedProfile);
|
||||
myDeletedProfiles.add(selectedProfile.getName());
|
||||
myDeletedProfiles.add(getProfilePrefix(selectedProfile) + selectedProfile.getName());
|
||||
myDeleteButton.setEnabled(isDeleteEnabled(selectedProfile));
|
||||
}
|
||||
});
|
||||
@@ -177,7 +177,7 @@ public abstract class InspectionToolsConfigurable extends BaseConfigurable imple
|
||||
if (Messages.showOkCancelDialog(myWholePanel, "Profile with name \'" + profile.getName() + "\' already exists. Do you want to overwrite it?", "Warning", Messages.getInformationIcon()) != DialogWrapper.OK_EXIT_CODE) return;
|
||||
}
|
||||
addProfile((InspectionProfileImpl)profile.getModifiableModel());
|
||||
myDeletedProfiles.remove(profile.getName());
|
||||
myDeletedProfiles.remove(getProfilePrefix(profile) + profile.getName());
|
||||
myDeleteButton.setEnabled(true);
|
||||
}
|
||||
catch (InvalidDataException e1) {
|
||||
@@ -228,7 +228,7 @@ public abstract class InspectionToolsConfigurable extends BaseConfigurable imple
|
||||
final InspectionProfileImpl modifiableModel = (InspectionProfileImpl)model.getModifiableModel();
|
||||
modifiableModel.setModified(true);
|
||||
addProfile(modifiableModel);
|
||||
myDeletedProfiles.remove(model.getName());
|
||||
myDeletedProfiles.remove(getProfilePrefix(model) + model.getName());
|
||||
myDeleteButton.setEnabled(true);
|
||||
}
|
||||
}
|
||||
@@ -244,7 +244,7 @@ public abstract class InspectionToolsConfigurable extends BaseConfigurable imple
|
||||
final String modelName = model.getName();
|
||||
final SingleInspectionProfilePanel panel = new SingleInspectionProfilePanel(myProjectProfileManager, modelName, model);
|
||||
myPanel.add(modelName, panel);
|
||||
if (!myPanels.containsKey(modelName)) {
|
||||
if (!myPanels.containsKey(getProfilePrefix(model) + modelName)) {
|
||||
((DefaultComboBoxModel)myProfiles.getModel()).addElement(model);
|
||||
}
|
||||
putProfile(model, panel);
|
||||
@@ -323,7 +323,8 @@ public abstract class InspectionToolsConfigurable extends BaseConfigurable imple
|
||||
final Map<String, SingleInspectionProfilePanel> panels = new LinkedHashMap<String, SingleInspectionProfilePanel>();
|
||||
for (final String name : myPanels.keySet()) {
|
||||
if (myDeletedProfiles.remove(name)) {
|
||||
deleteProfile(name);
|
||||
final String profileName = getProfilePanel(name).getSelectedProfile().getName();
|
||||
deleteProfile(profileName);
|
||||
}
|
||||
else {
|
||||
final SingleInspectionProfilePanel panel = getProfilePanel(name);
|
||||
|
||||
@@ -52,6 +52,8 @@ public class Tool implements SchemeElement {
|
||||
private boolean myEnabled;
|
||||
|
||||
private boolean myUseConsole;
|
||||
private boolean myShowConsoleOnStdOut;
|
||||
private boolean myShowConsoleOnStdErr;
|
||||
private boolean mySynchronizeAfterExecution;
|
||||
|
||||
private String myWorkingDirectory;
|
||||
@@ -103,6 +105,14 @@ public class Tool implements SchemeElement {
|
||||
return myUseConsole;
|
||||
}
|
||||
|
||||
public boolean isShowConsoleOnStdOut() {
|
||||
return myShowConsoleOnStdOut;
|
||||
}
|
||||
|
||||
public boolean isShowConsoleOnStdErr() {
|
||||
return myShowConsoleOnStdErr;
|
||||
}
|
||||
|
||||
public boolean synchronizeAfterExecution() {
|
||||
return mySynchronizeAfterExecution;
|
||||
}
|
||||
@@ -139,6 +149,14 @@ public class Tool implements SchemeElement {
|
||||
myUseConsole = useConsole;
|
||||
}
|
||||
|
||||
void setShowConsoleOnStdOut(boolean showConsole) {
|
||||
myShowConsoleOnStdOut = showConsole;
|
||||
}
|
||||
|
||||
void setShowConsoleOnStdErr(boolean showConsole) {
|
||||
myShowConsoleOnStdErr = showConsole;
|
||||
}
|
||||
|
||||
public void setFilesSynchronizedAfterRun(boolean synchronizeAfterRun) {
|
||||
mySynchronizeAfterExecution = synchronizeAfterRun;
|
||||
}
|
||||
@@ -192,6 +210,8 @@ public class Tool implements SchemeElement {
|
||||
myShownInSearchResultsPopup = source.myShownInSearchResultsPopup;
|
||||
myEnabled = source.myEnabled;
|
||||
myUseConsole = source.myUseConsole;
|
||||
myShowConsoleOnStdOut = source.myShowConsoleOnStdOut;
|
||||
myShowConsoleOnStdErr = source.myShowConsoleOnStdErr;
|
||||
mySynchronizeAfterExecution = source.mySynchronizeAfterExecution;
|
||||
myWorkingDirectory = source.myWorkingDirectory;
|
||||
myProgram = source.myProgram;
|
||||
@@ -215,6 +235,8 @@ public class Tool implements SchemeElement {
|
||||
myShownInSearchResultsPopup == source.myShownInSearchResultsPopup &&
|
||||
myEnabled == source.myEnabled &&
|
||||
myUseConsole == source.myUseConsole &&
|
||||
myShowConsoleOnStdOut == source.myShowConsoleOnStdOut &&
|
||||
myShowConsoleOnStdErr == source.myShowConsoleOnStdErr &&
|
||||
mySynchronizeAfterExecution == source.mySynchronizeAfterExecution &&
|
||||
Comparing.equal(myWorkingDirectory, source.myWorkingDirectory) &&
|
||||
Comparing.equal(myProgram, source.myProgram) &&
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.intellij.tools;
|
||||
|
||||
import com.intellij.execution.ExecutionBundle;
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.ide.macro.MacroManager;
|
||||
import com.intellij.ide.macro.MacrosDialog;
|
||||
@@ -36,8 +37,11 @@ import com.intellij.openapi.wm.IdeFocusManager;
|
||||
import com.intellij.ui.DocumentAdapter;
|
||||
import com.intellij.ui.IdeBorderFactory;
|
||||
import com.intellij.util.Consumer;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.text.BadLocationException;
|
||||
import java.awt.*;
|
||||
@@ -55,6 +59,8 @@ public class ToolEditorDialog extends DialogWrapper {
|
||||
private final JCheckBox myShowInProjectTreeCheckbox = new JCheckBox(ToolsBundle.message("tools.menu.project.checkbox"));
|
||||
private final JCheckBox myShowInSearchResultsPopupCheckbox = new JCheckBox(ToolsBundle.message("tools.menu.search.checkbox"));
|
||||
private final JCheckBox myUseConsoleCheckbox = new JCheckBox(ToolsBundle.message("tools.open.console.checkbox"));
|
||||
private final JCheckBox myShowConsoleOnStdOutCheckbox = new JCheckBox(ExecutionBundle.message("logs.show.console.on.stdout"));
|
||||
private final JCheckBox myShowConsoleOnStdErrCheckbox = new JCheckBox(ExecutionBundle.message("logs.show.console.on.stderr"));
|
||||
private final JCheckBox mySynchronizedAfterRunCheckbox = new JCheckBox(ToolsBundle.message("tools.synchronize.files.checkbox"));
|
||||
private boolean myEnabled;
|
||||
|
||||
@@ -179,6 +185,8 @@ public class ToolEditorDialog extends DialogWrapper {
|
||||
setTitle(ToolsBundle.message("tools.edit.title"));
|
||||
init();
|
||||
addListeners();
|
||||
myShowConsoleOnStdOutCheckbox.setVisible(false);
|
||||
myShowConsoleOnStdErrCheckbox.setVisible(false);
|
||||
}
|
||||
|
||||
private JPanel createCommandPane() {
|
||||
@@ -375,6 +383,14 @@ public class ToolEditorDialog extends DialogWrapper {
|
||||
handleOKButton();
|
||||
}
|
||||
});
|
||||
|
||||
myUseConsoleCheckbox.addChangeListener(new ChangeListener() {
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
myShowConsoleOnStdOutCheckbox.setVisible(myUseConsoleCheckbox.isSelected());
|
||||
myShowConsoleOnStdErrCheckbox.setVisible(myUseConsoleCheckbox.isSelected());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void handleOKButton() {
|
||||
@@ -392,6 +408,8 @@ public class ToolEditorDialog extends DialogWrapper {
|
||||
tool.setShownInProjectViews(myShowInProjectTreeCheckbox.isSelected());
|
||||
tool.setShownInSearchResultsPopup(myShowInSearchResultsPopupCheckbox.isSelected());
|
||||
tool.setUseConsole(myUseConsoleCheckbox.isSelected());
|
||||
tool.setShowConsoleOnStdOut(myShowConsoleOnStdOutCheckbox.isSelected());
|
||||
tool.setShowConsoleOnStdErr(myShowConsoleOnStdErrCheckbox.isSelected());
|
||||
tool.setFilesSynchronizedAfterRun(mySynchronizedAfterRunCheckbox.isSelected());
|
||||
tool.setEnabled(myEnabled);
|
||||
|
||||
@@ -428,6 +446,8 @@ public class ToolEditorDialog extends DialogWrapper {
|
||||
myShowInProjectTreeCheckbox.setSelected(tool.isShownInProjectViews());
|
||||
myShowInSearchResultsPopupCheckbox.setSelected(tool.isShownInSearchResultsPopup());
|
||||
myUseConsoleCheckbox.setSelected(tool.isUseConsole());
|
||||
myShowConsoleOnStdOutCheckbox.setSelected(tool.isShowConsoleOnStdOut());
|
||||
myShowConsoleOnStdErrCheckbox.setSelected(tool.isShowConsoleOnStdErr());
|
||||
mySynchronizedAfterRunCheckbox.setSelected(tool.synchronizeAfterExecution());
|
||||
myEnabled = tool.isEnabled();
|
||||
myTfCommandWorkingDirectory.setText(toCurrentSystemFormat(tool.getWorkingDirectory()));
|
||||
@@ -453,11 +473,13 @@ public class ToolEditorDialog extends DialogWrapper {
|
||||
}
|
||||
|
||||
private JPanel getOptionsPanel() {
|
||||
JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 0));
|
||||
JPanel panel = new JPanel(new MigLayout("fill, gap 10"));
|
||||
panel.setBorder(IdeBorderFactory.createTitledBorder(ToolsBundle.message("tools.options.group"), true));
|
||||
panel.add(mySynchronizedAfterRunCheckbox);
|
||||
panel.add(myUseConsoleCheckbox);
|
||||
panel.add(myOutputFiltersButton);
|
||||
panel.add(myOutputFiltersButton, "ax right, wrap");
|
||||
panel.add(myShowConsoleOnStdOutCheckbox);
|
||||
panel.add(myShowConsoleOnStdErrCheckbox, "spanx 2");
|
||||
return panel;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,21 +16,20 @@
|
||||
package com.intellij.tools;
|
||||
|
||||
import com.intellij.execution.ExecutionException;
|
||||
import com.intellij.execution.ExecutionManager;
|
||||
import com.intellij.execution.ExecutionResult;
|
||||
import com.intellij.execution.Executor;
|
||||
import com.intellij.execution.configurations.*;
|
||||
import com.intellij.execution.filters.RegexpFilter;
|
||||
import com.intellij.execution.filters.TextConsoleBuilder;
|
||||
import com.intellij.execution.filters.TextConsoleBuilderFactory;
|
||||
import com.intellij.execution.process.ColoredProcessHandler;
|
||||
import com.intellij.execution.process.OSProcessHandler;
|
||||
import com.intellij.execution.process.ProcessHandler;
|
||||
import com.intellij.execution.process.ProcessTerminatedListener;
|
||||
import com.intellij.execution.process.*;
|
||||
import com.intellij.execution.runners.ExecutionEnvironment;
|
||||
import com.intellij.execution.runners.ProgramRunner;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -89,11 +88,21 @@ public class ToolRunProfile implements ModuleRunProfile{
|
||||
return processHandler;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ExecutionResult execute(@NotNull final Executor executor, @NotNull ProgramRunner runner) throws ExecutionException {
|
||||
final ExecutionResult result = super.execute(executor, runner);
|
||||
final ProcessHandler processHandler = result.getProcessHandler();
|
||||
if (processHandler != null) {
|
||||
processHandler.addProcessListener(new ToolProcessAdapter(project, myTool.synchronizeAfterExecution(), getName()));
|
||||
processHandler.addProcessListener(new ProcessAdapter() {
|
||||
@Override
|
||||
public void onTextAvailable(ProcessEvent event, Key outputType) {
|
||||
if ((outputType == ProcessOutputTypes.STDOUT && myTool.isShowConsoleOnStdOut())
|
||||
|| (outputType == ProcessOutputTypes.STDERR && myTool.isShowConsoleOnStdErr())) {
|
||||
ExecutionManager.getInstance(project).getContentManager().toFrontRunContent(executor, processHandler);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -42,6 +42,8 @@ class ToolsProcessor extends BaseSchemeProcessor<ToolsGroup> {
|
||||
@NonNls private static final String SHOW_IN_SEARCH_POPUP = "showInSearchPopup";
|
||||
@NonNls private static final String DISABLED = "disabled";
|
||||
@NonNls private static final String USE_CONSOLE = "useConsole";
|
||||
@NonNls private static final String SHOW_CONSOLE_ON_STDOUT = "showConsoleOnStdOut";
|
||||
@NonNls private static final String SHOW_CONSOLE_ON_STDERR = "showConsoleOnStdErr";
|
||||
@NonNls private static final String SYNCHRONIZE_AFTER_EXECUTION = "synchronizeAfterRun";
|
||||
@NonNls private static final String EXEC = "exec";
|
||||
@NonNls private static final String WORKING_DIRECTORY = "WORKING_DIRECTORY";
|
||||
@@ -76,6 +78,8 @@ class ToolsProcessor extends BaseSchemeProcessor<ToolsGroup> {
|
||||
tool.setShownInSearchResultsPopup(Boolean.valueOf(element.getAttributeValue(SHOW_IN_SEARCH_POPUP)).booleanValue());
|
||||
tool.setEnabled(!Boolean.valueOf(element.getAttributeValue(DISABLED)).booleanValue());
|
||||
tool.setUseConsole(Boolean.valueOf(element.getAttributeValue(USE_CONSOLE)).booleanValue());
|
||||
tool.setShowConsoleOnStdOut(Boolean.valueOf(element.getAttributeValue(SHOW_CONSOLE_ON_STDOUT)).booleanValue());
|
||||
tool.setShowConsoleOnStdErr(Boolean.valueOf(element.getAttributeValue(SHOW_CONSOLE_ON_STDERR)).booleanValue());
|
||||
tool.setFilesSynchronizedAfterRun(Boolean.valueOf(element.getAttributeValue(SYNCHRONIZE_AFTER_EXECUTION)).booleanValue());
|
||||
|
||||
Element exec = element.getChild(EXEC);
|
||||
@@ -150,6 +154,8 @@ class ToolsProcessor extends BaseSchemeProcessor<ToolsGroup> {
|
||||
element.setAttribute(SHOW_IN_SEARCH_POPUP, Boolean.toString(tool.isShownInSearchResultsPopup()));
|
||||
element.setAttribute(DISABLED, Boolean.toString(!tool.isEnabled()));
|
||||
element.setAttribute(USE_CONSOLE, Boolean.toString(tool.isUseConsole()));
|
||||
element.setAttribute(SHOW_CONSOLE_ON_STDOUT, Boolean.toString(tool.isShowConsoleOnStdOut()));
|
||||
element.setAttribute(SHOW_CONSOLE_ON_STDERR, Boolean.toString(tool.isShowConsoleOnStdErr()));
|
||||
element.setAttribute(SYNCHRONIZE_AFTER_EXECUTION, Boolean.toString(tool.synchronizeAfterExecution()));
|
||||
|
||||
Element taskElement = new Element(EXEC);
|
||||
|
||||
@@ -3834,11 +3834,11 @@ public class AbstractTreeUi {
|
||||
}
|
||||
}
|
||||
|
||||
Set<Object> toSelect = new THashSet<Object>();
|
||||
clearSelection();
|
||||
ContainerUtil.addAll(toSelect, elements);
|
||||
Set<Object> toSelect = new THashSet<Object>();
|
||||
ContainerUtil.addAllNotNull(toSelect, elements);
|
||||
if (addToSelection) {
|
||||
toSelect.addAll(currentElements);
|
||||
ContainerUtil.addAllNotNull(toSelect, currentElements);
|
||||
}
|
||||
|
||||
if (checkIfInStructure) {
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.intellij.openapi.components.*;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectManager;
|
||||
import com.intellij.openapi.wm.IdeFrame;
|
||||
import com.intellij.openapi.wm.WindowManager;
|
||||
import com.intellij.ui.ScreenUtil;
|
||||
import gnu.trove.TObjectIntHashMap;
|
||||
@@ -263,8 +264,19 @@ public class DimensionService implements PersistentStateComponent<Element>, Appl
|
||||
private static String realKey(String key, @Nullable Project project) {
|
||||
if (project == null) return key;
|
||||
|
||||
final JFrame frame = WindowManager.getInstance().getFrame(project);
|
||||
if (frame == null) return key; //during frame initialization
|
||||
JFrame frame = WindowManager.getInstance().getFrame(project);
|
||||
if (frame == null) {
|
||||
final IdeFrame[] frames = WindowManager.getInstance().getAllFrames();
|
||||
for (IdeFrame ideFrame : frames) {
|
||||
if (ideFrame instanceof JFrame) {
|
||||
frame = (JFrame)ideFrame;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (frame == null) {
|
||||
return key; //during frame initialization
|
||||
}
|
||||
}
|
||||
|
||||
final Point topLeft = frame.getLocation();
|
||||
Point center = new Point(topLeft.x + frame.getWidth() / 2, topLeft.y + frame.getHeight() / 2);
|
||||
|
||||
@@ -65,7 +65,7 @@ StatusBar.bottomColor=2c2c2c
|
||||
Button.foreground=eeeeee
|
||||
Button.background=535353
|
||||
Button.border=com.intellij.ide.ui.laf.borders.DarculaButtonPainter
|
||||
ButtonUI=com.intellij.ide.ui.laf.borders.DarculaButtonUI
|
||||
#ButtonUI=com.intellij.ide.ui.laf.borders.DarculaButtonUI
|
||||
|
||||
MenuItem.acceleratorForeground=eeeeee
|
||||
PopupMenu.background=535353
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
Button.background=606060
|
||||
Button.foreground=cccccc
|
||||
|
||||
ComboBox.background=606060
|
||||
ComboBox.foreground=cccccc
|
||||
ButtonUI=com.intellij.ide.ui.laf.borders.DarculaButtonUI
|
||||
|
||||
Tree.line=909090
|
||||
Tree.hash=909090
|
||||
Tree.collapsedIcon=AllIcons.Darcula.TreeNodeCollapsed
|
||||
Tree.expandedIcon=AllIcons.Darcula.TreeNodeExpanded
|
||||
|
||||
Menu.selectionBackground=526CA4
|
||||
Tree.expandedIcon=AllIcons.Darcula.TreeNodeExpanded
|
||||
@@ -286,6 +286,8 @@ run.configuration.error.no.jdk.specified=No JDK specified
|
||||
run.configuration.cannot.find.vm.executable=Cannot find VM executable
|
||||
|
||||
logs.tab.title=Logs
|
||||
logs.show.console.on.stdout=Show console when standard out changes
|
||||
logs.show.console.on.stderr=Show console when standard error changes
|
||||
before.launch.panel.title=Before launch
|
||||
before.launch.panel.empty=There are no tasks to run before launch
|
||||
before.launch.panel.cyclic_dependency_warning=''{0}'' has already configured to be launched before {1}.\nSuch cyclic dependencies are not allowed.
|
||||
|
||||
@@ -29,6 +29,10 @@
|
||||
<action id="ActivateStructureToolWindow">
|
||||
<keyboard-shortcut first-keystroke="meta 2" />
|
||||
</action>
|
||||
<action id="FileStructurePopup">
|
||||
<keyboard-shortcut first-keystroke="control 6"/>
|
||||
<keyboard-shortcut first-keystroke="meta F12"/>
|
||||
</action>
|
||||
<action id="AutoIndentLines">
|
||||
<keyboard-shortcut first-keystroke="meta alt I" />
|
||||
<keyboard-shortcut first-keystroke="control I" />
|
||||
@@ -51,9 +55,9 @@
|
||||
<keyboard-shortcut first-keystroke="alt ESCAPE" />
|
||||
</action>
|
||||
<action id="CollapseRegion">
|
||||
<keyboard-shortcut first-keystroke="meta alt LEFT" />
|
||||
<keyboard-shortcut first-keystroke="meta SUBTRACT" />
|
||||
<keyboard-shortcut first-keystroke="meta MINUS" />
|
||||
<keyboard-shortcut first-keystroke="meta alt LEFT" />
|
||||
</action>
|
||||
<action id="CollapseSelection" />
|
||||
<action id="Console.History.Next" />
|
||||
@@ -164,9 +168,9 @@
|
||||
<keyboard-shortcut first-keystroke="meta OPEN_BRACKET" />
|
||||
</action>
|
||||
<action id="ExpandRegion">
|
||||
<keyboard-shortcut first-keystroke="meta alt RIGHT"/>
|
||||
<keyboard-shortcut first-keystroke="meta ADD" />
|
||||
<keyboard-shortcut first-keystroke="meta EQUALS" />
|
||||
<keyboard-shortcut first-keystroke="meta alt RIGHT" />
|
||||
</action>
|
||||
<action id="ExternalJavaDoc">
|
||||
<keyboard-shortcut first-keystroke="shift F1" />
|
||||
@@ -288,12 +292,12 @@
|
||||
<action id="ResizeToolWindowDown" />
|
||||
<action id="ResizeToolWindowUp" />
|
||||
<action id="Resume">
|
||||
<keyboard-shortcut first-keystroke="control Y"/>
|
||||
<keyboard-shortcut first-keystroke="F9" />
|
||||
<keyboard-shortcut first-keystroke="control Y" />
|
||||
</action>
|
||||
<action id="Run">
|
||||
<keyboard-shortcut first-keystroke="meta R"/>
|
||||
<keyboard-shortcut first-keystroke="shift F10" />
|
||||
<keyboard-shortcut first-keystroke="meta R" />
|
||||
</action>
|
||||
<action id="SaveAll">
|
||||
<keyboard-shortcut first-keystroke="meta alt S" />
|
||||
@@ -313,8 +317,8 @@
|
||||
<keyboard-shortcut first-keystroke="F6" />
|
||||
</action>
|
||||
<action id="Stop">
|
||||
<keyboard-shortcut first-keystroke="meta PERIOD"/>
|
||||
<keyboard-shortcut first-keystroke="meta F2" />
|
||||
<keyboard-shortcut first-keystroke="meta PERIOD" />
|
||||
</action>
|
||||
<action id="Vcs.QuickListPopupAction" />
|
||||
<action id="AddFilesToProjectAction">
|
||||
|
||||
+1
-1
@@ -133,7 +133,7 @@ public abstract class BaseTestsOutputConsoleView implements ConsoleView, Observa
|
||||
myConsole = null;
|
||||
}
|
||||
|
||||
public void addChangeListener(final ChangeListener listener, final Disposable parent) {
|
||||
public void addChangeListener(@NotNull final ChangeListener listener, @NotNull final Disposable parent) {
|
||||
if (myConsole instanceof ObservableConsoleView) {
|
||||
((ObservableConsoleView)myConsole).addChangeListener(listener, parent);
|
||||
} else {
|
||||
|
||||
@@ -67,7 +67,10 @@ public abstract class BundleBase {
|
||||
return messageOrDefault(bundle, key, null, params);
|
||||
}
|
||||
|
||||
public static String replaceMnemonicAmpersand(final String value) {
|
||||
@Nullable
|
||||
public static String replaceMnemonicAmpersand(@Nullable final String value) {
|
||||
if (value == null)
|
||||
return null;
|
||||
if (value.indexOf('&') >= 0) {
|
||||
boolean useMacMnemonic = value.contains("&&");
|
||||
StringBuilder realValue = new StringBuilder();
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.intellij.util;
|
||||
import gnu.trove.THashSet;
|
||||
import gnu.trove.TObjectHashingStrategy;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -123,6 +124,7 @@ public class CommonProcessors {
|
||||
return myValue != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public T getFoundValue() {
|
||||
return myValue;
|
||||
}
|
||||
|
||||
@@ -467,6 +467,25 @@ public class ContainerUtil extends ContainerUtilRt {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all not-null elements from the {@code elements}, ignoring nulls
|
||||
*/
|
||||
public static <T> void addAllNotNull(@NotNull Collection<T> collection, @NotNull Iterable<? extends T> elements) {
|
||||
addAll(collection, elements.iterator());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all not-null elements from the {@code elements}, ignoring nulls
|
||||
*/
|
||||
public static <T> void addAllNotNull(@NotNull Collection<T> collection, @NotNull Iterator<? extends T> elements) {
|
||||
while (elements.hasNext()) {
|
||||
T o = elements.next();
|
||||
if (o != null) {
|
||||
collection.add(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static <T> List<T> collect(@NotNull Iterator<T> iterator) {
|
||||
if (!iterator.hasNext()) return Collections.emptyList();
|
||||
@@ -859,6 +878,19 @@ public class ContainerUtil extends ContainerUtilRt {
|
||||
return collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all not-null elements from the {@code elements}, ignoring nulls
|
||||
*/
|
||||
public static <T, A extends T, C extends Collection<T>> C addAllNotNull(@NotNull C collection, @NotNull A... elements) {
|
||||
//noinspection ManualArrayToCollectionCopy
|
||||
for (T element : elements) {
|
||||
if (element != null) {
|
||||
collection.add(element);
|
||||
}
|
||||
}
|
||||
return collection;
|
||||
}
|
||||
|
||||
public static <T, U extends T> U findInstance(@NotNull Iterable<T> iterable, @NotNull Class<U> aClass) {
|
||||
return findInstance(iterable.iterator(), aClass);
|
||||
}
|
||||
|
||||
+21
@@ -23,6 +23,7 @@ import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.wm.IdeFocusManager;
|
||||
import com.intellij.xdebugger.XDebugSession;
|
||||
import com.intellij.xdebugger.XDebugSessionAdapter;
|
||||
import com.intellij.xdebugger.XDebuggerBundle;
|
||||
import com.intellij.xdebugger.XSourcePosition;
|
||||
import com.intellij.xdebugger.evaluation.EvaluationMode;
|
||||
@@ -54,6 +55,7 @@ public class XDebuggerEvaluationDialog extends DialogWrapper {
|
||||
private EvaluationMode myMode;
|
||||
private final XSourcePosition mySourcePosition;
|
||||
private final SwitchModeAction mySwitchModeAction;
|
||||
private final XDebugSessionAdapter mySessionListener;
|
||||
|
||||
public XDebuggerEvaluationDialog(@NotNull XDebugSession session,
|
||||
final @NotNull XDebuggerEditorsProvider editorsProvider,
|
||||
@@ -68,6 +70,19 @@ public class XDebuggerEvaluationDialog extends DialogWrapper {
|
||||
setOKButtonText(XDebuggerBundle.message("xdebugger.button.evaluate"));
|
||||
setCancelButtonText(XDebuggerBundle.message("xdebugger.evaluate.dialog.close"));
|
||||
|
||||
mySessionListener = new XDebugSessionAdapter() {
|
||||
@Override
|
||||
public void sessionStopped() {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
close(CANCEL_EXIT_CODE);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
mySession.addSessionListener(mySessionListener);
|
||||
|
||||
myTreePanel = new XDebuggerTreePanel(session, editorsProvider, myDisposable, sourcePosition, XDebuggerActions.EVALUATE_DIALOG_TREE_POPUP_GROUP);
|
||||
myResultPanel = new JPanel(new BorderLayout());
|
||||
myResultPanel.add(new JLabel(XDebuggerBundle.message("xdebugger.evaluate.label.result")), BorderLayout.NORTH);
|
||||
@@ -101,6 +116,12 @@ public class XDebuggerEvaluationDialog extends DialogWrapper {
|
||||
init();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dispose() {
|
||||
mySession.removeSessionListener(mySessionListener);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
protected void doOKAction() {
|
||||
evaluate();
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.testFramework.UsefulTestCase;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
@@ -71,11 +72,22 @@ public class XDebuggerTestUtil {
|
||||
XDebuggerUtil.getInstance().toggleLineBreakpoint(project, file, line);
|
||||
}
|
||||
|
||||
public static <P extends XBreakpointProperties>void insertBreakpoint(final Project project, final P properties, final Class<? extends XBreakpointType<XBreakpoint<P>, P>> typeClass) {
|
||||
public static <P extends XBreakpointProperties> XBreakpoint<P> insertBreakpoint(final Project project,
|
||||
final P properties,
|
||||
final Class<? extends XBreakpointType<XBreakpoint<P>, P>> typeClass) {
|
||||
return new WriteAction<XBreakpoint<P>>() {
|
||||
protected void run(final Result<XBreakpoint<P>> result) {
|
||||
result.setResult(XDebuggerManager.getInstance(project).getBreakpointManager()
|
||||
.addBreakpoint((XBreakpointType<XBreakpoint<P>, P>)XDebuggerUtil.getInstance().findBreakpointType(typeClass),
|
||||
properties));
|
||||
}
|
||||
}.execute().getResultObject();
|
||||
}
|
||||
|
||||
public static void removeBreakpoint(final Project project, final XBreakpoint<?> breakpoint) {
|
||||
new WriteAction() {
|
||||
protected void run(final Result result) {
|
||||
XBreakpointManager breakpointManager = XDebuggerManager.getInstance(project).getBreakpointManager();
|
||||
breakpointManager.addBreakpoint((XBreakpointType<XBreakpoint<P>,P>)XDebuggerUtil.getInstance().findBreakpointType(typeClass), properties);
|
||||
XDebuggerManager.getInstance(project).getBreakpointManager().removeBreakpoint(breakpoint);
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
@@ -267,6 +279,20 @@ public class XDebuggerTestUtil {
|
||||
UsefulTestCase.assertOrderedEquals(actualNames, expectedNames);
|
||||
}
|
||||
|
||||
public static void assertVariablesContain(List<XValue> vars, String... names) throws InterruptedException {
|
||||
List<String> expectedNames = new ArrayList<String>(Arrays.asList(names));
|
||||
|
||||
List<String> actualNames = new ArrayList<String>();
|
||||
for (XValue each : vars) {
|
||||
actualNames.add(computePresentation(each).myName);
|
||||
}
|
||||
|
||||
expectedNames.removeAll(actualNames);
|
||||
UsefulTestCase.assertTrue("Missing variables:" + StringUtil.join(expectedNames, ", ")
|
||||
+ "\nAll Variables: " + StringUtil.join(actualNames, ", "),
|
||||
expectedNames.isEmpty());
|
||||
}
|
||||
|
||||
public static void assertSourcePosition(final XValue value, VirtualFile file, int offset) {
|
||||
final XTestNavigatable n = new XTestNavigatable();
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
@@ -327,7 +353,7 @@ public class XDebuggerTestUtil {
|
||||
public static void removeAllBreakpoints(@NotNull final Project project) {
|
||||
final XBreakpointManager breakpointManager = XDebuggerManager.getInstance(project).getBreakpointManager();
|
||||
XBreakpoint<?>[] breakpoints = breakpointManager.getAllBreakpoints();
|
||||
for (XBreakpoint b: breakpoints) {
|
||||
for (XBreakpoint b : breakpoints) {
|
||||
breakpointManager.removeBreakpoint(b);
|
||||
}
|
||||
}
|
||||
|
||||
+25
-35
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2007 Dave Griffith, Bas Leijdekkers
|
||||
* Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,6 +18,8 @@ package com.siyeh.ig.cloneable;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.searches.SuperMethodsSearch;
|
||||
import com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
@@ -25,64 +27,64 @@ import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.InspectionGadgetsFix;
|
||||
import com.siyeh.ig.psiutils.CloneUtils;
|
||||
import com.siyeh.ig.psiutils.MethodUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class CloneDeclaresCloneNotSupportedInspection extends BaseInspection {
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getID() {
|
||||
return "CloneDoesntDeclareCloneNotSupportedException";
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getDisplayName() {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"clone.doesnt.declare.clonenotsupportedexception.display.name");
|
||||
return InspectionGadgetsBundle.message("clone.doesnt.declare.clonenotsupportedexception.display.name");
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String buildErrorString(Object... infos) {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"clone.doesnt.declare.clonenotsupportedexception.problem.descriptor");
|
||||
return InspectionGadgetsBundle.message("clone.doesnt.declare.clonenotsupportedexception.problem.descriptor");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabledByDefault() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InspectionGadgetsFix buildFix(Object... infos) {
|
||||
return new CloneDeclaresCloneNotSupportedInspectionFix();
|
||||
}
|
||||
|
||||
private static class CloneDeclaresCloneNotSupportedInspectionFix
|
||||
extends InspectionGadgetsFix {
|
||||
private static class CloneDeclaresCloneNotSupportedInspectionFix extends InspectionGadgetsFix {
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getName() {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"clone.doesnt.declare.clonenotsupportedexception.declare.quickfix");
|
||||
return InspectionGadgetsBundle.message("clone.doesnt.declare.clonenotsupportedexception.declare.quickfix");
|
||||
}
|
||||
|
||||
public void doFix(Project project, ProblemDescriptor descriptor)
|
||||
throws IncorrectOperationException {
|
||||
@Override
|
||||
public void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
|
||||
final PsiElement methodNameIdentifier = descriptor.getPsiElement();
|
||||
final PsiMethod method =
|
||||
(PsiMethod)methodNameIdentifier.getParent();
|
||||
PsiUtil.addException(method,
|
||||
"java.lang.CloneNotSupportedException");
|
||||
final PsiMethod method = (PsiMethod)methodNameIdentifier.getParent();
|
||||
PsiUtil.addException(method, "java.lang.CloneNotSupportedException");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseInspectionVisitor buildVisitor() {
|
||||
return new CloneDeclaresCloneNotSupportedExceptionVisitor();
|
||||
}
|
||||
|
||||
private static class CloneDeclaresCloneNotSupportedExceptionVisitor
|
||||
extends BaseInspectionVisitor {
|
||||
private static class CloneDeclaresCloneNotSupportedExceptionVisitor extends BaseInspectionVisitor {
|
||||
|
||||
@Override
|
||||
public void visitMethod(@NotNull PsiMethod method) {
|
||||
//note: no call to super;
|
||||
if (!CloneUtils.isClone(method)) {
|
||||
return;
|
||||
}
|
||||
@@ -96,30 +98,18 @@ public class CloneDeclaresCloneNotSupportedInspection extends BaseInspection {
|
||||
if (containingClass.hasModifierProperty(PsiModifier.FINAL)) {
|
||||
return;
|
||||
}
|
||||
if (hasThrowsCloneNotSupportedException(method)) {
|
||||
if (MethodUtils.hasInThrows(method, "java.lang.CloneNotSupportedException")) {
|
||||
return;
|
||||
}
|
||||
final PsiMethod[] superMethods = method.findSuperMethods();
|
||||
if (superMethods.length < 1) {
|
||||
final MethodSignatureBackedByPsiMethod signature = SuperMethodsSearch.search(method, null, true, false).findFirst();
|
||||
if (signature == null) {
|
||||
return;
|
||||
}
|
||||
if (!hasThrowsCloneNotSupportedException(superMethods[0])) {
|
||||
final PsiMethod superMethod = signature.getMethod();
|
||||
if (!MethodUtils.hasInThrows(superMethod, "java.lang.CloneNotSupportedException")) {
|
||||
return;
|
||||
}
|
||||
registerMethodError(method);
|
||||
}
|
||||
|
||||
public static boolean hasThrowsCloneNotSupportedException(
|
||||
@NotNull PsiMethod method) {
|
||||
final PsiReferenceList throwsList = method.getThrowsList();
|
||||
final PsiClassType[] thrownTypes = throwsList.getReferencedTypes();
|
||||
for (final PsiClassType thrownType : thrownTypes) {
|
||||
if (thrownType.equalsToText(
|
||||
"java.lang.CloneNotSupportedException")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -259,6 +259,9 @@ public class MethodUtils {
|
||||
}
|
||||
|
||||
public static boolean hasInThrows(@NotNull PsiMethod method, @NotNull String... exceptions) {
|
||||
if (exceptions.length == 0) {
|
||||
throw new IllegalArgumentException("no exceptions specified");
|
||||
}
|
||||
final PsiReferenceList throwsList = method.getThrowsList();
|
||||
final PsiJavaCodeReferenceElement[] references = throwsList.getReferenceElements();
|
||||
for (PsiJavaCodeReferenceElement reference : references) {
|
||||
|
||||
-22
@@ -1,22 +0,0 @@
|
||||
package com.siyeh.igtest.cloneable;
|
||||
|
||||
public class CloneDeclaresCloneNonSupportedExceptionInspection implements Cloneable
|
||||
{
|
||||
|
||||
public void foo()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public Object clone()
|
||||
{
|
||||
try
|
||||
{
|
||||
return super.clone();
|
||||
}
|
||||
catch(CloneNotSupportedException e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package com.siyeh.igtest.cloneable.clone_declares_clone_not_supported;
|
||||
|
||||
public class CloneDeclaresCloneNonSupportedException implements Cloneable
|
||||
{
|
||||
|
||||
public void foo()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public Object clone()
|
||||
{
|
||||
try
|
||||
{
|
||||
return super.clone();
|
||||
}
|
||||
catch(CloneNotSupportedException e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
class Normal implements Cloneable {
|
||||
|
||||
@Override
|
||||
protected Object clone() throws CloneNotSupportedException {
|
||||
return super.clone();
|
||||
}
|
||||
}
|
||||
class Child extends CloneDeclaresCloneNonSupportedException {
|
||||
|
||||
@Override
|
||||
public Object clone() {
|
||||
return super.clone();
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<problems>
|
||||
<problem>
|
||||
<file>CloneDeclaresCloneNonSupportedException.java</file>
|
||||
<line>11</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">'clone()' does not declare 'CloneNotSupportedException'</problem_class>
|
||||
<description><code>clone()</code> does not declare 'CloneNotSupportedException'</description>
|
||||
</problem>
|
||||
</problems>
|
||||
@@ -185,7 +185,81 @@
|
||||
enabledByDefault="true" level="ERROR"
|
||||
implementationClass="org.jetbrains.android.inspections.AndroidNonConstantResIdsInSwitchInspection"/>
|
||||
|
||||
<inspectionToolProvider implementation="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider"/>
|
||||
<globalInspection shortName="AndroidLintContentDescription" displayName="Missing content description" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintContentDescriptionInspection"/>
|
||||
<globalInspection shortName="AndroidLintAdapterViewChildren" displayName="AdapterView element cannot have children" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintAdapterViewChildrenInspection"/>
|
||||
<globalInspection shortName="AndroidLintScrollViewCount" displayName="ScrollView element can have only one child" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintScrollViewCountInspection"/>
|
||||
<globalInspection shortName="AndroidLintMissingPrefix" displayName="Missing Android XML namespace" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintMissingPrefixInspection"/>
|
||||
<globalInspection shortName="AndroidLintDuplicateIds" displayName="Duplicate ids within a single layout" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintDuplicateIdsInspection"/>
|
||||
<globalInspection shortName="AndroidLintGridLayout" displayName="GridLayout validation" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="ERROR" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintGridLayoutInspection"/>
|
||||
<globalInspection shortName="AndroidLintHardcodedText" displayName="Hardcoded text" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintHardcodedTextInspection"/>
|
||||
<globalInspection shortName="AndroidLintInefficientWeight" displayName="Inefficient layout weight" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintInefficientWeightInspection"/>
|
||||
<globalInspection shortName="AndroidLintNestedWeights" displayName="Nested layout weights" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintNestedWeightsInspection"/>
|
||||
<globalInspection shortName="AndroidLintDisableBaselineAlignment" displayName="Missing baselineAligned attribute" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintDisableBaselineAlignmentInspection"/>
|
||||
<globalInspection shortName="AndroidLintManifestOrder" displayName="Incorrect order of elements in manifest" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintManifestOrderInspection"/>
|
||||
<globalInspection shortName="AndroidLintMergeRootFrame" displayName="FrameLayout can be replaced with <merge> tag" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintMergeRootFrameInspection"/>
|
||||
<globalInspection shortName="AndroidLintNestedScrolling" displayName="Nested scrolling widgets" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintNestedScrollingInspection"/>
|
||||
<globalInspection shortName="AndroidLintObsoleteLayoutParam" displayName="Obsolete layout params" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintObsoleteLayoutParamInspection"/>
|
||||
<globalInspection shortName="AndroidLintProguard" displayName="Proguard config file validation" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="ERROR" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintProguardInspection"/>
|
||||
<globalInspection shortName="AndroidLintPxUsage" displayName="Using 'px' dimension" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintPxUsageInspection"/>
|
||||
<globalInspection shortName="AndroidLintScrollViewSize" displayName="ScrollView size validation" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintScrollViewSizeInspection"/>
|
||||
<globalInspection shortName="AndroidLintExportedService" displayName="Exported service does not require permission" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintExportedServiceInspection"/>
|
||||
<globalInspection shortName="AndroidLintGrantAllUris" displayName="Content provider shares everything" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintGrantAllUrisInspection"/>
|
||||
<globalInspection shortName="AndroidLintStateListReachable" displayName="Unreachable state in a <selector>" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintStateListReachableInspection"/>
|
||||
<globalInspection shortName="AndroidLintTextFields" displayName="Text field missing inputType or hint settings" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintTextFieldsInspection"/>
|
||||
<globalInspection shortName="AndroidLintTooManyViews" displayName="Layout has too many views" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintTooManyViewsInspection"/>
|
||||
<globalInspection shortName="AndroidLintTooDeepLayout" displayName="Layout hierarchy is too deep" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintTooDeepLayoutInspection"/>
|
||||
<globalInspection shortName="AndroidLintTypographyDashes" displayName="Hyphen can be replaced with dash" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintTypographyDashesInspection"/>
|
||||
<globalInspection shortName="AndroidLintTypographyQuotes" displayName="Straight quotes can be replaced with curvy quotes" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="false" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintTypographyQuotesInspection"/>
|
||||
<globalInspection shortName="AndroidLintTypographyFractions" displayName="Fraction string can be replaced with fraction character" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintTypographyFractionsInspection"/>
|
||||
<globalInspection shortName="AndroidLintTypographyEllipsis" displayName="Ellipsis string can be replaced with ellipsis character" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintTypographyEllipsisInspection"/>
|
||||
<globalInspection shortName="AndroidLintTypographyOther" displayName="Other typographical problems" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintTypographyOtherInspection"/>
|
||||
<globalInspection shortName="AndroidLintUseCompoundDrawables" displayName="Node can be replaced by TextView with compound drawables" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintUseCompoundDrawablesInspection"/>
|
||||
<globalInspection shortName="AndroidLintUselessParent" displayName="Useless parent layout" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintUselessParentInspection"/>
|
||||
<globalInspection shortName="AndroidLintUselessLeaf" displayName="Useless leaf layout" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintUselessLeafInspection"/>
|
||||
<globalInspection shortName="AndroidLintButtonOrder" displayName="Buttons order" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintButtonOrderInspection"/>
|
||||
<globalInspection shortName="AndroidLintBackButton" displayName="Back button" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="false" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintBackButtonInspection"/>
|
||||
<globalInspection shortName="AndroidLintButtonCase" displayName="Cancel/OK dialog buttons capitalization" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintButtonCaseInspection"/>
|
||||
<globalInspection shortName="AndroidLintResourceAsColor" displayName="Should pass resolved color instead of resource id" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="ERROR" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintResourceAsColorInspection"/>
|
||||
<globalInspection shortName="AndroidLintExtraText" displayName="Extraneous text in layout file" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintExtraTextInspection"/>
|
||||
<globalInspection shortName="AndroidLintHardcodedDebugMode" displayName="Hardcoded value of android:debuggable in the manifest" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintHardcodedDebugModeInspection"/>
|
||||
<globalInspection shortName="AndroidLintDrawAllocation" displayName="Memory allocations within drawing code" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintDrawAllocationInspection"/>
|
||||
<globalInspection shortName="AndroidLintSparseArray" displayName="HashMap can be replaced with SparseArray" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintSparseArrayInspection"/>
|
||||
<globalInspection shortName="AndroidLintUseValueOf" displayName="Should use 'valueOf' instead of 'new'" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintUseValueOfInspection"/>
|
||||
<globalInspection shortName="AndroidLintLibraryCustomView" displayName="Using custom namespace attributes in a library module" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="ERROR" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintLibraryCustomViewInspection"/>
|
||||
<globalInspection shortName="AndroidLintPrivateResource" displayName="Using custom namespace attributes in a library module" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="ERROR" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintPrivateResourceInspection"/>
|
||||
<globalInspection shortName="AndroidLintSdCardPath" displayName="Hardcoded reference to /sdcard" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintSdCardPathInspection"/>
|
||||
<globalInspection shortName="AndroidLintStyleCycle" displayName="Cycle in style definitions" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="ERROR" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintStyleCycleInspection"/>
|
||||
<globalInspection shortName="AndroidLintTextViewEdits" displayName="TextView should probably be an EditText instead" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintTextViewEditsInspection"/>
|
||||
<globalInspection shortName="AndroidLintEnforceUTF8" displayName="Encoding used in resource files is not UTF-8" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintEnforceUTF8Inspection"/>
|
||||
<globalInspection shortName="AndroidLintUnknownIdInLayout" displayName="Reference to an id that is not in the current layout" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintUnknownIdInLayoutInspection"/>
|
||||
<globalInspection shortName="AndroidLintSuspiciousImport" displayName="'import android.R' statement" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintSuspiciousImportInspection"/>
|
||||
<globalInspection shortName="AndroidLintMultipleUsesSdk" displayName="Multiple <uses-sdk> elements in the manifest" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="ERROR" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintMultipleUsesSdkInspection"/>
|
||||
<globalInspection shortName="AndroidLintUsesMinSdkAttributes" displayName="Minimum SDK and target SDK attributes not defined" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintUsesMinSdkAttributesInspection"/>
|
||||
<globalInspection shortName="AndroidLintProguardSplitConfig" displayName="Proguard.cfg file contains generic Android rules" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintProguardSplitConfigInspection"/>
|
||||
<globalInspection shortName="AndroidLintWorldWriteableFiles" displayName="openFileOutput() call passing MODE_WORLD_WRITEABLE" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintWorldWriteableFilesInspection"/>
|
||||
<globalInspection shortName="AndroidLintInconsistentArrays" displayName="Inconsistent arrays" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintInconsistentArraysInspection"/>
|
||||
<globalInspection shortName="AndroidLintDuplicateIncludedIds" displayName="Duplicate ids across layouts combined with include tags" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintDuplicateIncludedIdsInspection"/>
|
||||
<globalInspection shortName="AndroidLintIconExpectedSize" displayName="Icon has incorrect size" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="false" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintIconExpectedSizeInspection"/>
|
||||
<globalInspection shortName="AndroidLintIconDipSize" displayName="Icon density-independent size validation" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintIconDipSizeInspection"/>
|
||||
<globalInspection shortName="AndroidLintIconLocation" displayName="Image defined in density-independent drawable folder" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintIconLocationInspection"/>
|
||||
<globalInspection shortName="AndroidLintIconDensities" displayName="Icon densities validation" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintIconDensitiesInspection"/>
|
||||
<globalInspection shortName="AndroidLintIconMissingDensityFolder" displayName="Missing density folder" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintIconMissingDensityFolderInspection"/>
|
||||
<globalInspection shortName="AndroidLintGifUsage" displayName="Using .gif format for bitmaps is discouraged" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintGifUsageInspection"/>
|
||||
<globalInspection shortName="AndroidLintIconDuplicates" displayName="Duplicated icons under different names" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintIconDuplicatesInspection"/>
|
||||
<globalInspection shortName="AndroidLintIconDuplicatesConfig" displayName="Identical bitmaps across various configurations" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintIconDuplicatesConfigInspection"/>
|
||||
<globalInspection shortName="AndroidLintIconNoDpi" displayName="Icon appears in both -nodpi and dpi folders" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintIconNoDpiInspection"/>
|
||||
<globalInspection shortName="AndroidLintOverdraw" displayName="Overdraw issues" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintOverdrawInspection"/>
|
||||
<globalInspection shortName="AndroidLintMissingTranslation" displayName="Incomplete translation" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="ERROR" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintMissingTranslationInspection"/>
|
||||
<globalInspection shortName="AndroidLintExtraTranslation" displayName="Extra translation" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintExtraTranslationInspection"/>
|
||||
<globalInspection shortName="AndroidLintUnusedResources" displayName="Unused resources" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintUnusedResourcesInspection"/>
|
||||
<globalInspection shortName="AndroidLintUnusedIds" displayName="Unused id" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="false" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintUnusedIdsInspection"/>
|
||||
<globalInspection shortName="AndroidLintAlwaysShowAction" displayName="Usage of showAsAction=always" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintAlwaysShowActionInspection"/>
|
||||
<globalInspection shortName="AndroidLintStringFormatCount" displayName="Formatting argument types are inconsistent across translations" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintStringFormatCountInspection"/>
|
||||
<globalInspection shortName="AndroidLintStringFormatMatches" displayName="Format supplied in a call to String.format doesn't match the format string" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="ERROR" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintStringFormatMatchesInspection"/>
|
||||
<globalInspection shortName="AndroidLintStringFormatInvalid" displayName="Invalid format string" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="ERROR" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintStringFormatInvalidInspection"/>
|
||||
<globalInspection shortName="AndroidLintWrongViewCast" displayName="Mismatched view type" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="ERROR" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintWrongViewCastInspection"/>
|
||||
<globalInspection shortName="AndroidLintUnknownId" displayName="Reference to an unknown id" groupKey="android.lint.inspections.group.name" bundle="messages.AndroidBundle" enabledByDefault="true" level="ERROR" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintInspectionToolProvider$AndroidLintUnknownIdInspection"/>
|
||||
|
||||
<codeInspection.InspectionExtension implementation="org.jetbrains.android.inspections.lint.AndroidInspectionExtensionsFactory"/>
|
||||
|
||||
<colorSettingsPage implementation="org.jetbrains.android.logcat.AndroidLogcatColorPage"/>
|
||||
|
||||
+1
-84
@@ -4,7 +4,6 @@ import com.android.tools.lint.checks.*;
|
||||
import com.android.tools.lint.detector.api.Issue;
|
||||
import com.android.tools.lint.detector.api.LintConstants;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.codeInspection.InspectionToolProvider;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.android.util.AndroidBundle;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -12,95 +11,13 @@ import org.jetbrains.annotations.NotNull;
|
||||
/**
|
||||
* @author Eugene.Kudelevsky
|
||||
*/
|
||||
public class AndroidLintInspectionToolProvider implements InspectionToolProvider {
|
||||
public class AndroidLintInspectionToolProvider {
|
||||
|
||||
/*
|
||||
Missing: DeprecationDetector, NamespaceDetector.TYPO, NamespaceDetector.UNUSED
|
||||
Also detectors based on CLASS_FILE scope are missing
|
||||
*/
|
||||
|
||||
@Override
|
||||
public Class[] getInspectionClasses() {
|
||||
return new Class[]{
|
||||
AndroidLintContentDescriptionInspection.class,
|
||||
AndroidLintAdapterViewChildrenInspection.class,
|
||||
AndroidLintScrollViewCountInspection.class,
|
||||
AndroidLintMissingPrefixInspection.class,
|
||||
AndroidLintDuplicateIdsInspection.class,
|
||||
AndroidLintGridLayoutInspection.class,
|
||||
AndroidLintHardcodedTextInspection.class,
|
||||
AndroidLintInefficientWeightInspection.class,
|
||||
AndroidLintNestedWeightsInspection.class,
|
||||
AndroidLintDisableBaselineAlignmentInspection.class,
|
||||
AndroidLintManifestOrderInspection.class,
|
||||
AndroidLintMergeRootFrameInspection.class,
|
||||
AndroidLintNestedScrollingInspection.class,
|
||||
AndroidLintObsoleteLayoutParamInspection.class,
|
||||
AndroidLintProguardInspection.class,
|
||||
AndroidLintPxUsageInspection.class,
|
||||
AndroidLintScrollViewSizeInspection.class,
|
||||
AndroidLintExportedServiceInspection.class,
|
||||
AndroidLintGrantAllUrisInspection.class,
|
||||
AndroidLintStateListReachableInspection.class,
|
||||
AndroidLintTextFieldsInspection.class,
|
||||
AndroidLintTooManyViewsInspection.class,
|
||||
AndroidLintTooDeepLayoutInspection.class,
|
||||
AndroidLintTypographyDashesInspection.class,
|
||||
AndroidLintTypographyQuotesInspection.class,
|
||||
AndroidLintTypographyFractionsInspection.class,
|
||||
AndroidLintTypographyEllipsisInspection.class,
|
||||
AndroidLintTypographyOtherInspection.class,
|
||||
AndroidLintUseCompoundDrawablesInspection.class,
|
||||
AndroidLintUselessParentInspection.class,
|
||||
AndroidLintUselessLeafInspection.class,
|
||||
AndroidLintButtonOrderInspection.class,
|
||||
AndroidLintBackButtonInspection.class,
|
||||
AndroidLintButtonCaseInspection.class,
|
||||
AndroidLintResourceAsColorInspection.class,
|
||||
AndroidLintExtraTextInspection.class,
|
||||
AndroidLintHardcodedDebugModeInspection.class,
|
||||
AndroidLintDrawAllocationInspection.class,
|
||||
AndroidLintSparseArrayInspection.class,
|
||||
AndroidLintUseValueOfInspection.class,
|
||||
AndroidLintLibraryCustomViewInspection.class,
|
||||
AndroidLintPrivateResourceInspection.class,
|
||||
AndroidLintSdCardPathInspection.class,
|
||||
AndroidLintStyleCycleInspection.class,
|
||||
AndroidLintTextViewEditsInspection.class,
|
||||
AndroidLintEnforceUTF8Inspection.class,
|
||||
AndroidLintUnknownIdInLayoutInspection.class,
|
||||
AndroidLintSuspiciousImportInspection.class,
|
||||
AndroidLintMultipleUsesSdkInspection.class,
|
||||
AndroidLintUsesMinSdkAttributesInspection.class,
|
||||
AndroidLintProguardSplitConfigInspection.class,
|
||||
AndroidLintWorldWriteableFilesInspection.class,
|
||||
|
||||
// batch-mode-only
|
||||
AndroidLintInconsistentArraysInspection.class,
|
||||
AndroidLintDuplicateIncludedIdsInspection.class,
|
||||
AndroidLintIconExpectedSizeInspection.class,
|
||||
AndroidLintIconDipSizeInspection.class,
|
||||
AndroidLintIconLocationInspection.class,
|
||||
AndroidLintIconDensitiesInspection.class,
|
||||
AndroidLintIconMissingDensityFolderInspection.class,
|
||||
AndroidLintGifUsageInspection.class,
|
||||
AndroidLintIconDuplicatesInspection.class,
|
||||
AndroidLintIconDuplicatesConfigInspection.class,
|
||||
AndroidLintIconNoDpiInspection.class,
|
||||
AndroidLintOverdrawInspection.class,
|
||||
AndroidLintMissingTranslationInspection.class,
|
||||
AndroidLintExtraTranslationInspection.class,
|
||||
AndroidLintUnusedResourcesInspection.class,
|
||||
AndroidLintUnusedIdsInspection.class,
|
||||
AndroidLintAlwaysShowActionInspection.class,
|
||||
AndroidLintStringFormatCountInspection.class,
|
||||
AndroidLintStringFormatMatchesInspection.class,
|
||||
AndroidLintStringFormatInvalidInspection.class,
|
||||
AndroidLintWrongViewCastInspection.class,
|
||||
AndroidLintUnknownIdInspection.class
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch-mode-only inspections
|
||||
*/
|
||||
|
||||
@@ -127,6 +127,7 @@
|
||||
<psiEnhancerCategory implementation="org.jetbrains.plugins.groovy.dsl.psi.PsiExpressionCategory"/>
|
||||
|
||||
<variableEnhancer implementation="org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.ClosureParameterEnhancer"/>
|
||||
<variableEnhancer implementation="org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.ClosureAsAnonymousParameterEnhancer"/>
|
||||
|
||||
<membersContributor implementation="org.jetbrains.plugins.groovy.gant.GantMemberContributor"/>
|
||||
|
||||
|
||||
+1
-1
@@ -114,7 +114,7 @@ public class GppClosureParameterTypeProvider extends AbstractClosureParameterEnh
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiType getSingleMethodParameterType(@Nullable PsiType type, int index, GrClosableBlock closure) {
|
||||
public static PsiType getSingleMethodParameterType(@Nullable PsiType type, int index, GrClosableBlock closure) {
|
||||
final PsiType[] signature = findSingleAbstractMethodSignature(type);
|
||||
if (signature != null && GrClosureSignatureUtil.isSignatureApplicable(GrClosureSignatureUtil.createSignature(closure), signature, closure)) {
|
||||
return signature.length > index ? signature[index] : PsiType.NULL;
|
||||
|
||||
@@ -76,7 +76,7 @@ public class GppTypeConverter extends GrTypeConverter {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (rType instanceof GrClosureType) {
|
||||
else if (rType instanceof GrClosureType && hasTypedContext(context)) {
|
||||
final PsiType[] methodParameters = GppClosureParameterTypeProvider.findSingleAbstractMethodSignature(lType);
|
||||
if (isClosureOverride(methodParameters, (GrClosureType)rType, context)) return true;
|
||||
}
|
||||
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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 org.jetbrains.plugins.groovy.lang.psi.typeEnhancers;
|
||||
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.gpp.GppClosureParameterTypeProvider;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrSafeCastExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.GroovyExpectedTypesProvider;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Max Medvedev
|
||||
*/
|
||||
public class ClosureAsAnonymousParameterEnhancer extends AbstractClosureParameterEnhancer {
|
||||
@Nullable
|
||||
@Override
|
||||
protected PsiType getClosureParameterType(GrClosableBlock closure, int index) {
|
||||
|
||||
Set<PsiType> expectedTypes;
|
||||
|
||||
if (closure.getParent() instanceof GrSafeCastExpression) {
|
||||
GrSafeCastExpression safeCastExpression = (GrSafeCastExpression)closure.getParent();
|
||||
GrTypeElement typeElement = safeCastExpression.getCastTypeElement();
|
||||
if (typeElement != null) {
|
||||
PsiType castType = typeElement.getType();
|
||||
expectedTypes = new HashSet<PsiType>(GroovyExpectedTypesProvider.getDefaultExpectedTypes(safeCastExpression));
|
||||
PsiManager manager = closure.getManager();
|
||||
GlobalSearchScope scope = closure.getResolveScope();
|
||||
for (PsiType expected : expectedTypes) {
|
||||
if (!TypesUtil.isAssignable(expected, castType, manager, scope)) {
|
||||
expectedTypes.remove(expected);
|
||||
}
|
||||
}
|
||||
|
||||
if (expectedTypes.isEmpty()) expectedTypes.add(castType);
|
||||
}
|
||||
else {
|
||||
expectedTypes = GroovyExpectedTypesProvider.getDefaultExpectedTypes(closure);
|
||||
}
|
||||
}
|
||||
else {
|
||||
expectedTypes = GroovyExpectedTypesProvider.getDefaultExpectedTypes(closure);
|
||||
}
|
||||
|
||||
for (PsiType constraint : expectedTypes) {
|
||||
final PsiType suggestion = GppClosureParameterTypeProvider.getSingleMethodParameterType(constraint, index, closure);
|
||||
if (suggestion != null) {
|
||||
return suggestion;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1452,6 +1452,25 @@ List<String> foo() {[]}
|
||||
def (int <warning descr="Cannot assign 'String' to 'int'">x</warning>, String y) = foo()
|
||||
|
||||
List<String> foo() {[]}
|
||||
''', GroovyAssignabilityCheckInspection)
|
||||
}
|
||||
|
||||
void testCastClosureToInterface() {
|
||||
testHighlighting('''\
|
||||
interface Function<D, F> {
|
||||
F fun(D d)
|
||||
}
|
||||
|
||||
def foo(Function<String, String> function) {
|
||||
// print function.fun('abc')
|
||||
}
|
||||
|
||||
|
||||
foo<warning descr="'foo' in '_' cannot be applied to '(Function<java.lang.Double,java.lang.Double>)'">({println it.byteValue()} as Function<Double, Double>)</warning>
|
||||
foo({println it.substring(1)} as Function)
|
||||
foo({println it.substring(1)} as Function<String, String>)
|
||||
foo<warning descr="'foo' in '_' cannot be applied to '(groovy.lang.Closure<java.lang.Void>)'">({println it})</warning>
|
||||
|
||||
''', GroovyAssignabilityCheckInspection)
|
||||
}
|
||||
|
||||
|
||||
+13
-1
@@ -38,6 +38,16 @@ import java.util.List;
|
||||
public class DomElementAnnotationHolderImpl extends SmartList<DomElementProblemDescriptor> implements DomElementAnnotationHolder {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.util.xml.highlighting.DomElementAnnotationHolderImpl");
|
||||
private final SmartList<Annotation> myAnnotations = new SmartList<Annotation>();
|
||||
private final boolean myOnTheFly;
|
||||
|
||||
public DomElementAnnotationHolderImpl(boolean onTheFly) {
|
||||
myOnTheFly = onTheFly;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOnTheFly() {
|
||||
return myOnTheFly;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public DomElementProblemDescriptor createProblem(@NotNull DomElement domElement, @Nullable String message, LocalQuickFix... fixes) {
|
||||
@@ -104,7 +114,9 @@ public class DomElementAnnotationHolderImpl extends SmartList<DomElementProblemD
|
||||
return size();
|
||||
}
|
||||
|
||||
private static LocalQuickFix[] getQuickFixes(final GenericDomValue element, PsiReference reference) {
|
||||
private LocalQuickFix[] getQuickFixes(final GenericDomValue element, PsiReference reference) {
|
||||
if (!myOnTheFly) return LocalQuickFix.EMPTY_ARRAY;
|
||||
|
||||
final List<LocalQuickFix> result = new SmartList<LocalQuickFix>();
|
||||
final Converter converter = WrappingConverter.getDeepestConverter(element.getConverter(), element);
|
||||
if (converter instanceof ResolvingConverter) {
|
||||
|
||||
+3
-2
@@ -235,13 +235,14 @@ public class DomElementAnnotationsManagerImpl extends DomElementAnnotationsManag
|
||||
|
||||
@NotNull
|
||||
public <T extends DomElement> List<DomElementProblemDescriptor> checkFileElement(@NotNull final DomFileElement<T> domFileElement,
|
||||
@NotNull final DomElementsInspection<T> inspection) {
|
||||
@NotNull final DomElementsInspection<T> inspection,
|
||||
boolean onTheFly) {
|
||||
final DomElementsProblemsHolder problemHolder = getProblemHolder(domFileElement);
|
||||
if (isHolderUpToDate(domFileElement) && problemHolder.isInspectionCompleted(inspection)) {
|
||||
return problemHolder.getAllProblems(inspection);
|
||||
}
|
||||
|
||||
final DomElementAnnotationHolder holder = new DomElementAnnotationHolderImpl();
|
||||
final DomElementAnnotationHolder holder = new DomElementAnnotationHolderImpl(onTheFly);
|
||||
inspection.checkFileElement(domFileElement, holder);
|
||||
return appendProblems(domFileElement, holder, inspection.getClass());
|
||||
}
|
||||
|
||||
@@ -116,18 +116,10 @@ public class DomHighlightingHelperImpl extends DomHighlightingHelper {
|
||||
if (valueElement != null && !isSoftReference(element)) {
|
||||
final SmartList<DomElementProblemDescriptor> list = new SmartList<DomElementProblemDescriptor>();
|
||||
final PsiReference[] psiReferences = myProvider.getReferencesByElement(valueElement, new ProcessingContext());
|
||||
GenericDomValueReference domReference = null;
|
||||
for (final PsiReference reference : psiReferences) {
|
||||
if (reference instanceof GenericDomValueReference) {
|
||||
domReference = (GenericDomValueReference)reference;
|
||||
break;
|
||||
}
|
||||
}
|
||||
GenericDomValueReference domReference = ContainerUtil.findInstance(psiReferences, GenericDomValueReference.class);
|
||||
final Converter converter = WrappingConverter.getDeepestConverter(element.getConverter(), element);
|
||||
final boolean domReferenceResolveOK = domReference != null && !hasBadResolve(domReference)
|
||||
|| domReference != null && converter instanceof ResolvingConverter && ((ResolvingConverter)converter).getAdditionalVariants(domReference.getConvertContext()).contains(element.getStringValue());
|
||||
boolean hasBadResolve = false;
|
||||
if (!domReferenceResolveOK) {
|
||||
if (!(domReference != null && isDomResolveOK(element, domReference, converter))) {
|
||||
for (final PsiReference reference : psiReferences) {
|
||||
if (reference != domReference && hasBadResolve(reference)) {
|
||||
hasBadResolve = true;
|
||||
@@ -158,6 +150,11 @@ public class DomHighlightingHelperImpl extends DomHighlightingHelper {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private static boolean isDomResolveOK(GenericDomValue element, GenericDomValueReference domReference, Converter converter) {
|
||||
return !hasBadResolve(domReference)
|
||||
|| converter instanceof ResolvingConverter && ((ResolvingConverter)converter).getAdditionalVariants(domReference.getConvertContext()).contains(element.getStringValue());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<DomElementProblemDescriptor> checkNameIdentity(DomElement element, final DomElementAnnotationHolder holder) {
|
||||
final String elementName = ElementPresentationManager.getElementName(element);
|
||||
|
||||
@@ -48,7 +48,7 @@ public class DefaultDomAnnotator implements Annotator {
|
||||
DomElementAnnotationsManagerImpl annotationsManager = getAnnotationsManager(fileElement);
|
||||
if (DomElementAnnotationsManagerImpl.isHolderUpToDate(fileElement) && annotationsManager.getProblemHolder(fileElement).isInspectionCompleted(inspection)) return;
|
||||
|
||||
final DomElementAnnotationHolderImpl annotationHolder = new DomElementAnnotationHolderImpl();
|
||||
final DomElementAnnotationHolderImpl annotationHolder = new DomElementAnnotationHolderImpl(true);
|
||||
inspection.checkFileElement(fileElement, annotationHolder);
|
||||
annotationsManager.appendProblems(fileElement, annotationHolder, inspection.getClass());
|
||||
for (final DomElementProblemDescriptor descriptor : annotationHolder) {
|
||||
|
||||
@@ -29,6 +29,8 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface DomElementAnnotationHolder extends Iterable<DomElementProblemDescriptor>{
|
||||
|
||||
boolean isOnTheFly();
|
||||
|
||||
@NotNull
|
||||
DomElementProblemDescriptor createProblem(@NotNull DomElement domElement, @Nullable String message, LocalQuickFix... fixes);
|
||||
|
||||
|
||||
+5
-1
@@ -52,12 +52,16 @@ public abstract class DomElementAnnotationsManager {
|
||||
* Calls {@link com.intellij.util.xml.highlighting.DomElementsInspection#checkFileElement(com.intellij.util.xml.DomFileElement, DomElementAnnotationHolder)}
|
||||
* with appropriate parameters if needed, saves the collected problems to {@link com.intellij.util.xml.highlighting.DomElementsProblemsHolder}, which
|
||||
* can then be obtained from {@link #getProblemHolder(com.intellij.util.xml.DomElement)} method, and returns them.
|
||||
*
|
||||
* @param element file element being checked
|
||||
* @param inspection inspection to run on the given file element
|
||||
* @param onTheFly
|
||||
* @return collected DOM problem descriptors
|
||||
*/
|
||||
@NotNull
|
||||
public abstract <T extends DomElement> List<DomElementProblemDescriptor> checkFileElement(@NotNull DomFileElement<T> element, @NotNull DomElementsInspection<T> inspection);
|
||||
public abstract <T extends DomElement> List<DomElementProblemDescriptor> checkFileElement(@NotNull DomFileElement<T> element,
|
||||
@NotNull DomElementsInspection<T> inspection,
|
||||
boolean onTheFly);
|
||||
|
||||
public abstract void dropAnnotationsCache();
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ public abstract class DomElementsInspection<T extends DomElement> extends XmlSup
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called internally in {@link com.intellij.util.xml.highlighting.DomElementAnnotationsManager#checkFileElement(com.intellij.util.xml.DomFileElement, DomElementsInspection)},
|
||||
* This method is called internally in {@link DomElementAnnotationsManager#checkFileElement(com.intellij.util.xml.DomFileElement, DomElementsInspection, boolean)}
|
||||
* it should add some problems to the annotation holder. The default implementation performs recursive tree traversal, and calls
|
||||
* {@link #checkDomElement(com.intellij.util.xml.DomElement, DomElementAnnotationHolder, DomHighlightingHelper)} for each element.
|
||||
* @param domFileElement file element to check
|
||||
@@ -143,7 +143,7 @@ public abstract class DomElementsInspection<T extends DomElement> extends XmlSup
|
||||
@SuppressWarnings("UnusedParameters") final boolean isOnTheFly) {
|
||||
final DomElementAnnotationsManager annotationsManager = DomElementAnnotationsManager.getInstance(manager.getProject());
|
||||
|
||||
final List<DomElementProblemDescriptor> list = annotationsManager.checkFileElement(domFileElement, this);
|
||||
final List<DomElementProblemDescriptor> list = annotationsManager.checkFileElement(domFileElement, this, isOnTheFly);
|
||||
if (list.isEmpty()) return ProblemDescriptor.EMPTY_ARRAY;
|
||||
|
||||
List<ProblemDescriptor> problems =
|
||||
|
||||
@@ -117,25 +117,29 @@ public class DomHighlightingLiteTest extends DomTestCase {
|
||||
}
|
||||
|
||||
public void testProblemDescriptorIsCreated() throws Throwable {
|
||||
myAnnotationsManager.appendProblems(myElement, new DomElementAnnotationHolderImpl(), MyDomElementsInspection.class);
|
||||
myAnnotationsManager.appendProblems(myElement, createHolder(), MyDomElementsInspection.class);
|
||||
final DomElementsProblemsHolderImpl holder = assertNotEmptyHolder(myAnnotationsManager.getProblemHolder(myElement));
|
||||
assertEmpty(holder.getAllProblems());
|
||||
assertEmpty(holder.getAllProblems(new MyDomElementsInspection()));
|
||||
}
|
||||
|
||||
private static DomElementAnnotationHolderImpl createHolder() {
|
||||
return new DomElementAnnotationHolderImpl(true);
|
||||
}
|
||||
|
||||
private static DomElementsProblemsHolderImpl assertNotEmptyHolder(final DomElementsProblemsHolder holder1) {
|
||||
return assertInstanceOf(holder1, DomElementsProblemsHolderImpl.class);
|
||||
}
|
||||
|
||||
public void testInspectionMarkedAsPassedAfterAppend() throws Throwable {
|
||||
myAnnotationsManager.appendProblems(myElement, new DomElementAnnotationHolderImpl(), MyDomElementsInspection.class);
|
||||
myAnnotationsManager.appendProblems(myElement, createHolder(), MyDomElementsInspection.class);
|
||||
final DomElementsProblemsHolderImpl holder = (DomElementsProblemsHolderImpl)myAnnotationsManager.getProblemHolder(myElement);
|
||||
assertTrue(holder.isInspectionCompleted(MyDomElementsInspection.class));
|
||||
assertFalse(holder.isInspectionCompleted(DomElementsInspection.class));
|
||||
}
|
||||
|
||||
public void testHolderRecreationAfterChange() throws Throwable {
|
||||
myAnnotationsManager.appendProblems(myElement, new DomElementAnnotationHolderImpl(), MyDomElementsInspection.class);
|
||||
myAnnotationsManager.appendProblems(myElement, createHolder(), MyDomElementsInspection.class);
|
||||
assertTrue(DomElementAnnotationsManagerImpl.isHolderUpToDate(myElement));
|
||||
final DomElementsProblemsHolder holder = myAnnotationsManager.getProblemHolder(myElement);
|
||||
|
||||
@@ -143,7 +147,7 @@ public class DomHighlightingLiteTest extends DomTestCase {
|
||||
assertFalse(DomElementAnnotationsManagerImpl.isHolderUpToDate(myElement));
|
||||
assertSame(holder, myAnnotationsManager.getProblemHolder(myElement));
|
||||
|
||||
myAnnotationsManager.appendProblems(myElement, new DomElementAnnotationHolderImpl(), MyDomElementsInspection.class);
|
||||
myAnnotationsManager.appendProblems(myElement, createHolder(), MyDomElementsInspection.class);
|
||||
assertNotSame(holder, assertNotEmptyHolder(myAnnotationsManager.getProblemHolder(myElement)));
|
||||
}
|
||||
|
||||
@@ -194,13 +198,13 @@ public class DomHighlightingLiteTest extends DomTestCase {
|
||||
myElement.setFileDescription(new MyNonHighlightingDomFileDescription());
|
||||
assertEquals(DomHighlightStatus.NONE, myAnnotationsManager.getHighlightStatus(myElement));
|
||||
|
||||
myAnnotationsManager.appendProblems(myElement, new DomElementAnnotationHolderImpl(), MockDomInspection.class);
|
||||
myAnnotationsManager.appendProblems(myElement, createHolder(), MockDomInspection.class);
|
||||
assertEquals(DomHighlightStatus.INSPECTIONS_FINISHED, myAnnotationsManager.getHighlightStatus(myElement));
|
||||
}
|
||||
public void testHighlightStatus_MockAnnotatingDomInspection() throws Throwable {
|
||||
myElement.setFileDescription(new DomFileDescription(DomElement.class, "a"));
|
||||
|
||||
myAnnotationsManager.appendProblems(myElement, new DomElementAnnotationHolderImpl(), MockAnnotatingDomInspection.class);
|
||||
myAnnotationsManager.appendProblems(myElement, createHolder(), MockAnnotatingDomInspection.class);
|
||||
assertEquals(DomHighlightStatus.INSPECTIONS_FINISHED, myAnnotationsManager.getHighlightStatus(myElement));
|
||||
}
|
||||
|
||||
@@ -211,7 +215,7 @@ public class DomHighlightingLiteTest extends DomTestCase {
|
||||
@Override
|
||||
public ProblemDescriptor[] checkFile(@NotNull final PsiFile file, @NotNull final InspectionManager manager,
|
||||
final boolean isOnTheFly) {
|
||||
myAnnotationsManager.appendProblems(myElement, new DomElementAnnotationHolderImpl(), this.getClass());
|
||||
myAnnotationsManager.appendProblems(myElement, createHolder(), this.getClass());
|
||||
return new ProblemDescriptor[0];
|
||||
}
|
||||
|
||||
@@ -222,10 +226,10 @@ public class DomHighlightingLiteTest extends DomTestCase {
|
||||
HighlightDisplayKey.register(inspection.getShortName());
|
||||
myInspectionProfile.setInspectionTools(inspection);
|
||||
|
||||
myAnnotationsManager.appendProblems(myElement, new DomElementAnnotationHolderImpl(), MockAnnotatingDomInspection.class);
|
||||
myAnnotationsManager.appendProblems(myElement, createHolder(), MockAnnotatingDomInspection.class);
|
||||
assertEquals(DomHighlightStatus.ANNOTATORS_FINISHED, myAnnotationsManager.getHighlightStatus(myElement));
|
||||
|
||||
myAnnotationsManager.appendProblems(myElement, new DomElementAnnotationHolderImpl(), inspection.getClass());
|
||||
myAnnotationsManager.appendProblems(myElement, createHolder(), inspection.getClass());
|
||||
assertEquals(DomHighlightStatus.INSPECTIONS_FINISHED, myAnnotationsManager.getHighlightStatus(myElement));
|
||||
}
|
||||
|
||||
@@ -236,7 +240,7 @@ public class DomHighlightingLiteTest extends DomTestCase {
|
||||
@Override
|
||||
public ProblemDescriptor[] checkFile(@NotNull final PsiFile file, @NotNull final InspectionManager manager,
|
||||
final boolean isOnTheFly) {
|
||||
myAnnotationsManager.appendProblems(myElement, new DomElementAnnotationHolderImpl(), this.getClass());
|
||||
myAnnotationsManager.appendProblems(myElement, createHolder(), this.getClass());
|
||||
return new ProblemDescriptor[0];
|
||||
}
|
||||
|
||||
@@ -248,13 +252,13 @@ public class DomHighlightingLiteTest extends DomTestCase {
|
||||
myInspectionProfile.setInspectionTools(inspection);
|
||||
myInspectionProfile.setEnabled(inspection, false);
|
||||
|
||||
myAnnotationsManager.appendProblems(myElement, new DomElementAnnotationHolderImpl(), MockAnnotatingDomInspection.class);
|
||||
myAnnotationsManager.appendProblems(myElement, createHolder(), MockAnnotatingDomInspection.class);
|
||||
assertEquals(DomHighlightStatus.INSPECTIONS_FINISHED, myAnnotationsManager.getHighlightStatus(myElement));
|
||||
}
|
||||
|
||||
public void testRequiredAttributeWithoutAttributeValue() throws Throwable {
|
||||
final MyElement element = createElement("<a id />", MyElement.class);
|
||||
new MyBasicDomElementsInspection().checkDomElement(element.getId(), new DomElementAnnotationHolderImpl(), DomHighlightingHelperImpl.INSTANCE);
|
||||
new MyBasicDomElementsInspection().checkDomElement(element.getId(), createHolder(), DomHighlightingHelperImpl.INSTANCE);
|
||||
}
|
||||
|
||||
private class MyDomElementsInspection extends DomElementsInspection {
|
||||
|
||||
Reference in New Issue
Block a user