mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-22 06:21:25 +07:00
Annotation applicability highlighting reworked
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,8 +22,8 @@ import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.patterns.ElementPattern;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.filters.getters.MembersGetter;
|
||||
import com.intellij.psi.impl.PsiImplUtil;
|
||||
import com.intellij.psi.impl.source.tree.JavaElementType;
|
||||
import com.intellij.psi.impl.source.tree.java.PsiAnnotationImpl;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PropertyUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
@@ -92,27 +92,15 @@ public class PreferByKindWeigher extends LookupElementWeigher {
|
||||
if (psiElement().withParents(PsiJavaCodeReferenceElement.class, PsiAnnotation.class).accepts(position)) {
|
||||
final PsiAnnotation annotation = PsiTreeUtil.getParentOfType(position, PsiAnnotation.class);
|
||||
assert annotation != null;
|
||||
PsiAnnotationOwner owner = annotation.getOwner();
|
||||
if (owner instanceof PsiModifierList || owner instanceof PsiTypeElement || owner instanceof PsiTypeParameter) {
|
||||
PsiElement member = (PsiElement)owner;
|
||||
if (member instanceof PsiModifierList) {
|
||||
member = member.getParent();
|
||||
final PsiAnnotation.TargetType[] targets = PsiImplUtil.getApplicableTargets(annotation.getOwner());
|
||||
return new Condition<PsiClass>() {
|
||||
@Override
|
||||
public boolean value(PsiClass psiClass) {
|
||||
return psiClass.isAnnotationType() && PsiImplUtil.isAnnotationApplicable(psiClass, false, targets);
|
||||
}
|
||||
if (member instanceof PsiTypeElement && member.getParent() instanceof PsiMethod) {
|
||||
member = member.getParent();
|
||||
}
|
||||
final String[] elementTypeFields = PsiAnnotationImpl.getApplicableElementTypeFields(member);
|
||||
return new Condition<PsiClass>() {
|
||||
@Override
|
||||
public boolean value(PsiClass psiClass) {
|
||||
if (!psiClass.isAnnotationType()) {
|
||||
return false;
|
||||
}
|
||||
return PsiAnnotationImpl.isAnnotationApplicable(false, psiClass, elementTypeFields, position.getResolveScope());
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//noinspection unchecked
|
||||
return Condition.FALSE;
|
||||
}
|
||||
@@ -179,7 +167,7 @@ public class PreferByKindWeigher extends LookupElementWeigher {
|
||||
return MyResult.qualifiedWithGetter;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return MyResult.normal;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* Copyright 2000-2013 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.
|
||||
@@ -27,14 +27,13 @@ import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.patterns.ElementPattern;
|
||||
import com.intellij.patterns.PatternCondition;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.tree.java.PsiAnnotationImpl;
|
||||
import com.intellij.psi.impl.PsiImplUtil;
|
||||
import com.intellij.psi.impl.source.PsiClassReferenceType;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -161,17 +160,14 @@ public class AnnotationsHighlightUtil {
|
||||
@Nullable
|
||||
public static HighlightInfo checkDuplicateAnnotations(PsiAnnotation annotationToCheck) {
|
||||
PsiAnnotationOwner owner = annotationToCheck.getOwner();
|
||||
if (owner == null) {
|
||||
return null;
|
||||
}
|
||||
if (owner == null) return null;
|
||||
|
||||
PsiJavaCodeReferenceElement element = annotationToCheck.getNameReferenceElement();
|
||||
if (element == null) return null;
|
||||
PsiElement resolved = element.resolve();
|
||||
if (!(resolved instanceof PsiClass)) return null;
|
||||
|
||||
PsiAnnotation[] annotations = owner.getApplicableAnnotations();
|
||||
for (PsiAnnotation annotation : annotations) {
|
||||
for (PsiAnnotation annotation : owner.getAnnotations()) {
|
||||
if (annotation == annotationToCheck) continue;
|
||||
PsiJavaCodeReferenceElement nameRef = annotation.getNameReferenceElement();
|
||||
if (nameRef == null) continue;
|
||||
@@ -254,50 +250,117 @@ public class AnnotationsHighlightUtil {
|
||||
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(typeElement).descriptionAndTooltip(description).create();
|
||||
}
|
||||
|
||||
private static final ElementPattern<PsiElement> ANNOTATION_ALLOWED = psiElement().andOr(
|
||||
psiElement().with(new PatternCondition<PsiElement>("annotationOwner") {
|
||||
@Override
|
||||
public boolean accepts(@NotNull PsiElement element, ProcessingContext context) {
|
||||
return element instanceof PsiAnnotationOwner;
|
||||
}
|
||||
}),
|
||||
private static final ElementPattern<PsiElement> ANY_ANNOTATION_ALLOWED = psiElement().andOr(
|
||||
psiElement().withParent(PsiNameValuePair.class),
|
||||
psiElement().withParents(PsiArrayInitializerMemberValue.class, PsiNameValuePair.class),
|
||||
psiElement().withParent(PsiAnnotationMethod.class).afterLeaf(PsiKeyword.DEFAULT)
|
||||
);
|
||||
|
||||
@Nullable
|
||||
public static HighlightInfo checkApplicability(final PsiAnnotation annotation) {
|
||||
PsiAnnotationOwner owner = annotation.getOwner();
|
||||
if (owner instanceof PsiModifierList || owner instanceof PsiTypeElement || owner instanceof PsiTypeParameter) {
|
||||
PsiJavaCodeReferenceElement nameRef = annotation.getNameReferenceElement();
|
||||
if (nameRef == null) {
|
||||
return null;
|
||||
}
|
||||
PsiElement member = owner instanceof PsiModifierList ? ((PsiElement)owner).getParent() : (PsiElement)owner;
|
||||
String[] elementTypeFields = PsiAnnotationImpl.getApplicableElementTypeFields(member);
|
||||
if (elementTypeFields == null || PsiAnnotationImpl.isAnnotationApplicableTo(annotation, false, elementTypeFields)) {
|
||||
return null;
|
||||
}
|
||||
String target = JavaErrorMessages.message("annotation.target." + elementTypeFields[0]);
|
||||
String description = JavaErrorMessages.message("annotation.not.applicable", nameRef.getText(), target);
|
||||
HighlightInfo highlightInfo =
|
||||
HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(nameRef).descriptionAndTooltip(description).create();
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, new DeleteNotApplicableAnnotationAction(annotation));
|
||||
return highlightInfo;
|
||||
public static HighlightInfo checkApplicability(@NotNull PsiAnnotation annotation) {
|
||||
if (ANY_ANNOTATION_ALLOWED.accepts(annotation)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!ANNOTATION_ALLOWED.accepts(annotation)) {
|
||||
PsiJavaCodeReferenceElement nameRef = annotation.getNameReferenceElement();
|
||||
if (nameRef == null) return null;
|
||||
PsiElement annotationType = nameRef.resolve();
|
||||
if (!(annotationType instanceof PsiClass)) return null;
|
||||
|
||||
PsiAnnotationOwner owner = annotation.getOwner();
|
||||
PsiAnnotation.TargetType[] targets = PsiImplUtil.getApplicableTargets(owner);
|
||||
if (owner == null || targets == null) {
|
||||
String message = JavaErrorMessages.message("annotation.not.allowed.here");
|
||||
HighlightInfo highlightInfo =
|
||||
HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(annotation).descriptionAndTooltip(message).create();
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, new DeleteNotApplicableAnnotationAction(annotation));
|
||||
return highlightInfo;
|
||||
return annotationError(annotation, message);
|
||||
}
|
||||
|
||||
if (!(owner instanceof PsiModifierList)) {
|
||||
HighlightInfo info = HighlightUtil.checkTypeAnnotationFeature(annotation);
|
||||
if (info != null) return info;
|
||||
}
|
||||
|
||||
PsiAnnotation.TargetType applicable = PsiImplUtil.findApplicableTarget((PsiClass)annotationType, targets);
|
||||
if (applicable == null) {
|
||||
String target = JavaErrorMessages.message("annotation.target." + targets[0]);
|
||||
String message = JavaErrorMessages.message("annotation.not.applicable", nameRef.getText(), target);
|
||||
return annotationError(annotation, message);
|
||||
}
|
||||
|
||||
if (applicable == PsiAnnotation.TargetType.TYPE_USE) {
|
||||
if (owner instanceof PsiClassReferenceType) {
|
||||
PsiJavaCodeReferenceElement ref = ((PsiClassReferenceType)owner).getReference();
|
||||
HighlightInfo info = checkReferenceTarget(annotation, ref);
|
||||
if (info != null) return info;
|
||||
}
|
||||
else if (owner instanceof PsiModifierList) {
|
||||
PsiElement nextElement = PsiTreeUtil.skipSiblingsForward((PsiModifierList)owner,
|
||||
PsiComment.class, PsiWhiteSpace.class, PsiTypeParameterList.class);
|
||||
if (nextElement instanceof PsiTypeElement) {
|
||||
PsiTypeElement typeElement = (PsiTypeElement)nextElement;
|
||||
PsiType type = typeElement.getType();
|
||||
if (PsiType.VOID.equals(type)) {
|
||||
String message = JavaErrorMessages.message("annotation.not.allowed.void");
|
||||
return annotationError(annotation, message);
|
||||
}
|
||||
if (!(type instanceof PsiPrimitiveType)) {
|
||||
PsiJavaCodeReferenceElement ref = getOutermostReferenceElement(typeElement.getInnermostComponentReferenceElement());
|
||||
HighlightInfo info = checkReferenceTarget(annotation, ref);
|
||||
if (info != null) return info;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (owner instanceof PsiTypeElement) {
|
||||
PsiElement context = PsiTreeUtil.skipParentsOfType((PsiTypeElement)owner, PsiTypeElement.class);
|
||||
if (context instanceof PsiClassObjectAccessExpression) {
|
||||
String message = JavaErrorMessages.message("annotation.not.allowed.class");
|
||||
return annotationError(annotation, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static HighlightInfo annotationError(PsiAnnotation annotation, String message) {
|
||||
HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(annotation).descriptionAndTooltip(message).create();
|
||||
QuickFixAction.registerQuickFixAction(info, new DeleteAnnotationAction(annotation));
|
||||
return info;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static HighlightInfo checkReferenceTarget(PsiAnnotation annotation, @Nullable PsiJavaCodeReferenceElement ref) {
|
||||
if (ref == null) return null;
|
||||
PsiElement refTarget = ref.resolve();
|
||||
if (refTarget == null) return null;
|
||||
|
||||
String message = null;
|
||||
if (!(refTarget instanceof PsiClass)) {
|
||||
message = JavaErrorMessages.message("annotation.not.allowed.ref");
|
||||
}
|
||||
else {
|
||||
PsiElement parent = ref.getParent();
|
||||
if (parent instanceof PsiJavaCodeReferenceElement) {
|
||||
PsiElement qualified = ((PsiJavaCodeReferenceElement)parent).resolve();
|
||||
if (qualified instanceof PsiMember && ((PsiMember)qualified).hasModifierProperty(PsiModifier.STATIC)) {
|
||||
message = JavaErrorMessages.message("annotation.not.allowed.static");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return message != null ? annotationError(annotation, message) : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiJavaCodeReferenceElement getOutermostReferenceElement(@Nullable PsiJavaCodeReferenceElement ref) {
|
||||
if (ref == null) return null;
|
||||
|
||||
PsiElement qualifier;
|
||||
while ((qualifier = ref.getQualifier()) instanceof PsiJavaCodeReferenceElement) {
|
||||
ref = (PsiJavaCodeReferenceElement)qualifier;
|
||||
}
|
||||
return ref;
|
||||
}
|
||||
|
||||
public static HighlightInfo checkForeignInnerClassesUsed(final PsiAnnotation annotation) {
|
||||
final HighlightInfo[] infos = new HighlightInfo[1];
|
||||
final PsiAnnotationOwner owner = annotation.getOwner();
|
||||
@@ -463,10 +526,10 @@ public class AnnotationsHighlightUtil {
|
||||
}
|
||||
}
|
||||
|
||||
private static class DeleteNotApplicableAnnotationAction implements IntentionAction {
|
||||
private static class DeleteAnnotationAction implements IntentionAction {
|
||||
private final PsiAnnotation myAnnotation;
|
||||
|
||||
public DeleteNotApplicableAnnotationAction(PsiAnnotation annotation) {
|
||||
public DeleteAnnotationAction(PsiAnnotation annotation) {
|
||||
myAnnotation = annotation;
|
||||
}
|
||||
|
||||
|
||||
@@ -1383,7 +1383,7 @@ public class HighlightUtil extends HighlightUtilBase {
|
||||
if (aClass.isInterface()) {
|
||||
return thisNotFoundInInterfaceInfo(expr);
|
||||
}
|
||||
|
||||
|
||||
if (aClass instanceof PsiAnonymousClass && PsiTreeUtil.isAncestor(((PsiAnonymousClass)aClass).getArgumentList(), expr, true)) {
|
||||
final PsiClass parentClass = PsiTreeUtil.getParentOfType(aClass, PsiClass.class, true);
|
||||
if (parentClass != null && parentClass.isInterface()) {
|
||||
@@ -2630,7 +2630,7 @@ public class HighlightUtil extends HighlightUtilBase {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static enum Feature {
|
||||
private enum Feature {
|
||||
GENERICS(LanguageLevel.JDK_1_5, "feature.generics"),
|
||||
ANNOTATIONS(LanguageLevel.JDK_1_5, "feature.annotations"),
|
||||
STATIC_IMPORTS(LanguageLevel.JDK_1_5, "feature.static.imports"),
|
||||
@@ -2644,12 +2644,13 @@ public class HighlightUtil extends HighlightUtilBase {
|
||||
UNDERSCORES(LanguageLevel.JDK_1_7, "feature.underscores.in.literals"),
|
||||
EXTENSION_METHODS(LanguageLevel.JDK_1_8, "feature.extension.methods"),
|
||||
METHOD_REFERENCES(LanguageLevel.JDK_1_8, "feature.method.references"),
|
||||
LAMBDA_EXPRESSIONS(LanguageLevel.JDK_1_8, "feature.lambda.expressions");
|
||||
LAMBDA_EXPRESSIONS(LanguageLevel.JDK_1_8, "feature.lambda.expressions"),
|
||||
TYPE_ANNOTATIONS(LanguageLevel.JDK_1_8, "feature.type.annotations");
|
||||
|
||||
private final LanguageLevel level;
|
||||
private final String key;
|
||||
|
||||
private Feature(final LanguageLevel level, @PropertyKey(resourceBundle = JavaErrorMessages.BUNDLE) final String key) {
|
||||
Feature(final LanguageLevel level, @PropertyKey(resourceBundle = JavaErrorMessages.BUNDLE) final String key) {
|
||||
this.level = level;
|
||||
this.key = key;
|
||||
}
|
||||
@@ -2658,9 +2659,8 @@ public class HighlightUtil extends HighlightUtilBase {
|
||||
@Nullable
|
||||
private static HighlightInfo checkFeature(@Nullable final PsiElement element, @NotNull final Feature feature) {
|
||||
if (element != null && element.getManager().isInProject(element) && !PsiUtil.getLanguageLevel(element).isAtLeast(feature.level)) {
|
||||
final String message = JavaErrorMessages.message("insufficient.language.level", JavaErrorMessages.message(feature.key));
|
||||
final HighlightInfo info =
|
||||
HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(element).descriptionAndTooltip(message).create();
|
||||
String message = JavaErrorMessages.message("insufficient.language.level", JavaErrorMessages.message(feature.key));
|
||||
HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(element).descriptionAndTooltip(message).create();
|
||||
QuickFixAction.registerQuickFixAction(info, new IncreaseLanguageLevelFix(feature.level));
|
||||
QuickFixAction.registerQuickFixAction(info, new ShowModulePropertiesFix(element));
|
||||
return info;
|
||||
@@ -2670,57 +2670,62 @@ public class HighlightUtil extends HighlightUtilBase {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static HighlightInfo checkGenericsFeature(final PsiElement parameterList, final int listSize) {
|
||||
public static HighlightInfo checkGenericsFeature(PsiElement parameterList, int listSize) {
|
||||
return listSize > 0 ? checkFeature(parameterList, Feature.GENERICS) : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static HighlightInfo checkAnnotationFeature(final PsiElement element) {
|
||||
public static HighlightInfo checkAnnotationFeature(PsiElement element) {
|
||||
return checkFeature(element, Feature.ANNOTATIONS);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static HighlightInfo checkForEachFeature(final PsiForeachStatement statement) {
|
||||
public static HighlightInfo checkForEachFeature(PsiForeachStatement statement) {
|
||||
return checkFeature(statement, Feature.FOR_EACH);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static HighlightInfo checkStaticImportFeature(final PsiImportStaticStatement statement) {
|
||||
public static HighlightInfo checkStaticImportFeature(PsiImportStaticStatement statement) {
|
||||
return checkFeature(statement, Feature.STATIC_IMPORTS);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static HighlightInfo checkVarargFeature(final PsiParameter parameter) {
|
||||
public static HighlightInfo checkVarargFeature(PsiParameter parameter) {
|
||||
return checkFeature(parameter, Feature.VARARGS);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static HighlightInfo checkDiamondFeature(@NotNull final PsiTypeElement typeElement) {
|
||||
public static HighlightInfo checkDiamondFeature(PsiTypeElement typeElement) {
|
||||
return typeElement.getType() instanceof PsiDiamondType ? checkFeature(typeElement.getParent(), Feature.DIAMOND_TYPES) : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static HighlightInfo checkMultiCatchFeature(@NotNull final PsiParameter parameter) {
|
||||
public static HighlightInfo checkMultiCatchFeature(PsiParameter parameter) {
|
||||
return parameter.getType() instanceof PsiDisjunctionType ? checkFeature(parameter, Feature.MULTI_CATCH) : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static HighlightInfo checkTryWithResourcesFeature(@NotNull final PsiResourceVariable resourceVariable) {
|
||||
public static HighlightInfo checkTryWithResourcesFeature(PsiResourceVariable resourceVariable) {
|
||||
return checkFeature(resourceVariable.getParent(), Feature.TRY_WITH_RESOURCES);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static HighlightInfo checkExtensionMethodsFeature(final PsiMethod method) {
|
||||
public static HighlightInfo checkExtensionMethodsFeature(PsiMethod method) {
|
||||
return checkFeature(method, Feature.EXTENSION_METHODS);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static HighlightInfo checkMethodReferencesFeature(final PsiMethodReferenceExpression expression) {
|
||||
public static HighlightInfo checkMethodReferencesFeature(PsiMethodReferenceExpression expression) {
|
||||
return checkFeature(expression, Feature.METHOD_REFERENCES);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static HighlightInfo checkLambdaFeature(final PsiLambdaExpression expression) {
|
||||
public static HighlightInfo checkLambdaFeature(PsiLambdaExpression expression) {
|
||||
return checkFeature(expression, Feature.LAMBDA_EXPRESSIONS);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static HighlightInfo checkTypeAnnotationFeature(PsiAnnotation annotation) {
|
||||
return checkFeature(annotation, Feature.TYPE_ANNOTATIONS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* Copyright 2000-2013 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.
|
||||
@@ -41,6 +41,13 @@ public interface PsiAnnotation extends PsiAnnotationMemberValue, PsiMetaOwner {
|
||||
|
||||
@NonNls String DEFAULT_REFERENCED_METHOD_NAME = "value";
|
||||
|
||||
/**
|
||||
* Kinds of element to which an annotation type is applicable (see {@link java.lang.annotation.ElementType}).
|
||||
*/
|
||||
enum TargetType {
|
||||
TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, ANNOTATION_TYPE, PACKAGE, TYPE_USE, TYPE_PARAMETER
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of parameters for the annotation.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* Copyright 2000-2013 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.
|
||||
@@ -46,18 +46,35 @@ import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.PairFunction;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
import static com.intellij.psi.PsiAnnotation.TargetType;
|
||||
|
||||
public class PsiImplUtil {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.PsiImplUtil");
|
||||
|
||||
private PsiImplUtil() {
|
||||
}
|
||||
private static final Set<TargetType> DEFAULT_TARGETS = ContainerUtil.newHashSet(
|
||||
TargetType.PACKAGE, TargetType.TYPE, TargetType.ANNOTATION_TYPE,
|
||||
TargetType.FIELD, TargetType.METHOD, TargetType.CONSTRUCTOR,
|
||||
TargetType.PARAMETER, TargetType.LOCAL_VARIABLE);
|
||||
|
||||
private static final TargetType[] PACKAGE_TARGETS = {TargetType.PACKAGE};
|
||||
private static final TargetType[] TYPE_USE_TARGETS = {TargetType.TYPE_USE};
|
||||
private static final TargetType[] ANNOTATION_TARGETS = {TargetType.ANNOTATION_TYPE, TargetType.TYPE, TargetType.TYPE_USE};
|
||||
private static final TargetType[] TYPE_TARGETS = {TargetType.TYPE, TargetType.TYPE_USE};
|
||||
private static final TargetType[] TYPE_PARAMETER_TARGETS = {TargetType.TYPE_PARAMETER, TargetType.TYPE_USE};
|
||||
private static final TargetType[] CONSTRUCTOR_TARGETS = {TargetType.CONSTRUCTOR, TargetType.TYPE_USE};
|
||||
private static final TargetType[] METHOD_TARGETS = {TargetType.METHOD, TargetType.TYPE_USE};
|
||||
private static final TargetType[] FIELD_TARGETS = {TargetType.FIELD, TargetType.TYPE_USE};
|
||||
private static final TargetType[] PARAMETER_TARGETS = {TargetType.PARAMETER, TargetType.TYPE_USE};
|
||||
private static final TargetType[] LOCAL_VARIABLE_TARGETS ={TargetType.LOCAL_VARIABLE, TargetType.TYPE_USE};
|
||||
|
||||
private PsiImplUtil() { }
|
||||
|
||||
@NotNull
|
||||
public static PsiMethod[] getConstructors(@NotNull PsiClass aClass) {
|
||||
@@ -142,7 +159,7 @@ public class PsiImplUtil {
|
||||
int i;
|
||||
for (i = parameters.length - 1; i >= 0; i--) {
|
||||
PsiParameter paramInList = parameters[i];
|
||||
if (name.equals(paramInList.getName())) {
|
||||
if (Comparing.equal(name, paramInList.getName())) {
|
||||
suspect = paramInList;
|
||||
break;
|
||||
}
|
||||
@@ -298,17 +315,152 @@ public class PsiImplUtil {
|
||||
return new PsiImmediateClassType(classClass, substitutor);
|
||||
}
|
||||
|
||||
@Nullable public static PsiAnnotation findAnnotation(@NotNull PsiAnnotationOwner modifierList, @NotNull String qualifiedName) {
|
||||
PsiAnnotation[] annotations = modifierList.getAnnotations();
|
||||
@Nullable
|
||||
public static PsiAnnotation findAnnotation(@NotNull PsiAnnotationOwner annotationOwner, @NotNull String qualifiedName) {
|
||||
PsiAnnotation[] annotations = annotationOwner.getAnnotations();
|
||||
if (annotations.length == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final String shortName = StringUtil.getShortName(qualifiedName);
|
||||
String shortName = StringUtil.getShortName(qualifiedName);
|
||||
for (PsiAnnotation annotation : annotations) {
|
||||
final PsiJavaCodeReferenceElement referenceElement = annotation.getNameReferenceElement();
|
||||
PsiJavaCodeReferenceElement referenceElement = annotation.getNameReferenceElement();
|
||||
if (referenceElement != null && shortName.equals(referenceElement.getReferenceName())) {
|
||||
if (qualifiedName.equals(annotation.getQualifiedName())) return annotation;
|
||||
if (qualifiedName.equals(annotation.getQualifiedName())) {
|
||||
return annotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static TargetType translateTargetRef(PsiReference reference) {
|
||||
PsiElement field = reference.resolve();
|
||||
if (field instanceof PsiEnumConstant) {
|
||||
String name = ((PsiEnumConstant)field).getName();
|
||||
try {
|
||||
return TargetType.valueOf(name);
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
LOG.warn("Unknown target: " + name);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean isAnnotationApplicable(@NotNull PsiAnnotation annotation, boolean strict, @Nullable TargetType... types) {
|
||||
if (types != null && types.length != 0) {
|
||||
PsiJavaCodeReferenceElement ref = annotation.getNameReferenceElement();
|
||||
if (ref != null) {
|
||||
PsiElement annotationType = ref.resolve();
|
||||
if (annotationType instanceof PsiClass) {
|
||||
return findApplicableTarget((PsiClass)annotationType, types) != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return !strict;
|
||||
}
|
||||
|
||||
public static boolean isAnnotationApplicable(@NotNull PsiClass annotationType, boolean strict, @Nullable TargetType... types) {
|
||||
return types == null || types.length == 0 ? !strict : findApplicableTarget(annotationType, types) != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static TargetType findApplicableTarget(@NotNull PsiClass annotationType, @NotNull TargetType... types) {
|
||||
Set<TargetType> targets = getAnnotationTargets(annotationType);
|
||||
if (targets != null) {
|
||||
for (TargetType type : types) {
|
||||
if (targets.contains(type)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Set<TargetType> getAnnotationTargets(PsiClass annotationType) {
|
||||
if (!annotationType.isAnnotationType()) return null;
|
||||
PsiModifierList modifierList = annotationType.getModifierList();
|
||||
if (modifierList == null) return null;
|
||||
|
||||
// todo[r.sh] cache?
|
||||
PsiAnnotation target = modifierList.findAnnotation(CommonClassNames.TARGET_ANNOTATION_FQ_NAME);
|
||||
if (target == null) return DEFAULT_TARGETS; // if omitted it is applicable to all but Java 8 TYPE_USE/TYPE_PARAMETERS targets
|
||||
|
||||
PsiNameValuePair[] values = target.getParameterList().getAttributes();
|
||||
if (values.length == 0) return Collections.emptySet();
|
||||
|
||||
PsiAnnotationMemberValue value = values[0].getValue();
|
||||
if (value instanceof PsiReference) {
|
||||
TargetType targetType = translateTargetRef((PsiReference)value);
|
||||
if (targetType != null) {
|
||||
return Collections.singleton(targetType);
|
||||
}
|
||||
}
|
||||
else if (value instanceof PsiArrayInitializerMemberValue) {
|
||||
Set <TargetType> targets = ContainerUtil.newHashSet();
|
||||
for (PsiAnnotationMemberValue initializer : ((PsiArrayInitializerMemberValue)value).getInitializers()) {
|
||||
if (initializer instanceof PsiReference) {
|
||||
TargetType targetType = translateTargetRef((PsiReference)initializer);
|
||||
if (targetType != null) {
|
||||
targets.add(targetType);
|
||||
}
|
||||
}
|
||||
}
|
||||
return targets;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static TargetType[] getApplicableTargets(@Nullable PsiAnnotationOwner owner) {
|
||||
if (owner == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (owner instanceof PsiType || owner instanceof PsiTypeElement) {
|
||||
return TYPE_USE_TARGETS;
|
||||
}
|
||||
|
||||
if (owner instanceof PsiTypeParameter) {
|
||||
return TYPE_PARAMETER_TARGETS;
|
||||
}
|
||||
|
||||
if (owner instanceof PsiModifierList) {
|
||||
PsiElement element = ((PsiModifierList)owner).getParent();
|
||||
if (element instanceof PsiPackageStatement) {
|
||||
return PACKAGE_TARGETS;
|
||||
}
|
||||
if (element instanceof PsiClass) {
|
||||
if (((PsiClass)element).isAnnotationType()) {
|
||||
return ANNOTATION_TARGETS;
|
||||
}
|
||||
else {
|
||||
return TYPE_TARGETS;
|
||||
}
|
||||
}
|
||||
if (element instanceof PsiMethod) {
|
||||
if (((PsiMethod)element).isConstructor()) {
|
||||
return CONSTRUCTOR_TARGETS;
|
||||
}
|
||||
else {
|
||||
return METHOD_TARGETS;
|
||||
}
|
||||
}
|
||||
if (element instanceof PsiField) {
|
||||
return FIELD_TARGETS;
|
||||
}
|
||||
if (element instanceof PsiParameter) {
|
||||
return PARAMETER_TARGETS;
|
||||
}
|
||||
if (element instanceof PsiLocalVariable) {
|
||||
return LOCAL_VARIABLE_TARGETS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,14 +20,15 @@ import com.intellij.lang.LighterASTNode;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.CommonClassNames;
|
||||
import com.intellij.psi.JavaTokenType;
|
||||
import com.intellij.psi.PsiAnnotation;
|
||||
import com.intellij.psi.PsiNameHelper;
|
||||
import com.intellij.psi.impl.PsiImplUtil;
|
||||
import com.intellij.psi.impl.java.stubs.JavaStubElementTypes;
|
||||
import com.intellij.psi.impl.java.stubs.PsiAnnotationStub;
|
||||
import com.intellij.psi.impl.java.stubs.PsiClassStub;
|
||||
import com.intellij.psi.impl.java.stubs.PsiModifierListStub;
|
||||
import com.intellij.psi.impl.source.tree.JavaElementType;
|
||||
import com.intellij.psi.impl.source.tree.LightTreeUtil;
|
||||
import com.intellij.psi.impl.source.tree.java.PsiAnnotationImpl;
|
||||
import com.intellij.psi.stubs.StubBase;
|
||||
import com.intellij.psi.stubs.StubElement;
|
||||
import com.intellij.psi.stubs.StubInputStream;
|
||||
@@ -94,8 +95,7 @@ public class TypeInfo {
|
||||
for (StubElement child : modifierList.getChildrenStubs()) {
|
||||
if (!(child instanceof PsiAnnotationStub)) continue;
|
||||
PsiAnnotationStub annotationStub = (PsiAnnotationStub)child;
|
||||
PsiAnnotationImpl annotation = (PsiAnnotationImpl)annotationStub.getPsiElement();
|
||||
if (PsiAnnotationImpl.isAnnotationApplicableTo(annotation, true, "TYPE_USE")) {
|
||||
if (PsiImplUtil.isAnnotationApplicable(annotationStub.getPsiElement(), true, PsiAnnotation.TargetType.TYPE_USE)) {
|
||||
annotationStubs.add(annotationStub);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,42 +207,24 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
|
||||
@Override
|
||||
public final ASTNode findChildByRole(final int role) {
|
||||
LOG.assertTrue(ChildRole.isUnique(role));
|
||||
|
||||
switch (role) {
|
||||
default:
|
||||
return null;
|
||||
case ChildRole.REFERENCE_NAME:
|
||||
return TreeUtil.findChildBackward(this, JavaTokenType.IDENTIFIER);
|
||||
|
||||
case ChildRole.REFERENCE_NAME:
|
||||
if (getLastChildNode().getElementType() == JavaTokenType.IDENTIFIER) {
|
||||
return getLastChildNode();
|
||||
}
|
||||
else {
|
||||
if (getLastChildNode().getElementType() == JavaElementType.REFERENCE_PARAMETER_LIST) {
|
||||
ASTNode current = getLastChildNode().getTreePrev();
|
||||
while (current != null && (current.getPsi() instanceof PsiWhiteSpace || current.getPsi() instanceof PsiComment)) {
|
||||
current = current.getTreePrev();
|
||||
}
|
||||
if (current != null && current.getElementType() == JavaTokenType.IDENTIFIER) {
|
||||
return current;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
case ChildRole.REFERENCE_PARAMETER_LIST:
|
||||
if (getLastChildNode().getElementType() == JavaElementType.REFERENCE_PARAMETER_LIST) {
|
||||
return getLastChildNode();
|
||||
case ChildRole.REFERENCE_PARAMETER_LIST: {
|
||||
TreeElement lastChild = getLastChildNode();
|
||||
return lastChild.getElementType() == JavaElementType.REFERENCE_PARAMETER_LIST ? lastChild : null;
|
||||
}
|
||||
return null;
|
||||
|
||||
case ChildRole.QUALIFIER:
|
||||
if (getFirstChildNode().getElementType() == JavaElementType.JAVA_CODE_REFERENCE) {
|
||||
return getFirstChildNode();
|
||||
}
|
||||
return null;
|
||||
return findChildByType(JavaElementType.JAVA_CODE_REFERENCE);
|
||||
|
||||
case ChildRole.DOT:
|
||||
return findChildByType(JavaTokenType.DOT);
|
||||
return findChildByType(JavaTokenType.DOT);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -712,7 +694,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
|
||||
|
||||
@Override
|
||||
public boolean isQualified() {
|
||||
return getChildRole(getFirstChildNode()) != ChildRole.REFERENCE_NAME;
|
||||
return getQualifier() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -28,7 +28,6 @@ import com.intellij.psi.impl.source.codeStyle.CodeEditUtil;
|
||||
import com.intellij.psi.impl.source.tree.CompositeElement;
|
||||
import com.intellij.psi.impl.source.tree.Factory;
|
||||
import com.intellij.psi.impl.source.tree.TreeElement;
|
||||
import com.intellij.psi.impl.source.tree.java.PsiAnnotationImpl;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
@@ -259,11 +258,11 @@ public class PsiModifierListImpl extends JavaStubPsiElement<PsiModifierListStub>
|
||||
@Override
|
||||
@NotNull
|
||||
public PsiAnnotation[] getApplicableAnnotations() {
|
||||
final String[] fields = PsiAnnotationImpl.getApplicableElementTypeFields(this);
|
||||
final PsiAnnotation.TargetType[] targets = PsiImplUtil.getApplicableTargets(this);
|
||||
List<PsiAnnotation> filtered = ContainerUtil.findAll(getAnnotations(), new Condition<PsiAnnotation>() {
|
||||
@Override
|
||||
public boolean value(PsiAnnotation annotation) {
|
||||
return PsiAnnotationImpl.isAnnotationApplicableTo(annotation, true, fields);
|
||||
return PsiImplUtil.isAnnotationApplicable(annotation, true, targets);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@ import com.intellij.psi.impl.DebugUtil;
|
||||
import com.intellij.psi.impl.PsiImplUtil;
|
||||
import com.intellij.psi.impl.source.codeStyle.CodeEditUtil;
|
||||
import com.intellij.psi.impl.source.tree.*;
|
||||
import com.intellij.psi.impl.source.tree.java.PsiAnnotationImpl;
|
||||
import com.intellij.psi.scope.PsiScopeProcessor;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
@@ -159,10 +158,10 @@ public class PsiTypeElementImpl extends CompositePsiElement implements PsiTypeEl
|
||||
public static void addTypeUseAnnotationsFromModifierList(PsiElement member, List<PsiAnnotation> typeAnnotations) {
|
||||
if (!(member instanceof PsiModifierListOwner)) return;
|
||||
PsiModifierList list = ((PsiModifierListOwner)member).getModifierList();
|
||||
PsiAnnotation[] gluedAnnotations = list == null ? PsiAnnotation.EMPTY_ARRAY : list.getAnnotations();
|
||||
for (PsiAnnotation anno : gluedAnnotations) {
|
||||
if (PsiAnnotationImpl.isAnnotationApplicableTo(anno, true, "TYPE_USE")) {
|
||||
typeAnnotations.add(anno);
|
||||
PsiAnnotation[] annotations = list == null ? PsiAnnotation.EMPTY_ARRAY : list.getAnnotations();
|
||||
for (PsiAnnotation annotation : annotations) {
|
||||
if (PsiImplUtil.isAnnotationApplicable(annotation, true, PsiAnnotation.TargetType.TYPE_USE)) {
|
||||
typeAnnotations.add(annotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,7 +16,6 @@
|
||||
package com.intellij.psi.impl.source.tree.java;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiImplUtil;
|
||||
@@ -24,10 +23,9 @@ import com.intellij.psi.impl.java.stubs.JavaStubElementTypes;
|
||||
import com.intellij.psi.impl.java.stubs.PsiAnnotationStub;
|
||||
import com.intellij.psi.impl.meta.MetaRegistry;
|
||||
import com.intellij.psi.impl.source.JavaStubPsiElement;
|
||||
import com.intellij.psi.impl.source.PsiClassReferenceType;
|
||||
import com.intellij.psi.meta.PsiMetaData;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.PairFunction;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -37,8 +35,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
* @author ven
|
||||
*/
|
||||
public class PsiAnnotationImpl extends JavaStubPsiElement<PsiAnnotationStub> implements PsiAnnotation {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.PsiAnnotationImpl");
|
||||
|
||||
private static final PairFunction<Project, String, PsiAnnotation> ANNOTATION_CREATOR = new PairFunction<Project, String, PsiAnnotation>() {
|
||||
@Override
|
||||
public PsiAnnotation fun(Project project, String text) {
|
||||
@@ -56,16 +52,12 @@ public class PsiAnnotationImpl extends JavaStubPsiElement<PsiAnnotationStub> imp
|
||||
|
||||
@Override
|
||||
public PsiJavaCodeReferenceElement getNameReferenceElement() {
|
||||
final PsiAnnotationStub stub = getStub();
|
||||
PsiAnnotationStub stub = getStub();
|
||||
if (stub != null) {
|
||||
return PsiTreeUtil.getRequiredChildOfType(stub.getPsiElement(), PsiJavaCodeReferenceElement.class);
|
||||
}
|
||||
|
||||
final Object result = PsiTreeUtil.getChildOfType(this, PsiJavaCodeReferenceElement.class);
|
||||
if (result != null && !(result instanceof PsiJavaCodeReferenceElement)) {
|
||||
throw new AssertionError("getChildOfType returned rubbish: " + result);
|
||||
}
|
||||
return (PsiJavaCodeReferenceElement)result;
|
||||
return PsiTreeUtil.getChildOfType(this, PsiJavaCodeReferenceElement.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -122,149 +114,24 @@ public class PsiAnnotationImpl extends JavaStubPsiElement<PsiAnnotationStub> imp
|
||||
@Override
|
||||
public PsiAnnotationOwner getOwner() {
|
||||
PsiElement parent = getParent();
|
||||
if (!PsiUtil.isLanguageLevel8OrHigher(this)) {
|
||||
return parent instanceof PsiModifierList ? (PsiAnnotationOwner)parent : null;
|
||||
}
|
||||
|
||||
if (parent instanceof PsiTypeElement) {
|
||||
return ((PsiTypeElement)parent).getOwner(this);
|
||||
}
|
||||
if (parent instanceof PsiTypeParameter) {
|
||||
if (parent instanceof PsiAnnotationOwner) {
|
||||
return (PsiAnnotationOwner)parent;
|
||||
}
|
||||
PsiElement member = parent.getParent();
|
||||
String[] elementTypeFields = getApplicableElementTypeFields(member);
|
||||
if (elementTypeFields == null) return null;
|
||||
if (parent instanceof PsiAnnotationOwner
|
||||
&& isAnnotationApplicableTo(this, true, elementTypeFields)) return (PsiAnnotationOwner)parent;
|
||||
|
||||
PsiAnnotationOwner typeElement;
|
||||
if (member instanceof PsiVariable) {
|
||||
if (member instanceof PsiEnumConstant && parent instanceof PsiAnnotationOwner){
|
||||
return (PsiAnnotationOwner)parent;
|
||||
}
|
||||
typeElement = ((PsiVariable)member).getTypeElement();
|
||||
}
|
||||
else if (member instanceof PsiMethod && !((PsiMethod)member).isConstructor()) {
|
||||
typeElement = ((PsiMethod)member).getReturnTypeElement();
|
||||
}
|
||||
else if (parent instanceof PsiAnnotationOwner) {
|
||||
typeElement = (PsiAnnotationOwner)parent;
|
||||
}
|
||||
else {
|
||||
typeElement = null;
|
||||
}
|
||||
return typeElement;
|
||||
}
|
||||
|
||||
public static boolean isAnnotationApplicableTo(PsiAnnotation annotation, boolean strict, String... elementTypeFields) {
|
||||
if (elementTypeFields == null) return true;
|
||||
PsiJavaCodeReferenceElement nameRef = annotation.getNameReferenceElement();
|
||||
if (nameRef == null) {
|
||||
return !strict;
|
||||
}
|
||||
PsiElement resolved = nameRef.resolve();
|
||||
if (!(resolved instanceof PsiClass) || !((PsiClass)resolved).isAnnotationType()) {
|
||||
return !strict;
|
||||
}
|
||||
PsiClass annotationType = (PsiClass)resolved;
|
||||
return isAnnotationApplicable(strict, annotationType, elementTypeFields, annotation.getResolveScope());
|
||||
}
|
||||
|
||||
public static boolean isAnnotationApplicable(boolean strict,
|
||||
@NotNull PsiClass annotationType,
|
||||
@Nullable String[] elementTypeFields,
|
||||
GlobalSearchScope resolveScope) {
|
||||
if (elementTypeFields == null) {
|
||||
return !strict;
|
||||
}
|
||||
|
||||
PsiAnnotation target = annotationType.getModifierList().findAnnotation(CommonClassNames.TARGET_ANNOTATION_FQ_NAME);
|
||||
if (target == null) {
|
||||
//todo hack: ambiguity in spec
|
||||
return !strict;
|
||||
//return !ArrayUtil.contains("TYPE_USE", elementTypeFields);
|
||||
}
|
||||
PsiNameValuePair[] attributes = target.getParameterList().getAttributes();
|
||||
if (attributes.length == 0) {
|
||||
return !strict;
|
||||
}
|
||||
LOG.assertTrue(elementTypeFields.length > 0);
|
||||
|
||||
PsiClass elementTypeClass =
|
||||
JavaPsiFacade.getInstance(annotationType.getProject()).findClass("java.lang.annotation.ElementType", resolveScope);
|
||||
if (elementTypeClass == null) {
|
||||
//todo hack
|
||||
return !strict;
|
||||
//return !ArrayUtil.contains("TYPE_USE", elementTypeFields);
|
||||
}
|
||||
|
||||
PsiAnnotationMemberValue value = null;
|
||||
for (String fieldName : elementTypeFields) {
|
||||
PsiField field = elementTypeClass.findFieldByName(fieldName, false);
|
||||
if (field == null) {
|
||||
continue;
|
||||
}
|
||||
if (value == null) {
|
||||
value = attributes[0].getValue();
|
||||
}
|
||||
if (value instanceof PsiArrayInitializerMemberValue) {
|
||||
PsiAnnotationMemberValue[] initializers = ((PsiArrayInitializerMemberValue)value).getInitializers();
|
||||
for (PsiAnnotationMemberValue initializer : initializers) {
|
||||
if (initializer instanceof PsiReference) {
|
||||
if (((PsiReference)initializer).isReferenceTo(field)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (value instanceof PsiReference) {
|
||||
if (((PsiReference)value).isReferenceTo(field)) {
|
||||
return true;
|
||||
}
|
||||
if (parent instanceof PsiReferenceExpression) {
|
||||
PsiElement ctx = parent.getParent();
|
||||
if (ctx instanceof PsiMethodReferenceExpression) {
|
||||
return new PsiClassReferenceType((PsiJavaCodeReferenceElement)parent, null);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String[] getApplicableElementTypeFields(PsiElement owner) {
|
||||
if (owner instanceof PsiClass) {
|
||||
PsiClass aClass = (PsiClass)owner;
|
||||
if (aClass.isAnnotationType()) {
|
||||
return new String[]{"ANNOTATION_TYPE", "TYPE"};
|
||||
else if (parent instanceof PsiJavaCodeReferenceElement) {
|
||||
PsiElement ctx = PsiTreeUtil.skipParentsOfType(parent, PsiJavaCodeReferenceElement.class);
|
||||
if (ctx instanceof PsiReferenceList || ctx instanceof PsiNewExpression || ctx instanceof PsiTypeElement) {
|
||||
return new PsiClassReferenceType((PsiJavaCodeReferenceElement)parent, null);
|
||||
}
|
||||
else if (aClass instanceof PsiTypeParameter) {
|
||||
return new String[]{"TYPE_PARAMETER"};
|
||||
}
|
||||
else {
|
||||
return new String[]{"TYPE"};
|
||||
}
|
||||
}
|
||||
if (owner instanceof PsiMethod) {
|
||||
if (((PsiMethod)owner).isConstructor()) {
|
||||
return new String[]{"CONSTRUCTOR"};
|
||||
}
|
||||
else {
|
||||
return new String[]{"METHOD"};
|
||||
}
|
||||
}
|
||||
if (owner instanceof PsiField) {
|
||||
return new String[]{"FIELD"};
|
||||
}
|
||||
if (owner instanceof PsiParameter) {
|
||||
return new String[]{"PARAMETER"};
|
||||
}
|
||||
if (owner instanceof PsiLocalVariable) {
|
||||
return new String[]{"LOCAL_VARIABLE"};
|
||||
}
|
||||
if (owner instanceof PsiPackageStatement) {
|
||||
return new String[]{"PACKAGE"};
|
||||
}
|
||||
if (owner instanceof PsiTypeElement) {
|
||||
return new String[]{"TYPE_USE"};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,10 @@ annotation.annotation.type.expected=Annotation type expected
|
||||
annotation.members.may.not.have.throws.list=@interface members may not have throws list
|
||||
annotation.may.not.have.extends.list=@interface may not have extends list
|
||||
annotation.name.is.missing=Annotation attribute must be of the form 'name=value'
|
||||
annotation.not.allowed.ref=Annotation not applicable to this kind of reference
|
||||
annotation.not.allowed.static=Static member qualifying type may not be annotated
|
||||
annotation.not.allowed.void='void' type may not be annotated
|
||||
annotation.not.allowed.class=Class literal type may not be annotated
|
||||
|
||||
# These aren't unused.
|
||||
# suppress inspection "UnusedProperty"
|
||||
@@ -364,4 +368,5 @@ feature.underscores.in.literals=Underscores in literals
|
||||
feature.extension.methods=Extension methods
|
||||
feature.method.references=Method references
|
||||
feature.lambda.expressions=Lambda expressions
|
||||
feature.type.annotations=Type annotations
|
||||
insufficient.language.level={0} are not supported at this language level
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import java.util.List;
|
||||
|
||||
@<error descr="'@SafeVarargs' not applicable to type">SafeVarargs</error>
|
||||
<error descr="'@SafeVarargs' not applicable to type">@SafeVarargs</error>
|
||||
public class SafeVarargsTests {
|
||||
//fixed arity
|
||||
<error descr="@SafeVarargs is not allowed on methods with fixed arity">@SafeVarargs</error>
|
||||
|
||||
@@ -5,4 +5,4 @@ import java.lang.annotation.*;
|
||||
@Expose @interface Expose {}
|
||||
|
||||
@Target({ElementType.FIELD})
|
||||
@<error descr="'@Expose1' not applicable to annotation type">Expose1</error>@interface Expose1 {}
|
||||
<error descr="'@Expose1' not applicable to annotation type">@Expose1</error>@interface Expose1 {}
|
||||
@@ -1 +1 @@
|
||||
@<error descr="'@SuppressWarnings' not applicable to package">SuppressWarnings</error>("all") package annotations.invalidPackageAnnotationTarget;
|
||||
<error descr="'@SuppressWarnings' not applicable to package">@SuppressWarnings("all")</error> package annotations.invalidPackageAnnotationTarget;
|
||||
|
||||
@@ -1,33 +1,141 @@
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.*;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.io.<error descr="Annotations are not allowed here">@SuppressWarnings</error> Reader;
|
||||
import <error descr="Annotations are not allowed here">@SuppressWarnings</error> java.io.Writer;
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
|
||||
@Target({ElementType.TYPE_USE/*, ElementType.TYPE*/})
|
||||
@interface TA {
|
||||
}
|
||||
/*@Target({CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})*/ @interface A { }
|
||||
@Target({TYPE_USE}) @interface TA { }
|
||||
@Target({TYPE_PARAMETER}) @interface TPA { }
|
||||
|
||||
@<error descr="'@TA' not applicable to type">TA</error>
|
||||
class X0<@<error descr="'@TA' not applicable to type parameter">TA</error> T> {
|
||||
@TA
|
||||
protected
|
||||
void f() @<error descr="'@TA' not applicable to parameter">TA</error> {
|
||||
@TA String p=new @TA String();
|
||||
@A @TA <error descr="'@TPA' not applicable to type">@TPA</error>
|
||||
class Outer {
|
||||
private Map<@TA String, @TA List<@TA <error descr="'@A' not applicable to type use">@A</error> String>> m;
|
||||
|
||||
if (this instanceof @TA Object) return;
|
||||
String o = p;
|
||||
List<@TA String> l;
|
||||
Class c = @TA String.class;
|
||||
interface I { void m(int i); }
|
||||
private I i = (@TA <error descr="'@Override' not applicable to parameter">@Override</error> final int k) -> { };
|
||||
|
||||
<error descr="'void' type may not be annotated">@TA</error> <T> void m(T t) { }
|
||||
<error descr="'void' type may not be annotated">@TA</error> void test1() {
|
||||
this.<@TA <error descr="'@TPA' not applicable to type use">@TPA</error> String>m("...");
|
||||
}
|
||||
|
||||
class FF<F extends @TA String> { }
|
||||
|
||||
Collection<? super @TA String> cs;
|
||||
|
||||
interface BI<T> { }
|
||||
class BII<T> implements @TA BI<@TA T> { }
|
||||
class BIII extends @TA BII<Object> { }
|
||||
|
||||
void tm() throws @TA RuntimeException { }
|
||||
|
||||
class Middle {
|
||||
class Inner {
|
||||
void test() {
|
||||
@TA Inner v1;
|
||||
@TA Middle.@TA Inner v2;
|
||||
@TA Outer.@TA Middle.@TA Inner v3;
|
||||
@TA Outer v4;
|
||||
@TA Outer.@TA Middle v5;
|
||||
@TA Outer.@TA Middle.@TA Inner v6;
|
||||
List<@TA Outer.@TA Middle.@TA Inner> l;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TA int @TA[] methodf() throws @TA Exception {
|
||||
boolean a = this instanceof @TA X0;
|
||||
X0<@<error descr="Duplicate annotation">TA</error> @<error descr="Duplicate annotation">TA</error> X0> c = new @TA X0<@TA X0>();
|
||||
Object o = (@TA Object) c;
|
||||
@TA X0.field = null;
|
||||
return null;
|
||||
static class StaticMiddle {
|
||||
static class StaticInner {
|
||||
void test() {
|
||||
@TA StaticInner v1;
|
||||
<error descr="Static member qualifying type may not be annotated">@TA</error> StaticMiddle.@TA StaticInner v2;
|
||||
<error descr="Static member qualifying type may not be annotated">@TA</error> Outer.<error descr="Static member qualifying type may not be annotated">@TA</error> StaticMiddle.@TA StaticInner v3;
|
||||
List<@TA Outer.<error descr="Static member qualifying type may not be annotated">@TA</error> StaticMiddle.@TA StaticInner> l;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TA() int @TA[] p;
|
||||
static @TA Object field;
|
||||
@TA List<String> disambiguateBetweenBinaryExpr;
|
||||
{
|
||||
new @TA Object();
|
||||
new @TA ArrayList<String>();
|
||||
|
||||
ArrayList<String> var = new <String> @TA ArrayList();
|
||||
new @TA Outer().new @TA Middle();
|
||||
|
||||
@A Map.@TA Entry e1;
|
||||
@A <error descr="Static member qualifying type may not be annotated">@TA</error> Map.@TA Entry e2;
|
||||
@A java.<error descr="Annotation not applicable to this kind of reference">@TA</error> util.Map.@TA Entry e3;
|
||||
@A List<java.<error descr="Annotation not applicable to this kind of reference">@TA</error> lang.@TA String> l1;
|
||||
|
||||
Object obj = "str";
|
||||
@TA String str = (@TA String)obj;
|
||||
|
||||
boolean b = str instanceof @TA String;
|
||||
|
||||
<error descr="Annotations are not allowed here">@TA</error> tm();
|
||||
|
||||
try (@TA Reader r = new @TA FileReader("/dev/zero"); @TA Writer w = new @TA FileWriter("/dev/null")) { }
|
||||
catch (@TA IllegalArgumentException | @TA IOException e) { }
|
||||
|
||||
@A @TA <error descr="Cannot resolve symbol 'Unknown'">Unknown</error>.@TA Unknown uu;
|
||||
|
||||
Class<?> c1 = <error descr="Class literal type may not be annotated">@TA</error> String.class;
|
||||
Class<?> c2 = int <error descr="Class literal type may not be annotated">@TA</error> [].class;
|
||||
}
|
||||
|
||||
interface IntFunction<T> { int apply(T t); }
|
||||
interface Sorter<T> { void sort(T[] a, Comparator<? super T> c); }
|
||||
void m1(IntFunction<Date> f) { }
|
||||
void m2(IntFunction<List<String>> f) { }
|
||||
void m3(Sorter<Integer> s) { }
|
||||
|
||||
void lambdas() {
|
||||
m1(@TA Date::getDay);
|
||||
m1(<error descr="Annotations are not allowed here">@TA</error> java.util.@TA Date::getDay);
|
||||
m2(List<@TA String>::size);
|
||||
m3(Arrays::<@TA Integer>sort);
|
||||
|
||||
Comparator<Object> cmp = (@TA Object x, @TA Object y) -> { System.out.println("x=" + x + " y=" + y); return 0; };
|
||||
}
|
||||
|
||||
void m(List<@TA ? extends Comparable<Object>> p) { }
|
||||
|
||||
void arrays(String @TA ... docs) {
|
||||
//todo[r.sh]
|
||||
//@TA String @TA [] @TA [] docs1 = new @TA String @TA [2] @TA [2];
|
||||
}
|
||||
|
||||
@TA Outer() { }
|
||||
|
||||
class MyClass<@TA @TPA T> { }
|
||||
interface MyInterface<@TA @TPA E> { }
|
||||
|
||||
static class Super {
|
||||
protected int aField;
|
||||
int getField() { return aField; }
|
||||
}
|
||||
static class This extends Super {
|
||||
void superField() {
|
||||
Outer.<error descr="Annotations are not allowed here">@TA</error> This.super.aField = 0;
|
||||
IntFunction<Super> f = Outer.<error descr="Annotations are not allowed here">@TA</error> This.super::getField;
|
||||
}
|
||||
}
|
||||
|
||||
//todo[r.sh]
|
||||
/*public String toString(@TA C this) { return ""; }
|
||||
|
||||
public boolean equals(@TA C this, @TA C other) { return false; }
|
||||
|
||||
C(@TA C this, boolean b) { }
|
||||
|
||||
class Outer {
|
||||
class Middle {
|
||||
class Inner {
|
||||
void innerMethod(@TA Outer.@TA Middle.@TA Inner this) { }
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
List<@<error descr="Duplicate annotation">TA</error> @<error descr="Duplicate annotation">TA</error> String> c = null;
|
||||
}
|
||||
|
||||
@@ -15,14 +15,14 @@ abstract class C {
|
||||
void notWrong() { }
|
||||
}
|
||||
|
||||
class B extends <error descr="Annotations are not allowed here">@Deprecated</error> Object { }
|
||||
class B extends <error descr="Type annotations are not supported at this language level">@Deprecated</error> Object { }
|
||||
|
||||
enum E {
|
||||
@Anno E1
|
||||
}
|
||||
|
||||
interface I {
|
||||
@<error descr="Duplicate annotation">Anno</error> public @<error descr="Duplicate annotation">Anno</error> Collection<<error descr="Annotations are not allowed here">@Anno</error> String> method(@<error descr="Duplicate annotation">Anno</error> @<error descr="Duplicate annotation">Anno</error> Object o);
|
||||
@<error descr="Duplicate annotation">Anno</error> public @<error descr="Duplicate annotation">Anno</error> Collection<<error descr="Type annotations are not supported at this language level">@Anno</error> String> method(@<error descr="Duplicate annotation">Anno</error> @<error descr="Duplicate annotation">Anno</error> Object o);
|
||||
}
|
||||
|
||||
@interface Caller {
|
||||
|
||||
@@ -3,10 +3,10 @@ interface I {
|
||||
}
|
||||
|
||||
class Foo {
|
||||
I ii = (@<error descr="'@Override' not applicable to type use">Override</error> final int k)->{
|
||||
I ii = (<error descr="'@Override' not applicable to parameter">@Override</error> final int k) -> {
|
||||
int j = k;
|
||||
};
|
||||
I ii1 = (final int k)->{
|
||||
I ii1 = (final int k) -> {
|
||||
<error descr="Incompatible types. Found: 'int', required: 'java.lang.String'">String s = k;</error>
|
||||
};
|
||||
|
||||
@@ -14,24 +14,24 @@ class Foo {
|
||||
bar((<error descr="Incompatible parameter types in lambda expression">String s</error>) -> {
|
||||
System.out.println(s);});
|
||||
bar((int i) -> {System.out.println(i);});
|
||||
}
|
||||
void bar(I i){}
|
||||
}
|
||||
|
||||
void bar(I i) { }
|
||||
}
|
||||
|
||||
class ReturnTypeCompatibility {
|
||||
interface I1<L> {
|
||||
L m(L x);
|
||||
}
|
||||
|
||||
interface I1<L> {
|
||||
L m(L x);
|
||||
}
|
||||
static <P> void call(I1<P> i2) {
|
||||
i2.m(null);
|
||||
}
|
||||
|
||||
static <P> void call(I1<P> i2) {
|
||||
i2.m(null);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
call((String i)->{ return i;});
|
||||
call(<error descr="Cyclic inference">i->{ return i;}</error>);
|
||||
call(<error descr="Cyclic inference">i->""</error>);
|
||||
call<error descr="'call(ReturnTypeCompatibility.I1<java.lang.Integer>)' in 'ReturnTypeCompatibility' cannot be applied to '(<lambda expression>)'">((int i)->{ return i;})</error>;
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
call((String i)->{ return i;});
|
||||
call(<error descr="Cyclic inference">i->{ return i;}</error>);
|
||||
call(<error descr="Cyclic inference">i->""</error>);
|
||||
call<error descr="'call(ReturnTypeCompatibility.I1<java.lang.Integer>)' in 'ReturnTypeCompatibility' cannot be applied to '(<lambda expression>)'">((int i)->{ return i;})</error>;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,13 +22,7 @@ import org.jetbrains.annotations.NonNls;
|
||||
* @author ven
|
||||
*/
|
||||
public class AnnotationsHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
@NonNls
|
||||
private static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/annotations";
|
||||
|
||||
private void doTest(boolean checkWarnings) {
|
||||
setLanguageLevel(LanguageLevel.JDK_1_7);
|
||||
doTest(BASE_PATH + "/" + getTestName(true) + ".java", checkWarnings, false);
|
||||
}
|
||||
@NonNls private static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/annotations";
|
||||
|
||||
public void testWrongPlace() { doTest(false); }
|
||||
public void testNotValueNameOmitted() { doTest(false); }
|
||||
@@ -49,5 +43,15 @@ public class AnnotationsHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
public void testInvalidPackageAnnotationTarget() { doTest(BASE_PATH + "/" + getTestName(true) + "/package-info.java", false, false); }
|
||||
public void testPackageAnnotationNotInPackageInfo() { doTest(BASE_PATH + "/" + getTestName(true) + "/notPackageInfo.java", false, false); }
|
||||
|
||||
//public void testTypeAnnotations() { doTest(false); } // todo[r.sh] make separate test with correct language level
|
||||
public void testTypeAnnotations() { doTest8(false); }
|
||||
|
||||
private void doTest(boolean checkWarnings) {
|
||||
setLanguageLevel(LanguageLevel.JDK_1_7);
|
||||
doTest(BASE_PATH + "/" + getTestName(true) + ".java", checkWarnings, false);
|
||||
}
|
||||
|
||||
private void doTest8(boolean checkWarnings) {
|
||||
setLanguageLevel(LanguageLevel.JDK_1_8);
|
||||
doTest(BASE_PATH + "/" + getTestName(true) + ".java", checkWarnings, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* Copyright 2000-2013 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.
|
||||
@@ -114,8 +114,8 @@ public class DataFlowInspectionTest extends LightCodeInsightFixtureTestCase {
|
||||
}
|
||||
|
||||
private void setupCustomAnnotations() {
|
||||
myFixture.addClass("package foo; public @interface Nullable {}");
|
||||
myFixture.addClass("package foo; public @interface NotNull {}");
|
||||
myFixture.addClass("package foo;\n\nimport java.lang.annotation.*;\n\n@Target({ElementType.TYPE_USE}) public @interface Nullable { }");
|
||||
myFixture.addClass("package foo;\n\nimport java.lang.annotation.*;\n\n@Target({ElementType.TYPE_USE}) public @interface NotNull { }");
|
||||
final NullableNotNullManager nnnManager = NullableNotNullManager.getInstance(getProject());
|
||||
nnnManager.setNotNulls("foo.NotNull");
|
||||
nnnManager.setNullables("foo.Nullable");
|
||||
@@ -140,7 +140,7 @@ public class DataFlowInspectionTest extends LightCodeInsightFixtureTestCase {
|
||||
}
|
||||
|
||||
public void testConstantDoubleComparisons() { doTest(); }
|
||||
|
||||
|
||||
public void testMutableNullableFieldsTreatment() { doTest(); }
|
||||
public void testMutableVolatileNullableFieldsTreatment() { doTest(); }
|
||||
public void testMutableNotAnnotatedFieldsTreatment() { doTest(); }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* Copyright 2000-2013 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.
|
||||
@@ -20,8 +20,8 @@ import com.intellij.codeInsight.completion.CompletionWeigher;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.PsiTypeLookupItem;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiImplUtil;
|
||||
import com.intellij.psi.impl.light.LightElement;
|
||||
import com.intellij.psi.impl.source.tree.java.PsiAnnotationImpl;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
@@ -98,7 +98,7 @@ public class GrKindWeigher extends CompletionWeigher {
|
||||
PsiElement annoParent = annotation.getParent();
|
||||
PsiElement owner = annoParent.getParent();
|
||||
String[] elementTypeFields = GrAnnotationImpl.getApplicableElementTypeFields(annoParent instanceof PsiModifierList ? owner : annoParent);
|
||||
if (PsiAnnotationImpl.isAnnotationApplicable(false, (PsiClass)o, elementTypeFields, position.getResolveScope())) {
|
||||
if (PsiImplUtil.isAnnotationApplicable((PsiClass)o, false, GrAnnotationImpl.translate(elementTypeFields))) {
|
||||
return NotQualifiedKind.restrictedClass;
|
||||
}
|
||||
}
|
||||
@@ -149,11 +149,11 @@ public class GrKindWeigher extends CompletionWeigher {
|
||||
final PsiClass containingClass = o.getContainingClass();
|
||||
return containingClass != null && TRASH_CLASSES.contains(containingClass.getQualifiedName());
|
||||
}
|
||||
|
||||
|
||||
private static boolean isAccessor(PsiMember member) {
|
||||
return member instanceof PsiMethod && (GroovyPropertyUtils.isSimplePropertyAccessor((PsiMethod)member) || "setProperty".equals(((PsiMethod)member).getName()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static boolean isQualifierClassMember(PsiMember member, PsiElement qualifier) {
|
||||
if (!(qualifier instanceof GrExpression)) return false;
|
||||
|
||||
@@ -17,13 +17,14 @@
|
||||
package org.jetbrains.plugins.groovy.lang.psi.impl.auxiliary.annotation;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiImplUtil;
|
||||
import com.intellij.psi.impl.light.LightClassReference;
|
||||
import com.intellij.psi.impl.source.tree.java.PsiAnnotationImpl;
|
||||
import com.intellij.psi.meta.PsiMetaData;
|
||||
import com.intellij.util.PairFunction;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -46,11 +47,15 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.GrStubElementBase;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.stubs.GrAnnotationStub;
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author: Dmitry.Krasilschikov
|
||||
* @date: 04.04.2007
|
||||
*/
|
||||
public class GrAnnotationImpl extends GrStubElementBase<GrAnnotationStub> implements GrAnnotation, StubBasedPsiElement<GrAnnotationStub> {
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.plugins.groovy.lang.psi.impl.auxiliary.annotation.GrAnnotationImpl");
|
||||
|
||||
private static final PairFunction<Project, String, PsiAnnotation> ANNOTATION_CREATOR = new PairFunction<Project, String, PsiAnnotation>() {
|
||||
public PsiAnnotation fun(Project project, String text) {
|
||||
return GroovyPsiElementFactory.getInstance(project).createAnnotationFromText(text);
|
||||
@@ -188,14 +193,23 @@ public class GrAnnotationImpl extends GrStubElementBase<GrAnnotationStub> implem
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static TargetType[] translate(@Nullable String... types) {
|
||||
if (types == null) return null;
|
||||
|
||||
List<TargetType> targets = ContainerUtil.newArrayListWithExpectedSize(types.length);
|
||||
for (String type : types) {
|
||||
try {
|
||||
targets.add(TargetType.valueOf(type));
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
LOG.error("Unknown target: " + type);
|
||||
}
|
||||
}
|
||||
return targets.toArray(new TargetType[targets.size()]);
|
||||
}
|
||||
|
||||
public static boolean isAnnotationApplicableTo(GrAnnotation annotation, boolean strict, String... elementTypeFields) {
|
||||
if (elementTypeFields == null) return true;
|
||||
GrCodeReferenceElement nameRef = annotation.getClassReference();
|
||||
PsiElement resolved = nameRef.resolve();
|
||||
if (resolved instanceof PsiClass && ((PsiClass)resolved).isAnnotationType()) {
|
||||
return PsiAnnotationImpl.isAnnotationApplicable(strict, (PsiClass)resolved, elementTypeFields, annotation.getResolveScope());
|
||||
}
|
||||
return !strict;
|
||||
return elementTypeFields == null || PsiImplUtil.isAnnotationApplicable(annotation, strict, translate(elementTypeFields));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user