mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-15 02:59:33 +07:00
Magic constant inspection
This commit is contained in:
@@ -145,7 +145,7 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
|
||||
if (document == null) continue;
|
||||
final XmlTag rootTag = document.getRootTag();
|
||||
if (rootTag == null) continue;
|
||||
final String externalName = PsiFormatUtil.getExternalName(listOwner, false);
|
||||
final String externalName = getExternalName(listOwner, false);
|
||||
final String oldExternalName = getNormalizedExternalName(listOwner);
|
||||
for (final XmlTag tag : rootTag.getSubTags()) {
|
||||
final String className = tag.getAttributeValue("name");
|
||||
@@ -179,6 +179,10 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
|
||||
return result;
|
||||
}
|
||||
|
||||
private static String getExternalName(PsiModifierListOwner listOwner, boolean showParamName) {
|
||||
return PsiFormatUtil.getExternalName(listOwner, showParamName, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
|
||||
public void annotateExternally(@NotNull final PsiModifierListOwner listOwner,
|
||||
@NotNull final String annotationFQName,
|
||||
@@ -317,7 +321,7 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
|
||||
if (document != null) {
|
||||
final XmlTag rootTag = document.getRootTag();
|
||||
if (rootTag != null) {
|
||||
final String externalName = PsiFormatUtil.getExternalName(listOwner, false);
|
||||
final String externalName = getExternalName(listOwner, false);
|
||||
final String oldExternalName = getNormalizedExternalName(listOwner);
|
||||
for (final XmlTag tag : rootTag.getSubTags()) {
|
||||
final String className = tag.getAttributeValue("name");
|
||||
@@ -445,7 +449,7 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
|
||||
final XmlDocument document = xmlFile.getDocument();
|
||||
if (document != null) {
|
||||
final XmlTag rootTag = document.getRootTag();
|
||||
final String externalName = PsiFormatUtil.getExternalName(listOwner, false);
|
||||
final String externalName = getExternalName(listOwner, false);
|
||||
if (rootTag != null) {
|
||||
for (XmlTag tag : rootTag.getSubTags()) {
|
||||
if (Comparing.strEqual(tag.getAttributeValue("name"), externalName)) {
|
||||
@@ -603,7 +607,7 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
|
||||
|
||||
@Nullable
|
||||
private static String getNormalizedExternalName(PsiModifierListOwner owner) {
|
||||
String externalName = PsiFormatUtil.getExternalName(owner);
|
||||
String externalName = getExternalName(owner, true);
|
||||
if (externalName != null) {
|
||||
if (owner instanceof PsiParameter && owner.getParent() instanceof PsiParameterList) {
|
||||
final PsiMethod method = PsiTreeUtil.getParentOfType(owner, PsiMethod.class);
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* 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.codeInspection.magicConstant;
|
||||
|
||||
import com.intellij.codeInsight.completion.*;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupElementBuilder;
|
||||
import com.intellij.codeInsight.lookup.LookupItemUtil;
|
||||
import com.intellij.codeInsight.lookup.VariableLookupItem;
|
||||
import com.intellij.patterns.ElementPattern;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Consumer;
|
||||
import gnu.trove.THashSet;
|
||||
import gnu.trove.TObjectHashingStrategy;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import static com.intellij.patterns.PlatformPatterns.psiElement;
|
||||
|
||||
public class MagicCompletionContributor extends CompletionContributor {
|
||||
private static final ElementPattern<PsiElement> IN_METHOD_CALL_ARGUMENT =
|
||||
psiElement().withParent(psiElement(PsiReferenceExpression.class).inside(psiElement(PsiExpressionList.class).withParent(PsiCall.class)));
|
||||
private static final ElementPattern<PsiElement> IN_BINARY_COMPARISON =
|
||||
psiElement().withParent(psiElement(PsiReferenceExpression.class).inside(psiElement(PsiBinaryExpression.class)));
|
||||
private static final ElementPattern<PsiElement> IN_ASSIGNMENT =
|
||||
psiElement().withParent(psiElement(PsiReferenceExpression.class).inside(psiElement(PsiAssignmentExpression.class)));
|
||||
private static final ElementPattern<PsiElement> IN_RETURN =
|
||||
psiElement().withParent(psiElement(PsiReferenceExpression.class).inside(psiElement(PsiReturnStatement.class)));
|
||||
private static final ElementPattern<PsiElement> IN_ANNOTATION_INITIALIZER =
|
||||
psiElement().afterLeaf("=").withParent(PsiReferenceExpression.class).withSuperParent(2,PsiNameValuePair.class).withSuperParent(3,PsiAnnotationParameterList.class).withSuperParent(4,PsiAnnotation.class);
|
||||
private static final int PRIORITY = 100;
|
||||
|
||||
@Override
|
||||
public void fillCompletionVariants(final CompletionParameters parameters, final CompletionResultSet result) {
|
||||
//if (parameters.getCompletionType() != CompletionType.SMART) return;
|
||||
PsiElement pos = parameters.getPosition();
|
||||
MagicConstantInspection.AllowedValues allowedValues = null;
|
||||
|
||||
if (IN_METHOD_CALL_ARGUMENT.accepts(pos)) {
|
||||
PsiCall call = PsiTreeUtil.getParentOfType(pos, PsiCall.class);
|
||||
if (!(call instanceof PsiExpression)) return;
|
||||
PsiType type = ((PsiExpression)call).getType();
|
||||
|
||||
PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(call.getProject()).getResolveHelper();
|
||||
JavaResolveResult[] methods = call instanceof PsiMethodCallExpression
|
||||
? ((PsiMethodCallExpression)call).getMethodExpression().multiResolve(true)
|
||||
: call instanceof PsiNewExpression && type instanceof PsiClassType
|
||||
? resolveHelper.multiResolveConstructor((PsiClassType)type, call.getArgumentList(), call)
|
||||
: JavaResolveResult.EMPTY_ARRAY;
|
||||
for (JavaResolveResult resolveResult : methods) {
|
||||
PsiElement element = resolveResult.getElement();
|
||||
if (!(element instanceof PsiMethod)) return;
|
||||
PsiMethod method = (PsiMethod)element;
|
||||
if (!resolveHelper.isAccessible(method, call, null)) continue;
|
||||
PsiElement argument = pos;
|
||||
while (!(argument.getParent() instanceof PsiExpressionList)) argument = argument.getParent();
|
||||
PsiExpressionList list = (PsiExpressionList)argument.getParent();
|
||||
int i = ArrayUtil.indexOf(list.getExpressions(), argument);
|
||||
if (i == -1) continue;
|
||||
PsiParameter[] params = method.getParameterList().getParameters();
|
||||
if (i >= params.length) continue;
|
||||
PsiParameter parameter = params[i];
|
||||
MagicConstantInspection.AllowedValues values =
|
||||
parameter == null ? null : MagicConstantInspection.getAllowedValues(parameter, parameter.getType(), null);
|
||||
if (values == null) continue;
|
||||
if (allowedValues == null) {
|
||||
allowedValues = values;
|
||||
continue;
|
||||
}
|
||||
if (!allowedValues.equals(values)) return;
|
||||
}
|
||||
}
|
||||
else if (IN_BINARY_COMPARISON.accepts(pos)) {
|
||||
PsiBinaryExpression exp = PsiTreeUtil.getParentOfType(pos, PsiBinaryExpression.class);
|
||||
if (exp != null && (exp.getOperationTokenType() == JavaTokenType.EQEQ || exp.getOperationTokenType() == JavaTokenType.NE)) {
|
||||
PsiExpression l = exp.getLOperand();
|
||||
PsiElement resolved;
|
||||
if (l instanceof PsiReferenceExpression && (resolved = ((PsiReferenceExpression)l).resolve()) instanceof PsiModifierListOwner) {
|
||||
allowedValues = MagicConstantInspection.getAllowedValues((PsiModifierListOwner)resolved, l.getType(), null);
|
||||
}
|
||||
PsiExpression r = exp.getROperand();
|
||||
if (allowedValues == null && r instanceof PsiReferenceExpression && (resolved = ((PsiReferenceExpression)r).resolve()) instanceof PsiModifierListOwner) {
|
||||
allowedValues = MagicConstantInspection.getAllowedValues((PsiModifierListOwner)resolved, r.getType(), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (IN_ASSIGNMENT.accepts(pos)) {
|
||||
PsiAssignmentExpression assignment = PsiTreeUtil.getParentOfType(pos, PsiAssignmentExpression.class);
|
||||
PsiElement resolved;
|
||||
PsiExpression l = assignment == null ? null : assignment.getLExpression();
|
||||
if (assignment != null && PsiTreeUtil.isAncestor(assignment.getRExpression(), pos, false) && l instanceof PsiReferenceExpression && (resolved = ((PsiReferenceExpression)l).resolve()) instanceof PsiModifierListOwner) {
|
||||
allowedValues = MagicConstantInspection.getAllowedValues((PsiModifierListOwner)resolved, l.getType(), null);
|
||||
}
|
||||
}
|
||||
else if (IN_RETURN.accepts(pos)) {
|
||||
PsiReturnStatement statement = PsiTreeUtil.getParentOfType(pos, PsiReturnStatement.class);
|
||||
PsiExpression l = statement == null ? null : statement.getReturnValue();
|
||||
PsiMethod method = PsiTreeUtil.getParentOfType(l, PsiMethod.class);
|
||||
if (method != null) {
|
||||
allowedValues = MagicConstantInspection.getAllowedValues(method, method.getReturnType(), null);
|
||||
}
|
||||
}
|
||||
else if (IN_ANNOTATION_INITIALIZER.accepts(pos)) {
|
||||
PsiNameValuePair pair = (PsiNameValuePair)pos.getParent().getParent();
|
||||
PsiAnnotationMemberValue value = pair.getValue();
|
||||
if (!(value instanceof PsiExpression)) return;
|
||||
PsiReference ref = pair.getReference();
|
||||
if (ref == null) return;
|
||||
PsiMethod method = (PsiMethod)ref.resolve();
|
||||
if (method == null) return;
|
||||
allowedValues = MagicConstantInspection.getAllowedValues(method, method.getReturnType(), null);
|
||||
}
|
||||
if (allowedValues == null) return;
|
||||
|
||||
final Set<PsiElement> allowed = new THashSet<PsiElement>(new TObjectHashingStrategy<PsiElement>() {
|
||||
@Override
|
||||
public int computeHashCode(PsiElement object) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(PsiElement o1, PsiElement o2) {
|
||||
return parameters.getOriginalFile().getManager().areElementsEquivalent(o1, o2);
|
||||
}
|
||||
});
|
||||
if (allowedValues.canBeOred) {
|
||||
PsiElementFactory factory = JavaPsiFacade.getElementFactory(pos.getProject());
|
||||
PsiExpression e0 = factory.createExpressionFromText("0", pos);
|
||||
result.addElement(PrioritizedLookupElement.withPriority(LookupElementBuilder.create(e0,"0"), PRIORITY-1));
|
||||
PsiExpression e1 = factory.createExpressionFromText("-1", pos);
|
||||
result.addElement(PrioritizedLookupElement.withPriority(LookupElementBuilder.create(e1,"-1"), PRIORITY-1));
|
||||
allowed.add(e0);
|
||||
allowed.add(e1);
|
||||
}
|
||||
for (PsiAnnotationMemberValue value : allowedValues.values) {
|
||||
if (value instanceof PsiReference) {
|
||||
PsiElement resolved = ((PsiReference)value).resolve();
|
||||
if (resolved instanceof PsiNamedElement) {
|
||||
|
||||
LookupElement lookupElement = LookupItemUtil.objectToLookupItem(resolved);
|
||||
if (lookupElement instanceof VariableLookupItem) {
|
||||
((VariableLookupItem)lookupElement).setSubstitutor(PsiSubstitutor.EMPTY);
|
||||
}
|
||||
result.addElement(PrioritizedLookupElement.withPriority(lookupElement, PRIORITY));
|
||||
allowed.add(resolved);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
LookupElementBuilder builder = LookupElementBuilder.create(value, value.getText());
|
||||
result.addElement(builder);
|
||||
allowed.add(value);
|
||||
}
|
||||
result.runRemainingContributors(parameters, new Consumer<CompletionResult>() {
|
||||
@Override
|
||||
public void consume(CompletionResult completionResult) {
|
||||
LookupElement element = completionResult.getLookupElement();
|
||||
if (allowed.contains(element.getObject())) {
|
||||
return;
|
||||
}
|
||||
result.passResult(completionResult);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,544 @@
|
||||
/*
|
||||
* 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.codeInspection.magicConstant;
|
||||
|
||||
import com.intellij.analysis.AnalysisScope;
|
||||
import com.intellij.codeInsight.AnnotationUtil;
|
||||
import com.intellij.codeInsight.daemon.GroupNames;
|
||||
import com.intellij.codeInspection.LocalInspectionTool;
|
||||
import com.intellij.codeInspection.LocalInspectionToolSession;
|
||||
import com.intellij.codeInspection.ProblemsHolder;
|
||||
import com.intellij.ide.util.treeView.AbstractTreeNode;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.javadoc.PsiDocComment;
|
||||
import com.intellij.psi.javadoc.PsiDocTag;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.LocalSearchScope;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.PropertyUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.slicer.*;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.Processor;
|
||||
import gnu.trove.THashSet;
|
||||
import org.intellij.lang.annotations.MagicConstant;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class MagicConstantInspection extends LocalInspectionTool {
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return "Magic Constant";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getShortName() {
|
||||
return "MagicConstant";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder,
|
||||
boolean isOnTheFly,
|
||||
@NotNull LocalInspectionToolSession session) {
|
||||
return new JavaElementVisitor() {
|
||||
@Override
|
||||
public void visitCallExpression(PsiCallExpression callExpression) {
|
||||
checkCall(callExpression, holder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitAssignmentExpression(PsiAssignmentExpression expression) {
|
||||
PsiExpression r = expression.getRExpression();
|
||||
if (r == null) return;
|
||||
PsiExpression l = expression.getLExpression();
|
||||
if (!(l instanceof PsiReferenceExpression)) return;
|
||||
PsiElement resolved = ((PsiReferenceExpression)l).resolve();
|
||||
if (!(resolved instanceof PsiModifierListOwner)) return;
|
||||
PsiModifierListOwner owner = (PsiModifierListOwner)resolved;
|
||||
PsiType type = expression.getType();
|
||||
checkExpression(r, owner, type, holder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitReturnStatement(PsiReturnStatement statement) {
|
||||
PsiExpression value = statement.getReturnValue();
|
||||
if (value == null) return;
|
||||
PsiMethod method = PsiTreeUtil.getParentOfType(statement, PsiMethod.class);
|
||||
if (method == null) return;
|
||||
checkExpression(value, method, value.getType(), holder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNameValuePair(PsiNameValuePair pair) {
|
||||
PsiAnnotationMemberValue value = pair.getValue();
|
||||
if (!(value instanceof PsiExpression)) return;
|
||||
PsiReference ref = pair.getReference();
|
||||
if (ref == null) return;
|
||||
PsiMethod method = (PsiMethod)ref.resolve();
|
||||
if (method == null) return;
|
||||
checkExpression((PsiExpression)value, method, method.getReturnType(), holder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitBinaryExpression(PsiBinaryExpression expression) {
|
||||
IElementType tokenType = expression.getOperationTokenType();
|
||||
if (tokenType != JavaTokenType.EQEQ && tokenType != JavaTokenType.NE) return;
|
||||
PsiExpression l = expression.getLOperand();
|
||||
PsiExpression r = expression.getROperand();
|
||||
if (r == null) return;
|
||||
checkBinary(l, r);
|
||||
checkBinary(r, l);
|
||||
}
|
||||
|
||||
private void checkBinary(PsiExpression l, PsiExpression r) {
|
||||
if (l instanceof PsiReference) {
|
||||
PsiElement resolved = ((PsiReference)l).resolve();
|
||||
if (resolved instanceof PsiModifierListOwner) {
|
||||
checkExpression(r, (PsiModifierListOwner)resolved, getType((PsiModifierListOwner)resolved), holder);
|
||||
}
|
||||
}
|
||||
else if (l instanceof PsiMethodCallExpression) {
|
||||
PsiMethod method = ((PsiMethodCallExpression)l).resolveMethod();
|
||||
if (method != null) {
|
||||
checkExpression(r, method, method.getReturnType(), holder);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static void checkExpression(PsiExpression expression,
|
||||
PsiModifierListOwner owner,
|
||||
PsiType type,
|
||||
ProblemsHolder holder) {
|
||||
AllowedValues allowed = getAllowedValues(owner, type, null);
|
||||
if (allowed == null) return;
|
||||
PsiElement scope = PsiUtil.getTopLevelEnclosingCodeBlock(expression, null);
|
||||
if (scope == null) scope = expression;
|
||||
if (!isAllowed(scope, expression, allowed, expression.getManager())) {
|
||||
registerProblem(expression, allowed, holder);
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkCall(@NotNull PsiCallExpression methodCall, @NotNull ProblemsHolder holder) {
|
||||
PsiMethod method = methodCall.resolveMethod();
|
||||
if (method == null) return;
|
||||
PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
PsiExpression[] arguments = methodCall.getArgumentList().getExpressions();
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
PsiParameter parameter = parameters[i];
|
||||
AllowedValues values = getAllowedValues(parameter, parameter.getType(), null);
|
||||
if (values == null) continue;
|
||||
//PsiAnnotation annotation = AnnotationUtil.findAnnotation(parameter, Collections.singletonList(MagicConstant.class.getName()));
|
||||
//if (annotation == null) continue;
|
||||
if (i >= arguments.length) break;
|
||||
PsiExpression argument = arguments[i];
|
||||
argument = PsiUtil.deparenthesizeExpression(argument);
|
||||
if (argument == null) continue;
|
||||
|
||||
checkMagicParameterArgument(parameter, argument, values, holder);
|
||||
}
|
||||
}
|
||||
|
||||
static class AllowedValues {
|
||||
final PsiAnnotationMemberValue[] values;
|
||||
final boolean canBeOred;
|
||||
|
||||
private AllowedValues(PsiAnnotationMemberValue[] values, boolean canBeOred) {
|
||||
this.values = values;
|
||||
this.canBeOred = canBeOred;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
AllowedValues a2 = (AllowedValues)o;
|
||||
if (canBeOred != a2.canBeOred) {
|
||||
return false;
|
||||
}
|
||||
Set<PsiAnnotationMemberValue> v1 = new THashSet<PsiAnnotationMemberValue>(Arrays.asList(values));
|
||||
Set<PsiAnnotationMemberValue> v2 = new THashSet<PsiAnnotationMemberValue>(Arrays.asList(a2.values));
|
||||
if (v1.size() != v2.size()) {
|
||||
return false;
|
||||
}
|
||||
for (PsiAnnotationMemberValue value : v1) {
|
||||
for (PsiAnnotationMemberValue value2 : v2) {
|
||||
if (same(value, value2, value.getManager())) {
|
||||
v2.remove(value2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return v2.isEmpty();
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = values != null ? Arrays.hashCode(values) : 0;
|
||||
result = 31 * result + (canBeOred ? 1 : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private static AllowedValues getAllowedValuesFromMagic(@NotNull PsiModifierListOwner element, @NotNull PsiType type) {
|
||||
PsiAnnotation magic = AnnotationUtil.findAnnotationInHierarchy(element, Collections.singleton(MagicConstant.class.getName()));
|
||||
if (magic == null) return null;
|
||||
PsiAnnotationMemberValue[] allowedValues;
|
||||
final boolean canBeOred;
|
||||
if (TypeConversionUtil.getTypeRank(type) <= TypeConversionUtil.LONG_RANK) {
|
||||
PsiAnnotationMemberValue intValues = magic.findAttributeValue("intValues");
|
||||
allowedValues = intValues instanceof PsiArrayInitializerMemberValue
|
||||
? ((PsiArrayInitializerMemberValue)intValues).getInitializers() : PsiAnnotationMemberValue.EMPTY_ARRAY;
|
||||
if (allowedValues.length == 0) {
|
||||
PsiAnnotationMemberValue orValue = magic.findAttributeValue("flags");
|
||||
allowedValues = orValue instanceof PsiArrayInitializerMemberValue ? ((PsiArrayInitializerMemberValue)orValue).getInitializers() : PsiAnnotationMemberValue.EMPTY_ARRAY;
|
||||
canBeOred = true;
|
||||
}
|
||||
else {
|
||||
canBeOred = false;
|
||||
}
|
||||
}
|
||||
else if (type.equals(PsiType.getJavaLangString(element.getManager(), GlobalSearchScope.allScope(element.getProject())))) {
|
||||
PsiAnnotationMemberValue strValuesAttr = magic.findAttributeValue("stringValues");
|
||||
allowedValues = strValuesAttr instanceof PsiArrayInitializerMemberValue ? ((PsiArrayInitializerMemberValue)strValuesAttr).getInitializers() : PsiAnnotationMemberValue.EMPTY_ARRAY;
|
||||
canBeOred = false;
|
||||
}
|
||||
else {
|
||||
return null; //other types not supported
|
||||
}
|
||||
|
||||
if (allowedValues.length != 0) {
|
||||
return new AllowedValues(allowedValues, canBeOred);
|
||||
}
|
||||
|
||||
// last resort: try valuesFromClass
|
||||
PsiAnnotationMemberValue[] values = readFromClass("valuesFromClass", magic, type);
|
||||
boolean ored = false;
|
||||
if (values == null) {
|
||||
values = readFromClass("flagsFromClass", magic, type);
|
||||
ored = true;
|
||||
}
|
||||
if (values == null) return null;
|
||||
return new AllowedValues(values, ored);
|
||||
}
|
||||
|
||||
private static PsiAnnotationMemberValue[] readFromClass(@NonNls String attributeName, @NotNull PsiAnnotation magic, PsiType type) {
|
||||
PsiAnnotationMemberValue fromClassAttr = magic.findAttributeValue(attributeName);
|
||||
PsiType fromClassType = fromClassAttr instanceof PsiClassObjectAccessExpression ? ((PsiClassObjectAccessExpression)fromClassAttr).getOperand().getType() : null;
|
||||
PsiClass fromClass = fromClassType instanceof PsiClassType ? ((PsiClassType)fromClassType).resolve() : null;
|
||||
if (fromClass == null) return null;
|
||||
String fqn = fromClass.getQualifiedName();
|
||||
if (fqn == null) return null;
|
||||
List<PsiAnnotationMemberValue> constants = new ArrayList<PsiAnnotationMemberValue>();
|
||||
for (PsiField field : fromClass.getFields()) {
|
||||
if (!field.hasModifierProperty(PsiModifier.PUBLIC) || !field.hasModifierProperty(PsiModifier.STATIC) || !field.hasModifierProperty(PsiModifier.FINAL)) continue;
|
||||
PsiType fieldType = field.getType();
|
||||
if (!Comparing.equal(fieldType, type)) continue;
|
||||
PsiAssignmentExpression e = (PsiAssignmentExpression)JavaPsiFacade.getElementFactory(field.getProject()).createExpressionFromText("x="+fqn + "." + field.getName(), field);
|
||||
PsiReferenceExpression refToField = (PsiReferenceExpression)e.getRExpression();
|
||||
constants.add(refToField);
|
||||
}
|
||||
if (constants.isEmpty()) return null;
|
||||
|
||||
return constants.toArray(new PsiAnnotationMemberValue[constants.size()]);
|
||||
}
|
||||
|
||||
static AllowedValues getAllowedValues(@NotNull PsiModifierListOwner element, PsiType type, Set<PsiClass> visited) {
|
||||
AllowedValues values;
|
||||
if (type != null) {
|
||||
values = getAllowedValuesFromMagic(element, type);
|
||||
if (values != null) return values;
|
||||
}
|
||||
|
||||
PsiAnnotation[] annotations = AnnotationUtil.getAllAnnotations(element, true, null);
|
||||
for (PsiAnnotation annotation : annotations) {
|
||||
PsiJavaCodeReferenceElement ref = annotation.getNameReferenceElement();
|
||||
PsiElement resolved = ref == null ? null : ref.resolve();
|
||||
if (!(resolved instanceof PsiClass) || !((PsiClass)resolved).isAnnotationType()) continue;
|
||||
PsiClass aClass = (PsiClass)resolved;
|
||||
if (visited == null) visited = new THashSet<PsiClass>();
|
||||
if (!visited.add(aClass)) continue;
|
||||
values = getAllowedValues(aClass, type, visited);
|
||||
if (values != null) return values;
|
||||
}
|
||||
|
||||
|
||||
return parseBeanInfo(element);
|
||||
}
|
||||
|
||||
private static AllowedValues parseBeanInfo(@NotNull PsiModifierListOwner owner) {
|
||||
PsiMethod method = null;
|
||||
if (owner instanceof PsiParameter) {
|
||||
PsiParameter parameter = (PsiParameter)owner;
|
||||
PsiElement scope = parameter.getDeclarationScope();
|
||||
if (!(scope instanceof PsiMethod)) return null;
|
||||
PsiElement nav = scope.getNavigationElement();
|
||||
if (!(nav instanceof PsiMethod)) return null;
|
||||
method = (PsiMethod)nav;
|
||||
if (method.isConstructor()) {
|
||||
// not a property, try the @ConstructorProperties({"prop"})
|
||||
PsiAnnotation annotation = AnnotationUtil.findAnnotation(method, "java.beans.ConstructorProperties");
|
||||
if (annotation == null) return null;
|
||||
PsiAnnotationMemberValue value = annotation.findAttributeValue("value");
|
||||
if (!(value instanceof PsiArrayInitializerMemberValue)) return null;
|
||||
PsiAnnotationMemberValue[] initializers = ((PsiArrayInitializerMemberValue)value).getInitializers();
|
||||
PsiElement parent = parameter.getParent();
|
||||
if (!(parent instanceof PsiParameterList)) return null;
|
||||
int index = ((PsiParameterList)parent).getParameterIndex(parameter);
|
||||
if (index >= initializers.length) return null;
|
||||
PsiAnnotationMemberValue initializer = initializers[index];
|
||||
if (!(initializer instanceof PsiLiteralExpression)) return null;
|
||||
Object val = ((PsiLiteralExpression)initializer).getValue();
|
||||
if (!(val instanceof String)) return null;
|
||||
PsiMethod setter = PropertyUtil.findPropertySetter(method.getContainingClass(), (String)val, false, false);
|
||||
if (setter == null) return null;
|
||||
// try the @beaninfo of the corresponding setter
|
||||
method = (PsiMethod)setter.getNavigationElement();
|
||||
}
|
||||
}
|
||||
else if (owner instanceof PsiMethod) {
|
||||
PsiElement nav = owner.getNavigationElement();
|
||||
if (!(nav instanceof PsiMethod)) return null;
|
||||
method = (PsiMethod)nav;
|
||||
}
|
||||
if (method == null) return null;
|
||||
|
||||
PsiClass aClass = method.getContainingClass();
|
||||
if (aClass == null) return null;
|
||||
if (PropertyUtil.isSimplePropertyGetter(method)) {
|
||||
List<PsiMethod> setters = PropertyUtil.getSetters(aClass, PropertyUtil.getPropertyNameByGetter(method));
|
||||
if (setters.size() != 1) return null;
|
||||
method = setters.get(0);
|
||||
}
|
||||
if (!PropertyUtil.isSimplePropertySetter(method)) return null;
|
||||
PsiDocComment doc = method.getDocComment();
|
||||
if (doc == null) return null;
|
||||
PsiDocTag beaninfo = doc.findTagByName("beaninfo");
|
||||
if (beaninfo == null) return null;
|
||||
String data = StringUtil.join(beaninfo.getDataElements(), new Function<PsiElement, String>() {
|
||||
@Override
|
||||
public String fun(PsiElement element) {
|
||||
return element.getText();
|
||||
}
|
||||
}, "\n");
|
||||
int enumIndex = StringUtil.indexOfSubstringEnd(data, "enum:");
|
||||
if (enumIndex == -1) return null;
|
||||
data = data.substring(enumIndex);
|
||||
int colon = data.indexOf(":");
|
||||
int last = colon == -1 ? data.length() : data.substring(0,colon).lastIndexOf("\n");
|
||||
data = data.substring(0, last);
|
||||
|
||||
List<PsiAnnotationMemberValue> values = new ArrayList<PsiAnnotationMemberValue>();
|
||||
for (String line : StringUtil.splitByLines(data)) {
|
||||
List<String> words = StringUtil.split(line, " ", true, true);
|
||||
if (words.size() != 2) continue;
|
||||
String ref = words.get(1);
|
||||
PsiExpression constRef = JavaPsiFacade.getElementFactory(aClass.getProject()).createExpressionFromText(ref, aClass);
|
||||
if (!(constRef instanceof PsiReferenceExpression)) continue;
|
||||
PsiReferenceExpression expr = (PsiReferenceExpression)constRef;
|
||||
values.add(expr);
|
||||
}
|
||||
if (values.isEmpty()) return null;
|
||||
PsiAnnotationMemberValue[] array = values.toArray(new PsiAnnotationMemberValue[values.size()]);
|
||||
return new AllowedValues(array, false);
|
||||
}
|
||||
|
||||
private static PsiType getType(PsiModifierListOwner element) {
|
||||
return element instanceof PsiVariable ? ((PsiVariable)element).getType() : element instanceof PsiMethod ? ((PsiMethod)element).getReturnType() : null;
|
||||
}
|
||||
|
||||
private static void checkMagicParameterArgument(@NotNull PsiParameter parameter,
|
||||
PsiExpression argument,
|
||||
@NotNull AllowedValues allowedValues,
|
||||
@NotNull ProblemsHolder holder) {
|
||||
final PsiManager manager = PsiManager.getInstance(holder.getProject());
|
||||
|
||||
if (!argument.getTextRange().isEmpty() && !isAllowed(parameter.getDeclarationScope(), argument, allowedValues, manager)) {
|
||||
registerProblem(argument, allowedValues, holder);
|
||||
}
|
||||
}
|
||||
|
||||
private static void registerProblem(PsiExpression argument, AllowedValues allowedValues, ProblemsHolder holder) {
|
||||
String values = StringUtil.join(allowedValues.values,
|
||||
new Function<PsiAnnotationMemberValue, String>() {
|
||||
@Override
|
||||
public String fun(PsiAnnotationMemberValue value) {
|
||||
return value.getText();
|
||||
}
|
||||
}, ", ");
|
||||
holder.registerProblem(argument, "Must be one of the: "+ values);
|
||||
}
|
||||
|
||||
private static boolean isAllowed(@NotNull final PsiElement scope,
|
||||
@NotNull final PsiExpression argument,
|
||||
@NotNull final AllowedValues allowedValues,
|
||||
@NotNull final PsiManager manager) {
|
||||
if (isGoodExpression(argument, allowedValues, scope, manager)) return true;
|
||||
|
||||
return processValuesFlownTo(argument, scope, new Processor<PsiExpression>() {
|
||||
@Override
|
||||
public boolean process(PsiExpression expression) {
|
||||
if (false & !PsiTreeUtil.isAncestor(scope, expression, false)) return true;
|
||||
return isGoodExpression(expression, allowedValues, scope, manager);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static boolean isGoodExpression(PsiExpression expression,
|
||||
AllowedValues allowedValues,
|
||||
PsiElement scope,
|
||||
PsiManager manager) {
|
||||
expression = PsiUtil.deparenthesizeExpression(expression);
|
||||
if (expression == null) return true;
|
||||
if (expression instanceof PsiConditionalExpression) {
|
||||
PsiExpression thenExpression = ((PsiConditionalExpression)expression).getThenExpression();
|
||||
boolean thenAllowed = thenExpression == null || isAllowed(scope, thenExpression, allowedValues, manager);
|
||||
if (!thenAllowed) return false;
|
||||
PsiExpression elseExpression = ((PsiConditionalExpression)expression).getElseExpression();
|
||||
return elseExpression == null || isAllowed(scope, elseExpression, allowedValues, manager);
|
||||
}
|
||||
|
||||
if (isOneOf(expression, allowedValues, manager)) return true;
|
||||
|
||||
if (allowedValues.canBeOred) {
|
||||
if (expression instanceof PsiPolyadicExpression &&
|
||||
JavaTokenType.OR.equals(((PsiPolyadicExpression)expression).getOperationTokenType())) {
|
||||
for (PsiExpression operand : ((PsiPolyadicExpression)expression).getOperands()) {
|
||||
if (!isAllowed(scope, operand, allowedValues, manager)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//todo & ~(CONST | CONST)
|
||||
PsiExpression zero = JavaPsiFacade.getElementFactory(manager.getProject()).createExpressionFromText("0", expression);
|
||||
if (same(expression, zero, manager)) return true;
|
||||
PsiExpression mOne = JavaPsiFacade.getElementFactory(manager.getProject()).createExpressionFromText("-1", expression);
|
||||
if (same(expression, mOne, manager)) return true;
|
||||
}
|
||||
|
||||
PsiElement resolved = null;
|
||||
if (expression instanceof PsiReference) {
|
||||
resolved = ((PsiReference)expression).resolve();
|
||||
}
|
||||
else if (expression instanceof PsiCallExpression) {
|
||||
resolved = ((PsiCallExpression)expression).resolveMethod();
|
||||
}
|
||||
|
||||
AllowedValues allowedForRef;
|
||||
if (resolved instanceof PsiModifierListOwner &&
|
||||
(allowedForRef = getAllowedValues((PsiModifierListOwner)resolved, getType((PsiModifierListOwner)resolved), null)) != null &&
|
||||
Comparing.equal(allowedValues, allowedForRef)) return true;
|
||||
|
||||
return PsiType.NULL.equals(expression.getType());
|
||||
}
|
||||
|
||||
private static boolean isOneOf(@NotNull PsiExpression expression, @NotNull AllowedValues allowedValues, @NotNull PsiManager manager) {
|
||||
for (PsiAnnotationMemberValue allowedValue : allowedValues.values) {
|
||||
if (same(allowedValue, expression, manager)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean same(PsiElement e1, PsiElement e2, @NotNull PsiManager manager) {
|
||||
if (e1 instanceof PsiLiteralExpression && e2 instanceof PsiLiteralExpression) {
|
||||
return Comparing.equal(((PsiLiteralExpression)e1).getValue(), ((PsiLiteralExpression)e2).getValue());
|
||||
}
|
||||
if (e1 instanceof PsiPrefixExpression && e2 instanceof PsiPrefixExpression && ((PsiPrefixExpression)e1).getOperationTokenType() == ((PsiPrefixExpression)e2).getOperationTokenType()) {
|
||||
return same(((PsiPrefixExpression)e1).getOperand(), ((PsiPrefixExpression)e2).getOperand(), manager);
|
||||
}
|
||||
if (e1 instanceof PsiReference && e2 instanceof PsiReference) {
|
||||
e1 = ((PsiReference)e1).resolve();
|
||||
e2 = ((PsiReference)e2).resolve();
|
||||
}
|
||||
return manager.areElementsEquivalent(e2, e1);
|
||||
}
|
||||
|
||||
private static boolean processValuesFlownTo(@NotNull final PsiExpression argument,
|
||||
PsiElement scope,
|
||||
@NotNull final Processor<PsiExpression> processor) {
|
||||
SliceAnalysisParams params = new SliceAnalysisParams();
|
||||
params.dataFlowToThis = true;
|
||||
params.scope = new AnalysisScope(new LocalSearchScope(scope), argument.getProject());
|
||||
|
||||
SliceRootNode rootNode = new SliceRootNode(scope.getProject(), new DuplicateMap(), SliceManager.createRootUsage(argument, params));
|
||||
|
||||
Collection<? extends AbstractTreeNode> children = rootNode.getChildren().iterator().next().getChildren();
|
||||
for (AbstractTreeNode child : children) {
|
||||
SliceUsage usage = (SliceUsage)child.getValue();
|
||||
PsiElement element = usage.getElement();
|
||||
if (element instanceof PsiExpression && !processor.process((PsiExpression)element)) return false;
|
||||
}
|
||||
|
||||
|
||||
return !children.isEmpty();
|
||||
|
||||
//Set<PsiElement> elements = new THashSet<PsiElement>(DfaUtil.getPossibleInitializationElements(argument));
|
||||
//elements.remove(argument);
|
||||
//if (elements.isEmpty()) return processor.process(argument);
|
||||
//for (PsiElement element : elements) {
|
||||
// if (element != argument && !processor.process((PsiExpression)element)) return false;
|
||||
//}
|
||||
//return processor.process(argument);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -44,8 +44,8 @@ import java.util.regex.Pattern;
|
||||
)
|
||||
public class SliceManager implements PersistentStateComponent<SliceManager.StoredSettingsBean> {
|
||||
private final Project myProject;
|
||||
private final ContentManager myBackContentManager;
|
||||
private final ContentManager myForthContentManager;
|
||||
private ContentManager myBackContentManager;
|
||||
private ContentManager myForthContentManager;
|
||||
private volatile boolean myCanceled;
|
||||
private final StoredSettingsBean myStoredSettings = new StoredSettingsBean();
|
||||
private static final String BACK_TOOLWINDOW_ID = "Analyze Dataflow to";
|
||||
@@ -60,15 +60,8 @@ public class SliceManager implements PersistentStateComponent<SliceManager.Store
|
||||
return ServiceManager.getService(project, SliceManager.class);
|
||||
}
|
||||
|
||||
public SliceManager(@NotNull Project project, @NotNull ToolWindowManager toolWindowManager, final PsiManager psiManager) {
|
||||
public SliceManager(@NotNull Project project, PsiManager psiManager) {
|
||||
myProject = project;
|
||||
ToolWindow backToolWindow = toolWindowManager.registerToolWindow(BACK_TOOLWINDOW_ID, true, ToolWindowAnchor.BOTTOM, project);
|
||||
myBackContentManager = backToolWindow.getContentManager();
|
||||
new ContentManagerWatcher(backToolWindow, myBackContentManager);
|
||||
|
||||
ToolWindow forthToolWindow = toolWindowManager.registerToolWindow(FORTH_TOOLWINDOW_ID, true, ToolWindowAnchor.BOTTOM, project);
|
||||
myForthContentManager = forthToolWindow.getContentManager();
|
||||
new ContentManagerWatcher(forthToolWindow, myForthContentManager);
|
||||
|
||||
psiManager.addPsiTreeChangeListener(new PsiTreeChangeAdapter() {
|
||||
@Override
|
||||
@@ -103,6 +96,24 @@ public class SliceManager implements PersistentStateComponent<SliceManager.Store
|
||||
}, project);
|
||||
}
|
||||
|
||||
private ContentManager getContentManager(boolean dataFlowToThis) {
|
||||
if (dataFlowToThis) {
|
||||
if (myBackContentManager == null) {
|
||||
ToolWindow backToolWindow = ToolWindowManager.getInstance(myProject).registerToolWindow(BACK_TOOLWINDOW_ID, true, ToolWindowAnchor.BOTTOM, myProject);
|
||||
myBackContentManager = backToolWindow.getContentManager();
|
||||
new ContentManagerWatcher(backToolWindow, myBackContentManager);
|
||||
}
|
||||
return myBackContentManager;
|
||||
}
|
||||
|
||||
if (myForthContentManager == null) {
|
||||
ToolWindow forthToolWindow = ToolWindowManager.getInstance(myProject).registerToolWindow(FORTH_TOOLWINDOW_ID, true, ToolWindowAnchor.BOTTOM, myProject);
|
||||
myForthContentManager = forthToolWindow.getContentManager();
|
||||
new ContentManagerWatcher(forthToolWindow, myForthContentManager);
|
||||
}
|
||||
return myForthContentManager;
|
||||
}
|
||||
|
||||
private void cancel() {
|
||||
myCanceled = true;
|
||||
}
|
||||
@@ -121,7 +132,7 @@ public class SliceManager implements PersistentStateComponent<SliceManager.Store
|
||||
|
||||
public void createToolWindow(final boolean dataFlowToThis, final SliceRootNode rootNode, boolean splitByLeafExpressions, String displayName) {
|
||||
final SliceToolwindowSettings sliceToolwindowSettings = SliceToolwindowSettings.getInstance(myProject);
|
||||
final ContentManager contentManager = dataFlowToThis ? myBackContentManager : myForthContentManager;
|
||||
final ContentManager contentManager = getContentManager(dataFlowToThis);
|
||||
final Content[] myContent = new Content[1];
|
||||
ToolWindow toolWindow = ToolWindowManager.getInstance(myProject).getToolWindow(dataFlowToThis ? BACK_TOOLWINDOW_ID : FORTH_TOOLWINDOW_ID);
|
||||
final SlicePanel slicePanel = new SlicePanel(myProject, dataFlowToThis, rootNode, splitByLeafExpressions, toolWindow) {
|
||||
|
||||
@@ -57,7 +57,7 @@ public class TypeConversionUtil {
|
||||
public static final int SHORT_RANK = 2;
|
||||
public static final int CHAR_RANK = 3;
|
||||
public static final int INT_RANK = 4;
|
||||
private static final int LONG_RANK = 5;
|
||||
public static final int LONG_RANK = 5;
|
||||
private static final int FLOAT_RANK = 6;
|
||||
private static final int DOUBLE_RANK = 7;
|
||||
private static final int BOOL_RANK = 10;
|
||||
@@ -540,18 +540,16 @@ public class TypeConversionUtil {
|
||||
if (i == JavaTokenType.MINUSMINUS || i == JavaTokenType.PLUSPLUS) {
|
||||
return typeRank <= MAX_NUMERIC_RANK;
|
||||
}
|
||||
else if (i == JavaTokenType.MINUS || i == JavaTokenType.PLUS) {
|
||||
if (i == JavaTokenType.MINUS || i == JavaTokenType.PLUS) {
|
||||
return typeRank <= MAX_NUMERIC_RANK;
|
||||
}
|
||||
else if (i == JavaTokenType.TILDE) {
|
||||
if (i == JavaTokenType.TILDE) {
|
||||
return typeRank <= LONG_RANK;
|
||||
}
|
||||
else if (i == JavaTokenType.EXCL) {
|
||||
if (i == JavaTokenType.EXCL) {
|
||||
return typeRank == BOOL_RANK;
|
||||
}
|
||||
else {
|
||||
LOG.error("unknown token: " + token);
|
||||
}
|
||||
LOG.error("unknown token: " + token);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
435
java/java-tests/testData/inspection/magic/simple/expected.xml
Normal file
435
java/java-tests/testData/inspection/magic/simple/expected.xml
Normal file
@@ -0,0 +1,435 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<problems>
|
||||
<!--<problem>-->
|
||||
<!--<file>X.java</file>-->
|
||||
<!--<line>5</line>-->
|
||||
<!--<problem_class>Duplicate throws</problem_class>-->
|
||||
<!--<description>Duplicate throws</description>-->
|
||||
<!--</problem>-->
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>29</line>
|
||||
|
||||
|
||||
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y, Const.Z</description>
|
||||
</problem>
|
||||
|
||||
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>30</line>
|
||||
|
||||
|
||||
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y, Const.Z</description>
|
||||
</problem>
|
||||
|
||||
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>31</line>
|
||||
|
||||
|
||||
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y, Const.Z</description>
|
||||
</problem>
|
||||
|
||||
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>33</line>
|
||||
|
||||
|
||||
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y, Const.Z</description>
|
||||
</problem>
|
||||
|
||||
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>34</line>
|
||||
|
||||
|
||||
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y, Const.Z</description>
|
||||
</problem>
|
||||
|
||||
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>35</line>
|
||||
|
||||
|
||||
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y, Const.Z</description>
|
||||
</problem>
|
||||
|
||||
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>36</line>
|
||||
|
||||
|
||||
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y, Const.Z</description>
|
||||
</problem>
|
||||
|
||||
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>55</line>
|
||||
|
||||
|
||||
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y, Const.Z</description>
|
||||
</problem>
|
||||
|
||||
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>56</line>
|
||||
|
||||
|
||||
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y, Const.Z</description>
|
||||
</problem>
|
||||
|
||||
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>57</line>
|
||||
|
||||
|
||||
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y, Const.Z</description>
|
||||
</problem>
|
||||
|
||||
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>59</line>
|
||||
|
||||
|
||||
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y, Const.Z</description>
|
||||
</problem>
|
||||
|
||||
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>60</line>
|
||||
|
||||
|
||||
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y, Const.Z</description>
|
||||
</problem>
|
||||
|
||||
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>61</line>
|
||||
|
||||
|
||||
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y, Const.Z</description>
|
||||
</problem>
|
||||
|
||||
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>62</line>
|
||||
|
||||
|
||||
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y, Const.Z</description>
|
||||
</problem>
|
||||
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>81</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y, Const.Z</description>
|
||||
</problem>
|
||||
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>82</line>
|
||||
|
||||
|
||||
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y, Const.Z</description>
|
||||
</problem>
|
||||
|
||||
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>83</line>
|
||||
|
||||
|
||||
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y, Const.Z</description>
|
||||
</problem>
|
||||
|
||||
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>85</line>
|
||||
|
||||
|
||||
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y, Const.Z</description>
|
||||
</problem>
|
||||
|
||||
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>86</line>
|
||||
|
||||
|
||||
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y, Const.Z</description>
|
||||
</problem>
|
||||
|
||||
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>87</line>
|
||||
|
||||
|
||||
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y, Const.Z</description>
|
||||
</problem>
|
||||
|
||||
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>88</line>
|
||||
|
||||
|
||||
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y, Const.Z</description>
|
||||
</problem>
|
||||
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>118</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y, Const.Z</description>
|
||||
</problem>
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>119</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y, Const.Z</description>
|
||||
</problem>
|
||||
|
||||
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>122</line>
|
||||
|
||||
|
||||
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y, Const.Z</description>
|
||||
</problem>
|
||||
|
||||
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>123</line>
|
||||
|
||||
|
||||
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y, Const.Z</description>
|
||||
</problem>
|
||||
|
||||
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>124</line>
|
||||
|
||||
|
||||
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y, Const.Z</description>
|
||||
</problem>
|
||||
|
||||
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>125</line>
|
||||
|
||||
|
||||
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y, Const.Z</description>
|
||||
</problem>
|
||||
|
||||
|
||||
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>173</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y, Const.Z</description>
|
||||
</problem>
|
||||
|
||||
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>174</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y, Const.Z</description>
|
||||
</problem>
|
||||
|
||||
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>175</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y, Const.Z</description>
|
||||
</problem>
|
||||
|
||||
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>177</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y, Const.Z</description>
|
||||
</problem>
|
||||
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>178</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y, Const.Z</description>
|
||||
</problem>
|
||||
|
||||
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>179</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y, Const.Z</description>
|
||||
</problem>
|
||||
|
||||
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>180</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y, Const.Z</description>
|
||||
</problem>
|
||||
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>193</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y</description>
|
||||
</problem>
|
||||
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>195</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y</description>
|
||||
</problem>
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>227</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y</description>
|
||||
</problem>
|
||||
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>228</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y</description>
|
||||
</problem>
|
||||
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>229</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y</description>
|
||||
</problem>
|
||||
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>230</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y</description>
|
||||
</problem>
|
||||
|
||||
<problem>
|
||||
<file>X.java</file>
|
||||
<line>231</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">magic constant</problem_class>
|
||||
<description>Must be one of the: Const.X, Const.Y</description>
|
||||
</problem>
|
||||
|
||||
</problems>
|
||||
235
java/java-tests/testData/inspection/magic/simple/src/X.java
Normal file
235
java/java-tests/testData/inspection/magic/simple/src/X.java
Normal file
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* Copyright 2000-2011 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.
|
||||
*/
|
||||
import org.intellij.lang.annotations.MagicConstant;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
class Const {
|
||||
public static final int X = 0;
|
||||
public static final int Y = 2;
|
||||
public static final int Z = 3;
|
||||
}
|
||||
public class X {
|
||||
|
||||
void f(@MagicConstant(intValues={Const.X, Const.Y, Const.Z}) int x) {
|
||||
/////////// BAD
|
||||
f(0);
|
||||
f(1);
|
||||
f(Const.X | Const.Y);
|
||||
int i = Const.X | Const.Y;
|
||||
f(i);
|
||||
if (x == 3) {
|
||||
x = 2;
|
||||
assert x != 1;
|
||||
}
|
||||
|
||||
////////////// GOOD
|
||||
f(Const.X);
|
||||
f(Const.Y);
|
||||
f(Const.Z);
|
||||
int i2 = this == null ? Const.X : Const.Y;
|
||||
f(i2);
|
||||
if (x == Const.X) {
|
||||
x = Const.Y;
|
||||
assert x != Const.Z;
|
||||
}
|
||||
|
||||
f2(x);
|
||||
}
|
||||
|
||||
void f2(@MagicConstant(valuesFromClass =Const.class) int x) {
|
||||
/////////// BAD
|
||||
f2(0);
|
||||
f2(1);
|
||||
f2(Const.X | Const.Y);
|
||||
int i = Const.X | Const.Y;
|
||||
f2(i);
|
||||
if (x == 3) {
|
||||
x = 2;
|
||||
assert x != 1;
|
||||
}
|
||||
|
||||
////////////// GOOD
|
||||
f2(Const.X);
|
||||
f2(Const.Y);
|
||||
f2(Const.Z);
|
||||
int i2 = this == null ? Const.X : Const.Y;
|
||||
f2(i2);
|
||||
if (x == Const.X) {
|
||||
x = Const.Y;
|
||||
assert x != Const.Z;
|
||||
}
|
||||
|
||||
f(x);
|
||||
}
|
||||
|
||||
void f3(@MagicConstant(flags ={Const.X, Const.Y, Const.Z}) int x) {
|
||||
/////////// BAD
|
||||
f3(2);
|
||||
f3(1);
|
||||
f(Const.X | Const.Y);
|
||||
int i = Const.X | 4;
|
||||
f3(i);
|
||||
if (x == 3) {
|
||||
x = 2;
|
||||
assert x != 1;
|
||||
}
|
||||
|
||||
////////////// GOOD
|
||||
f3(Const.X);
|
||||
f3(Const.Y);
|
||||
f3(Const.Z);
|
||||
|
||||
int i2 = this == null ? Const.X : Const.Y;
|
||||
f3(i2);
|
||||
int ix = Const.X | Const.Y;
|
||||
f3(ix);
|
||||
f3(0);
|
||||
f3(-1);
|
||||
int f = 0;
|
||||
if (x == Const.X) {
|
||||
x = Const.Y;
|
||||
assert x != Const.Z;
|
||||
f |= Const.Y;
|
||||
}
|
||||
else {
|
||||
f |= Const.X;
|
||||
}
|
||||
f3(f);
|
||||
|
||||
f4(x);
|
||||
}
|
||||
|
||||
void f4(@MagicConstant(flagsFromClass =Const.class) int x) {
|
||||
/////////// BAD
|
||||
f4(-3);
|
||||
f4(1);
|
||||
f4(Const.X | Const.Y);
|
||||
int i = Const.X | 4;
|
||||
f4(i);
|
||||
if (x == 3) {
|
||||
x = 2;
|
||||
assert x != 1;
|
||||
}
|
||||
|
||||
////////////// GOOD
|
||||
f4(Const.X);
|
||||
f4(Const.Y);
|
||||
f4(Const.Z);
|
||||
|
||||
int i2 = this == null ? Const.X : Const.Y;
|
||||
f4(i2);
|
||||
int ix = Const.X | Const.Y;
|
||||
f4(ix);
|
||||
f4(0);
|
||||
f4(-1);
|
||||
int f = 0;
|
||||
if (x == Const.X) {
|
||||
x = Const.Y;
|
||||
assert x != Const.Z;
|
||||
f |= Const.Y;
|
||||
}
|
||||
else {
|
||||
f |= Const.X;
|
||||
}
|
||||
f4(f);
|
||||
|
||||
f3(x);
|
||||
}
|
||||
|
||||
|
||||
class Alias {
|
||||
@MagicConstant(intValues={Const.X, Const.Y, Const.Z})
|
||||
@interface IntEnum{}
|
||||
|
||||
void f(@IntEnum int x) {
|
||||
////////////// GOOD
|
||||
f(Const.X);
|
||||
f(Const.Y);
|
||||
f(Const.Z);
|
||||
int i2 = this == null ? Const.X : Const.Y;
|
||||
f(i2);
|
||||
if (x == Const.X) {
|
||||
x = Const.Y;
|
||||
assert x != Const.Z;
|
||||
}
|
||||
|
||||
f2(x);
|
||||
|
||||
/////////// BAD
|
||||
f(0);
|
||||
f(1);
|
||||
f(Const.X | Const.Y);
|
||||
int i = Const.X | Const.Y;
|
||||
f(i);
|
||||
if (x == 3 || getClass().isInterface()) {
|
||||
x = 2;
|
||||
assert x != 1;
|
||||
}
|
||||
|
||||
f2(x);
|
||||
}
|
||||
}
|
||||
|
||||
class MagicAnnoInsideAnnotationUsage {
|
||||
@interface III {
|
||||
@MagicConstant(intValues = {Const.X, Const.Y}) int val();
|
||||
}
|
||||
|
||||
// bad
|
||||
@III(val = 2)
|
||||
int h;
|
||||
@III(val = Const.X | Const.Y)
|
||||
void f(){}
|
||||
|
||||
// good
|
||||
@III(val = Const.X)
|
||||
int h2;
|
||||
}
|
||||
|
||||
abstract class BeanInfoParsing {
|
||||
/**
|
||||
* @see java.lang.Runtime#exit(int)
|
||||
*
|
||||
* @beaninfo
|
||||
* preferred: true
|
||||
* bound: true
|
||||
* enum: DO_NOTHING_ON_CLOSE Const.X
|
||||
* HIDE_ON_CLOSE Const.Y
|
||||
* description: The frame's default close operation.
|
||||
*/
|
||||
public void setX(int operation) {
|
||||
|
||||
}
|
||||
|
||||
public abstract int getX();
|
||||
|
||||
{
|
||||
// good
|
||||
setX(Const.X);
|
||||
setX(Const.Y);
|
||||
if (getX() == Const.X || getX() == Const.Y) {}
|
||||
|
||||
// bad
|
||||
setX(0);
|
||||
setX(-1);
|
||||
setX(Const.Z);
|
||||
if (getX() == 1) {}
|
||||
if (getX() == Const.Z) {}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2000-2011 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: max
|
||||
* Date: Apr 11, 2002
|
||||
* Time: 6:50:50 PM
|
||||
* To change template for new class use
|
||||
* Code Style | Class Templates options (Tools | IDE Options).
|
||||
*/
|
||||
package com.intellij.codeInspection;
|
||||
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.codeInspection.ex.LocalInspectionToolWrapper;
|
||||
import com.intellij.codeInspection.magicConstant.MagicConstantInspection;
|
||||
import com.intellij.testFramework.InspectionTestCase;
|
||||
|
||||
public class MagicConstantInspectionTest extends InspectionTestCase {
|
||||
@Override
|
||||
protected String getTestDataPath() {
|
||||
return JavaTestUtil.getJavaTestDataPath() + "/inspection";
|
||||
}
|
||||
|
||||
private void doTest() throws Exception {
|
||||
doTest("magic/" + getTestName(true), new LocalInspectionToolWrapper(new MagicConstantInspection()), "jdk 1.7");
|
||||
}
|
||||
|
||||
public void testSimple() throws Exception { doTest(); }
|
||||
|
||||
|
||||
|
||||
//{
|
||||
// SecurityManager securityManager = System.getSecurityManager();
|
||||
// securityManager.checkMemberAccess(getClass(), 948);
|
||||
//
|
||||
// Font font = null;
|
||||
// new Cursor() ;
|
||||
// JOptionPane.showConfirmDialog(null, null, null, 0, );
|
||||
// JList l = null;
|
||||
// l.getSelectionModel().setSelectionMode();
|
||||
// new JSplitPane(9);
|
||||
// MouseWheelEvent event = new MouseWheelEvent(null,0,0,0,0,0,0,false,0,0,0 );
|
||||
// Pattern p = Pattern.compile("", Pattern.CANON_EQ);
|
||||
// JTree t = null; t.getSelectionModel().setSelectionMode();
|
||||
//
|
||||
// TitledBorder border = new TitledBorder(null,"",0,0);
|
||||
// new JLabel("text", )
|
||||
// Calendar calendar = Calendar.getInstance();
|
||||
// new Font("Arial", )
|
||||
//}
|
||||
|
||||
//public static Font createFont() {
|
||||
// return new Font("Arial", );
|
||||
//}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
Binary file not shown.
@@ -87,7 +87,7 @@ public class AnnotationUtil {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiAnnotation findAnnotation(PsiModifierListOwner listOwner, @NotNull Set<String> annotationNames) {
|
||||
public static PsiAnnotation findAnnotation(@Nullable PsiModifierListOwner listOwner, @NotNull Set<String> annotationNames) {
|
||||
return findAnnotation(listOwner, (Collection<String>)annotationNames);
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ public class AnnotationUtil {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiAnnotation findAnnotation(@Nullable PsiModifierListOwner listOwner, Collection<String> annotationNames,
|
||||
public static PsiAnnotation findAnnotation(@Nullable PsiModifierListOwner listOwner, @NotNull Collection<String> annotationNames,
|
||||
final boolean skipExternal) {
|
||||
if (listOwner == null) return null;
|
||||
final PsiModifierList list = listOwner.getModifierList();
|
||||
@@ -138,7 +138,7 @@ public class AnnotationUtil {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiAnnotation findAnnotationInHierarchy(PsiModifierListOwner listOwner, Set<String> annotationNames) {
|
||||
public static PsiAnnotation findAnnotationInHierarchy(PsiModifierListOwner listOwner, @NotNull Set<String> annotationNames) {
|
||||
PsiAnnotation directAnnotation = findAnnotation(listOwner, annotationNames);
|
||||
if (directAnnotation != null) return directAnnotation;
|
||||
if (listOwner instanceof PsiMethod) {
|
||||
@@ -146,15 +146,17 @@ public class AnnotationUtil {
|
||||
PsiClass aClass = method.getContainingClass();
|
||||
if (aClass == null) return null;
|
||||
HierarchicalMethodSignature methodSignature = method.getHierarchicalMethodSignature();
|
||||
return findAnnotationInHierarchy(methodSignature, annotationNames, method, null);
|
||||
} else if (listOwner instanceof PsiClass) {
|
||||
return findAnnotationInHierarchy(((PsiClass)listOwner), annotationNames, null);
|
||||
return findAnnotationInHierarchy(methodSignature, annotationNames, method, null,
|
||||
JavaPsiFacade.getInstance(method.getProject()).getResolveHelper());
|
||||
}
|
||||
if (listOwner instanceof PsiClass) {
|
||||
return findAnnotationInHierarchy((PsiClass)listOwner, annotationNames, null);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiAnnotation findAnnotationInHierarchy(final @NotNull PsiClass psiClass, final Set<String> annotationNames, @Nullable Set<PsiClass> processed) {
|
||||
private static PsiAnnotation findAnnotationInHierarchy(@NotNull final PsiClass psiClass, final Set<String> annotationNames, @Nullable Set<PsiClass> processed) {
|
||||
final PsiClass[] superClasses = psiClass.getSupers();
|
||||
for (final PsiClass superClass : superClasses) {
|
||||
if (processed == null) processed = new THashSet<PsiClass>();
|
||||
@@ -168,12 +170,12 @@ public class AnnotationUtil {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiAnnotation findAnnotationInHierarchy(HierarchicalMethodSignature signature,
|
||||
Set<String> annotationNames,
|
||||
PsiElement place,
|
||||
@Nullable Set<PsiMethod> processed) {
|
||||
private static PsiAnnotation findAnnotationInHierarchy(@NotNull HierarchicalMethodSignature signature,
|
||||
@NotNull Set<String> annotationNames,
|
||||
@NotNull PsiElement place,
|
||||
@Nullable Set<PsiMethod> processed,
|
||||
@NotNull PsiResolveHelper resolveHelper) {
|
||||
final List<HierarchicalMethodSignature> superSignatures = signature.getSuperSignatures();
|
||||
final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(place.getProject()).getResolveHelper();
|
||||
for (final HierarchicalMethodSignature superSignature : superSignatures) {
|
||||
final PsiMethod superMethod = superSignature.getMethod();
|
||||
if (processed == null) processed = new THashSet<PsiMethod>();
|
||||
@@ -181,7 +183,7 @@ public class AnnotationUtil {
|
||||
if (!resolveHelper.isAccessible(superMethod, place, null)) continue;
|
||||
PsiAnnotation direct = findAnnotation(superMethod, annotationNames);
|
||||
if (direct != null) return direct;
|
||||
PsiAnnotation superResult = findAnnotationInHierarchy(superSignature, annotationNames, place, processed);
|
||||
PsiAnnotation superResult = findAnnotationInHierarchy(superSignature, annotationNames, place, processed, resolveHelper);
|
||||
if (superResult != null) return superResult;
|
||||
}
|
||||
|
||||
@@ -261,10 +263,10 @@ public class AnnotationUtil {
|
||||
* @return <code>true</code> if annotated of at least one annotation from the annotations list
|
||||
*/
|
||||
public static boolean checkAnnotatedUsingPatterns(PsiModifierListOwner owner, Collection<String> annotations) {
|
||||
List<String> fqns = null;
|
||||
final PsiModifierList modList;
|
||||
if (owner == null || (modList = owner.getModifierList()) == null) return false;
|
||||
|
||||
List<String> fqns = null;
|
||||
for (String fqn : annotations) {
|
||||
boolean isPattern = fqn.endsWith("*");
|
||||
if (!isPattern && isAnnotated(owner, fqn, false)) {
|
||||
@@ -307,4 +309,71 @@ public class AnnotationUtil {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PsiAnnotation[] getAllAnnotations(@NotNull PsiModifierListOwner owner, boolean inHierarchy, Set<PsiModifierListOwner> visited) {
|
||||
final PsiModifierList list = owner.getModifierList();
|
||||
PsiAnnotation[] annotations = PsiAnnotation.EMPTY_ARRAY;
|
||||
if (list != null) {
|
||||
annotations = list.getAnnotations();
|
||||
}
|
||||
|
||||
final PsiAnnotation[] externalAnnotations = ExternalAnnotationsManager.getInstance(owner.getProject()).findExternalAnnotations(owner);
|
||||
if (externalAnnotations != null) {
|
||||
annotations = ArrayUtil.mergeArrays(annotations, externalAnnotations, PsiAnnotation.ARRAY_FACTORY);
|
||||
}
|
||||
|
||||
if (inHierarchy) {
|
||||
if (owner instanceof PsiClass) {
|
||||
for (PsiClass superClass : ((PsiClass)owner).getSupers()) {
|
||||
if (visited == null) visited = new THashSet<PsiModifierListOwner>();
|
||||
if (visited.add(superClass)) annotations = ArrayUtil.mergeArrays(annotations, getAllAnnotations(superClass, inHierarchy, visited));
|
||||
}
|
||||
}
|
||||
else if (owner instanceof PsiMethod) {
|
||||
PsiMethod method = (PsiMethod)owner;
|
||||
PsiClass aClass = method.getContainingClass();
|
||||
if (aClass != null) {
|
||||
HierarchicalMethodSignature methodSignature = method.getHierarchicalMethodSignature();
|
||||
|
||||
final List<HierarchicalMethodSignature> superSignatures = methodSignature.getSuperSignatures();
|
||||
PsiResolveHelper resolveHelper = PsiResolveHelper.SERVICE.getInstance(aClass.getProject());
|
||||
for (final HierarchicalMethodSignature superSignature : superSignatures) {
|
||||
final PsiMethod superMethod = superSignature.getMethod();
|
||||
if (visited == null) visited = new THashSet<PsiModifierListOwner>();
|
||||
if (!visited.add(superMethod)) continue;
|
||||
if (!resolveHelper.isAccessible(superMethod, owner, null)) continue;
|
||||
annotations = ArrayUtil.mergeArrays(annotations, getAllAnnotations(superMethod, inHierarchy, visited));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (owner instanceof PsiParameter) {
|
||||
PsiParameter parameter = (PsiParameter)owner;
|
||||
PsiElement scope = parameter.getDeclarationScope();
|
||||
if (scope instanceof PsiMethod) {
|
||||
PsiMethod method = (PsiMethod)scope;
|
||||
PsiClass aClass = method.getContainingClass();
|
||||
PsiElement parent = parameter.getParent();
|
||||
if (aClass != null && parent instanceof PsiParameterList) {
|
||||
int index = ((PsiParameterList)parent).getParameterIndex(parameter);
|
||||
HierarchicalMethodSignature methodSignature = method.getHierarchicalMethodSignature();
|
||||
|
||||
final List<HierarchicalMethodSignature> superSignatures = methodSignature.getSuperSignatures();
|
||||
PsiResolveHelper resolveHelper = PsiResolveHelper.SERVICE.getInstance(aClass.getProject());
|
||||
for (final HierarchicalMethodSignature superSignature : superSignatures) {
|
||||
final PsiMethod superMethod = superSignature.getMethod();
|
||||
if (visited == null) visited = new THashSet<PsiModifierListOwner>();
|
||||
if (!visited.add(superMethod)) continue;
|
||||
if (!resolveHelper.isAccessible(superMethod, owner, null)) continue;
|
||||
PsiParameter[] superParameters = superMethod.getParameterList().getParameters();
|
||||
if (index < superParameters.length) {
|
||||
annotations = ArrayUtil.mergeArrays(annotations, getAllAnnotations(superParameters[index], inHierarchy, visited));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return annotations;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,18 +17,24 @@ package com.intellij.psi.util;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import org.intellij.lang.annotations.MagicConstant;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class PsiFormatUtil extends PsiFormatUtilBase {
|
||||
@MagicConstant(flags = {SHOW_MODIFIERS, SHOW_TYPE, TYPE_AFTER, SHOW_CONTAINING_CLASS, SHOW_FQ_NAME, SHOW_NAME, SHOW_MODIFIERS, SHOW_INITIALIZER, SHOW_RAW_TYPE, SHOW_RAW_NON_TOP_TYPE, SHOW_FQ_CLASS_NAMES})
|
||||
public @interface FormatVariableOptions {}
|
||||
|
||||
public static String formatVariable(PsiVariable variable, int options, PsiSubstitutor substitutor){
|
||||
public static String formatVariable(PsiVariable variable, @FormatVariableOptions int options, PsiSubstitutor substitutor){
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
formatVariable(variable, options, substitutor,buffer);
|
||||
return buffer.toString();
|
||||
}
|
||||
private static void formatVariable(PsiVariable variable, int options, PsiSubstitutor substitutor,StringBuilder buffer){
|
||||
private static void formatVariable(PsiVariable variable,
|
||||
@FormatVariableOptions int options,
|
||||
PsiSubstitutor substitutor,
|
||||
@NotNull StringBuilder buffer){
|
||||
if ((options & SHOW_MODIFIERS) != 0 && (options & MODIFIERS_AFTER) == 0){
|
||||
formatModifiers(variable, options,buffer);
|
||||
}
|
||||
@@ -97,16 +103,20 @@ public class PsiFormatUtil extends PsiFormatUtilBase {
|
||||
}
|
||||
}
|
||||
|
||||
public static String formatMethod(PsiMethod method, PsiSubstitutor substitutor, int options, int parameterOptions){
|
||||
public static String formatMethod(PsiMethod method, PsiSubstitutor substitutor, @FormatMethodOptions int options, @FormatVariableOptions int parameterOptions){
|
||||
return formatMethod(method, substitutor, options, parameterOptions, MAX_PARAMS_TO_SHOW);
|
||||
}
|
||||
|
||||
public static String formatMethod(PsiMethod method, PsiSubstitutor substitutor, int options, int parameterOptions, int maxParametersToShow){
|
||||
public static String formatMethod(PsiMethod method, PsiSubstitutor substitutor, @FormatMethodOptions int options, @FormatVariableOptions int parameterOptions, int maxParametersToShow){
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
formatMethod(method, substitutor, options, parameterOptions, maxParametersToShow,buffer);
|
||||
return buffer.toString();
|
||||
}
|
||||
private static void formatMethod(PsiMethod method, PsiSubstitutor substitutor, int options, int parameterOptions, int maxParametersToShow, StringBuilder buffer){
|
||||
|
||||
@MagicConstant(flags = {SHOW_MODIFIERS, MODIFIERS_AFTER, SHOW_TYPE, TYPE_AFTER, SHOW_CONTAINING_CLASS, SHOW_FQ_NAME, SHOW_NAME, SHOW_PARAMETERS, SHOW_THROWS, SHOW_RAW_TYPE, SHOW_RAW_NON_TOP_TYPE, SHOW_FQ_CLASS_NAMES})
|
||||
public @interface FormatMethodOptions {}
|
||||
|
||||
private static void formatMethod(PsiMethod method, PsiSubstitutor substitutor, @FormatMethodOptions int options, @FormatVariableOptions int parameterOptions, int maxParametersToShow, StringBuilder buffer){
|
||||
if ((options & SHOW_MODIFIERS) != 0 && (options & MODIFIERS_AFTER) == 0){
|
||||
formatModifiers(method, options,buffer);
|
||||
}
|
||||
@@ -177,7 +187,7 @@ public class PsiFormatUtil extends PsiFormatUtilBase {
|
||||
}
|
||||
if ((options & SHOW_THROWS) != 0){
|
||||
String throwsText = formatReferenceList(method.getThrowsList(), options);
|
||||
if (throwsText.length() > 0){
|
||||
if (!throwsText.isEmpty()){
|
||||
appendSpaceIfNeeded(buffer);
|
||||
//noinspection HardCodedStringLiteral
|
||||
buffer.append("throws ");
|
||||
@@ -186,7 +196,12 @@ public class PsiFormatUtil extends PsiFormatUtilBase {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull public static String formatClass(@NotNull PsiClass aClass, int options){
|
||||
|
||||
@MagicConstant(flags = {SHOW_MODIFIERS, SHOW_NAME, SHOW_ANONYMOUS_CLASS_VERBOSE, SHOW_FQ_NAME, MODIFIERS_AFTER, SHOW_EXTENDS_IMPLEMENTS, SHOW_REDUNDANT_MODIFIERS, JAVADOC_MODIFIERS_ONLY})
|
||||
public @interface FormatClassOptions {}
|
||||
|
||||
@NotNull
|
||||
public static String formatClass(@NotNull PsiClass aClass, @FormatClassOptions int options){
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
if ((options & SHOW_MODIFIERS) != 0 && (options & MODIFIERS_AFTER) == 0){
|
||||
formatModifiers(aClass, options,buffer);
|
||||
@@ -222,14 +237,14 @@ public class PsiFormatUtil extends PsiFormatUtilBase {
|
||||
}
|
||||
if ((options & SHOW_EXTENDS_IMPLEMENTS) != 0){
|
||||
String extendsText = formatReferenceList(aClass.getExtendsList(), options);
|
||||
if (extendsText.length() > 0){
|
||||
if (!extendsText.isEmpty()){
|
||||
appendSpaceIfNeeded(buffer);
|
||||
//noinspection HardCodedStringLiteral
|
||||
buffer.append("extends ");
|
||||
buffer.append(extendsText);
|
||||
}
|
||||
String implementsText = formatReferenceList(aClass.getImplementsList(), options);
|
||||
if (implementsText.length() > 0){
|
||||
if (!implementsText.isEmpty()){
|
||||
appendSpaceIfNeeded(buffer);
|
||||
//noinspection HardCodedStringLiteral
|
||||
buffer.append("implements ");
|
||||
@@ -340,7 +355,7 @@ public class PsiFormatUtil extends PsiFormatUtilBase {
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public static String formatType(PsiType type, int options, PsiSubstitutor substitutor){
|
||||
public static String formatType(PsiType type, int options, @NotNull PsiSubstitutor substitutor){
|
||||
type = substitutor.substitute(type);
|
||||
if ((options & SHOW_RAW_TYPE) != 0) {
|
||||
type = TypeConversionUtil.erasure(type);
|
||||
@@ -367,6 +382,11 @@ public class PsiFormatUtil extends PsiFormatUtilBase {
|
||||
|
||||
@Nullable
|
||||
public static String getExternalName(PsiModifierListOwner owner, final boolean showParamName) {
|
||||
return getExternalName(owner, showParamName, MAX_PARAMS_TO_SHOW);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getExternalName(PsiModifierListOwner owner, final boolean showParamName, int maxParamsToShow) {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
if (owner instanceof PsiClass) {
|
||||
ClassUtil.formatClassName((PsiClass)owner, builder);
|
||||
@@ -379,7 +399,7 @@ public class PsiFormatUtil extends PsiFormatUtilBase {
|
||||
builder.append(" ");
|
||||
formatMethod((PsiMethod)owner, PsiSubstitutor.EMPTY,
|
||||
SHOW_NAME | SHOW_FQ_NAME | SHOW_TYPE | SHOW_PARAMETERS | SHOW_FQ_CLASS_NAMES,
|
||||
showParamName ? SHOW_NAME | SHOW_TYPE | SHOW_FQ_CLASS_NAMES : SHOW_TYPE | SHOW_FQ_CLASS_NAMES, MAX_PARAMS_TO_SHOW, builder);
|
||||
showParamName ? SHOW_NAME | SHOW_TYPE | SHOW_FQ_CLASS_NAMES : SHOW_TYPE | SHOW_FQ_CLASS_NAMES, maxParamsToShow, builder);
|
||||
}
|
||||
else if (owner instanceof PsiField) {
|
||||
builder.append(" ").append(((PsiField)owner).getName());
|
||||
@@ -392,7 +412,7 @@ public class PsiFormatUtil extends PsiFormatUtilBase {
|
||||
builder.append(" ");
|
||||
formatMethod(psiMethod, PsiSubstitutor.EMPTY,
|
||||
SHOW_NAME | SHOW_FQ_NAME | SHOW_TYPE | SHOW_PARAMETERS | SHOW_FQ_CLASS_NAMES,
|
||||
showParamName ? SHOW_NAME | SHOW_TYPE | SHOW_FQ_CLASS_NAMES : SHOW_TYPE | SHOW_FQ_CLASS_NAMES, MAX_PARAMS_TO_SHOW, builder);
|
||||
showParamName ? SHOW_NAME | SHOW_TYPE | SHOW_FQ_CLASS_NAMES : SHOW_TYPE | SHOW_FQ_CLASS_NAMES, maxParamsToShow, builder);
|
||||
builder.append(" ");
|
||||
|
||||
if (showParamName) {
|
||||
@@ -415,7 +435,7 @@ public class PsiFormatUtil extends PsiFormatUtilBase {
|
||||
public static String getPackageDisplayName(@NotNull final PsiClass psiClass) {
|
||||
@NonNls String packageName = psiClass.getQualifiedName();
|
||||
packageName = packageName == null || packageName.lastIndexOf('.') <= 0 ? "" : packageName.substring(0, packageName.lastIndexOf('.'));
|
||||
if (packageName.length() == 0) {
|
||||
if (packageName.isEmpty()) {
|
||||
packageName = "default package";
|
||||
}
|
||||
return packageName;
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.intellij.lang.annotations;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE,
|
||||
ElementType.ANNOTATION_TYPE, // to subclass
|
||||
ElementType.METHOD
|
||||
})
|
||||
public @interface MagicConstant {
|
||||
Class valuesFromClass() default void.class;
|
||||
Class flagsFromClass() default void.class; // int constants which can be combined via | (bitwise or) operator. 0 and -1 are considered acceptable values.
|
||||
String[] stringValues() default {};
|
||||
long[] intValues() default {};
|
||||
long[] flags() default {}; // int constants which can be combined via | (bitwise or) operator. 0 and -1 are considered acceptable values.
|
||||
}
|
||||
@@ -443,6 +443,7 @@
|
||||
<completion.skip implementation="com.intellij.codeInsight.template.impl.LiveTemplateCompletionContributor$Skipper" id="skipLiveTemplate"/>
|
||||
|
||||
<completion.contributor language="TEXT" implementationClass="com.intellij.openapi.vcs.CommitCompletionContributor" id="commitCompletion" order="first, before liveTemplates"/>
|
||||
<completion.contributor language="JAVA" implementationClass="com.intellij.codeInspection.magicConstant.MagicCompletionContributor" id="magicCompletion" order="first, before liveTemplates"/>
|
||||
|
||||
<applicationService serviceInterface="com.intellij.execution.console.ConsoleFoldingSettings" serviceImplementation="com.intellij.execution.console.ConsoleFoldingSettings"/>
|
||||
<console.folding implementation="com.intellij.execution.console.SubstringConsoleFolding"/>
|
||||
|
||||
13
resources-en/src/inspectionDescriptions/MagicConstant.html
Normal file
13
resources-en/src/inspectionDescriptions/MagicConstant.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<html>
|
||||
<body>
|
||||
<font face="verdana" size="-1">Report occurrences where usages of "magic" constants only are allowed
|
||||
but other expressions are used instead.<br>
|
||||
E.g. <b><font color="#000080">new </font></b> Font("Arial", <b><font color="#000080">42</font></b>) <br>
|
||||
instead of <b><font color="#000080">new </font></b> Font("Arial", Font.<b><font color="#000080">BOLD</font></b>) <br>
|
||||
|
||||
<br><br>
|
||||
|
||||
Please see <code>org.intellij.lang.annotations.MagicConstant</code> annotation description for details.
|
||||
</font>
|
||||
</body>
|
||||
</html>
|
||||
@@ -515,6 +515,9 @@
|
||||
<localInspection language="JAVA" shortName="JavacQuirks" bundle="messages.InspectionsBundle" key="inspection.compiler.javac.quirks.name"
|
||||
groupName="Compiler issues" enabledByDefault="true" level="WARNING"
|
||||
implementationClass="com.intellij.codeInspection.compiler.JavacQuirksInspection" />
|
||||
<localInspection language="JAVA" shortName="MagicConstant" displayName="Magic Constant"
|
||||
groupName="Probable bugs" enabledByDefault="true" level="WARNING"
|
||||
implementationClass="com.intellij.codeInspection.magicConstant.MagicConstantInspection" />
|
||||
|
||||
<intentionAction>
|
||||
<className>com.intellij.codeInsight.intention.impl.SplitIfAction</className>
|
||||
|
||||
Reference in New Issue
Block a user