예제 #1
0
 @Nullable
 public static PsiAnnotation getAnnotation(
     @NotNull PsiModifierListOwner field, @NotNull String annotationName) {
   final PsiModifierList modifierList = field.getModifierList();
   if (modifierList == null) return null;
   return modifierList.findAnnotation(annotationName);
 }
예제 #2
0
  /**
   * Returns a set of targets where the given annotation may be applied, or {@code null} when the
   * type is not a valid annotation.
   */
  @Nullable
  public static Set<TargetType> getAnnotationTargets(@NotNull PsiClass annotationType) {
    if (!annotationType.isAnnotationType()) return null;
    PsiModifierList modifierList = annotationType.getModifierList();
    if (modifierList == null) return null;
    PsiAnnotation target =
        modifierList.findAnnotation(CommonClassNames.JAVA_LANG_ANNOTATION_TARGET);
    if (target == null)
      return DEFAULT_TARGETS; // if omitted it is applicable to all but Java 8
                              // TYPE_USE/TYPE_PARAMETERS targets

    return extractRequiredAnnotationTargets(target.findAttributeValue(null));
  }
예제 #3
0
  public static boolean isAnnotatedCheckHierarchyWithCache(
      @NotNull PsiClass aClass, @NotNull String annotationFQN) {
    Map<String, PsiClass> classMap = getSuperClassesWithCache(aClass);

    for (PsiClass psiClass : classMap.values()) {
      PsiModifierList modifierList = psiClass.getModifierList();
      if (modifierList != null) {
        if (modifierList.findAnnotation(annotationFQN) != null) {
          return true;
        }
      }
    }

    return false;
  }
예제 #4
0
  @Override
  public void invoke(
      @NotNull Project project,
      @NotNull PsiFile file,
      @Nullable("is null when called from inspection") Editor editor,
      @NotNull PsiElement startElement,
      @NotNull PsiElement endElement) {
    final PsiModifierListOwner myModifierListOwner = (PsiModifierListOwner) startElement;

    final ExternalAnnotationsManager annotationsManager =
        ExternalAnnotationsManager.getInstance(project);
    final PsiModifierList modifierList = myModifierListOwner.getModifierList();
    LOG.assertTrue(modifierList != null);
    if (modifierList.findAnnotation(myAnnotation) != null) return;
    final ExternalAnnotationsManager.AnnotationPlace annotationAnnotationPlace =
        annotationsManager.chooseAnnotationsPlace(myModifierListOwner);
    if (annotationAnnotationPlace == ExternalAnnotationsManager.AnnotationPlace.NOWHERE) return;
    if (annotationAnnotationPlace == ExternalAnnotationsManager.AnnotationPlace.EXTERNAL) {
      for (String fqn : myAnnotationsToRemove) {
        annotationsManager.deannotate(myModifierListOwner, fqn);
      }
      annotationsManager.annotateExternally(myModifierListOwner, myAnnotation, file, myPairs);
    } else {
      final PsiFile containingFile = myModifierListOwner.getContainingFile();
      if (!CodeInsightUtilBase.preparePsiElementForWrite(containingFile)) return;
      for (String fqn : myAnnotationsToRemove) {
        PsiAnnotation annotation = AnnotationUtil.findAnnotation(myModifierListOwner, fqn);
        if (annotation != null) {
          annotation.delete();
        }
      }

      PsiAnnotation inserted = modifierList.addAnnotation(myAnnotation);
      for (PsiNameValuePair pair : myPairs) {
        inserted.setDeclaredAttributeValue(pair.getName(), pair.getValue());
      }
      JavaCodeStyleManager.getInstance(project).shortenClassReferences(inserted);
      if (containingFile != file) {
        UndoUtil.markPsiFileForUndo(file);
      }
    }
  }
  @Nullable
  private static RetentionPolicy getRetentionPolicy(PsiClass annotation) {
    PsiModifierList modifierList = annotation.getModifierList();
    if (modifierList != null) {
      PsiAnnotation retentionAnno =
          modifierList.findAnnotation(CommonClassNames.JAVA_LANG_ANNOTATION_RETENTION);
      if (retentionAnno == null) return RetentionPolicy.CLASS;

      PsiAnnotationMemberValue policyRef = PsiImplUtil.findAttributeValue(retentionAnno, null);
      if (policyRef instanceof PsiReference) {
        PsiElement field = ((PsiReference) policyRef).resolve();
        if (field instanceof PsiEnumConstant) {
          String name = ((PsiEnumConstant) field).getName();
          try {
            return RetentionPolicy.valueOf(name);
          } catch (Exception e) {
            LOG.warn("Unknown policy: " + name);
          }
        }
      }
    }

    return null;
  }
 public static boolean modifierListsAreEquivalent(
     @Nullable PsiModifierList list1, @Nullable PsiModifierList list2) {
   if (list1 == null) {
     return list2 == null;
   } else if (list2 == null) {
     return false;
   }
   final PsiAnnotation[] annotations = list1.getAnnotations();
   for (PsiAnnotation annotation : annotations) {
     final String qualifiedName = annotation.getQualifiedName();
     if (qualifiedName == null) {
       return false;
     }
     if (list2.findAnnotation(qualifiedName) == null) {
       return false;
     }
   }
   if (list1.hasModifierProperty(PsiModifier.ABSTRACT)
       && !list2.hasModifierProperty(PsiModifier.ABSTRACT)) {
     return false;
   }
   if (list1.hasModifierProperty(PsiModifier.FINAL)
       && !list2.hasModifierProperty(PsiModifier.FINAL)) {
     return false;
   }
   if (list1.hasModifierProperty(PsiModifier.NATIVE)
       && !list2.hasModifierProperty(PsiModifier.NATIVE)) {
     return false;
   }
   if (list1.hasModifierProperty(PsiModifier.PACKAGE_LOCAL)
       && !list2.hasModifierProperty(PsiModifier.PACKAGE_LOCAL)) {
     return false;
   }
   if (list1.hasModifierProperty(PsiModifier.PRIVATE)
       && !list2.hasModifierProperty(PsiModifier.PRIVATE)) {
     return false;
   }
   if (list1.hasModifierProperty(PsiModifier.PROTECTED)
       && !list2.hasModifierProperty(PsiModifier.PROTECTED)) {
     return false;
   }
   if (list1.hasModifierProperty(PsiModifier.PUBLIC)
       && !list2.hasModifierProperty(PsiModifier.PUBLIC)) {
     return false;
   }
   if (list1.hasModifierProperty(PsiModifier.STATIC)
       && !list2.hasModifierProperty(PsiModifier.STATIC)) {
     return false;
   }
   if (list1.hasModifierProperty(PsiModifier.STRICTFP)
       && !list2.hasModifierProperty(PsiModifier.STRICTFP)) {
     return false;
   }
   if (list1.hasModifierProperty(PsiModifier.SYNCHRONIZED)
       && !list2.hasModifierProperty(PsiModifier.SYNCHRONIZED)) {
     return false;
   }
   if (list1.hasModifierProperty(PsiModifier.TRANSIENT)
       && !list2.hasModifierProperty(PsiModifier.TRANSIENT)) {
     return false;
   }
   return !(list1.hasModifierProperty(PsiModifier.VOLATILE)
       && !list2.hasModifierProperty(PsiModifier.VOLATILE));
 }
예제 #7
0
 public static boolean isDeprecatedByAnnotation(@NotNull PsiModifierListOwner owner) {
   PsiModifierList modifierList = owner.getModifierList();
   return modifierList != null && modifierList.findAnnotation("java.lang.Deprecated") != null;
 }
  @Override
  public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) {
    if (!MinecraftSettings.Companion.getInstance().isShowEventListenerGutterIcons()) {
      return;
    }

    // Since we want to line up with the method declaration, not the annotation
    // declaration, we need to target identifiers, not just PsiMethods.
    if (!(element instanceof PsiIdentifier && (element.getParent() instanceof PsiMethod))) {
      return;
    }
    // The PsiIdentifier is going to be a method of course!
    PsiMethod method = (PsiMethod) element.getParent();
    if (method.hasModifierProperty(PsiModifier.ABSTRACT)) {
      // I don't think any implementation allows for abstract
      return;
    }
    PsiModifierList modifierList = method.getModifierList();
    Module module = ModuleUtilCore.findModuleForPsiElement(element);
    if (module == null) {
      return;
    }
    MinecraftModule instance = MinecraftModule.getInstance(module);
    if (instance == null) {
      return;
    }
    // Since each platform has their own valid listener annotations,
    // some platforms may have multiple allowed annotations for various cases
    final Collection<AbstractModuleType<?>> moduleTypes = instance.getTypes();
    boolean contains = false;
    for (AbstractModuleType<?> moduleType : moduleTypes) {
      final List<String> listenerAnnotations = moduleType.getListenerAnnotations();
      for (String listenerAnnotation : listenerAnnotations) {
        if (modifierList.findAnnotation(listenerAnnotation) != null) {
          contains = true;
          break;
        }
      }
    }
    if (!contains) {
      return;
    }

    final PsiParameter[] parameters = method.getParameterList().getParameters();
    if (parameters.length < 1) {
      return;
    }
    final PsiParameter eventParameter = parameters[0];
    if (eventParameter == null) {
      // Listeners must have at least a single parameter
      return;
    }
    // Get the type of the parameter so we can start resolving it
    PsiTypeElement psiEventElement = eventParameter.getTypeElement();
    if (psiEventElement == null) {
      return;
    }
    final PsiType type = psiEventElement.getType();
    // Validate that it is a class reference type, I don't know if this will work with
    // other JVM languages such as Kotlin or Scala, but it might!
    if (!(type instanceof PsiClassReferenceType)) {
      return;
    }
    // And again, make sure that we can at least resolve the type, otherwise it's not a valid
    // class reference.
    final PsiClass eventClass = ((PsiClassReferenceType) type).resolve();
    if (eventClass == null) {
      return;
    }

    if (instance.isEventClassValid(eventClass, method)) {
      return;
    }

    if (!instance.isStaticListenerSupported(eventClass, method)
        && method.hasModifierProperty(PsiModifier.STATIC)) {
      if (method.getNameIdentifier() != null) {
        holder.createErrorAnnotation(
            method.getNameIdentifier(), "Event listener method must not be static");
      }
    }

    if (!isSuperEventListenerAllowed(eventClass, method, instance)) {
      holder.createErrorAnnotation(
          eventParameter, instance.writeErrorMessageForEvent(eventClass, method));
    }
  }
  @Override
  public void collectMethods(
      @NotNull GrTypeDefinition typeDefinition, Collection<PsiMethod> collector) {
    if (typeDefinition.getName() == null) return;

    PsiModifierList modifierList = typeDefinition.getModifierList();
    if (modifierList == null) return;

    final PsiAnnotation tupleConstructor =
        modifierList.findAnnotation(GroovyCommonClassNames.GROOVY_TRANSFORM_TUPLE_CONSTRUCTOR);
    final boolean immutable =
        modifierList.findAnnotation(IMMUTABLE) != null
            || modifierList.findAnnotation(GroovyCommonClassNames.GROOVY_TRANSFORM_IMMUTABLE)
                != null;
    final PsiAnnotation canonical =
        modifierList.findAnnotation(GroovyCommonClassNames.GROOVY_TRANSFORM_CANONICAL);
    if (!immutable && canonical == null && tupleConstructor == null) {
      return;
    }

    if (tupleConstructor != null
        && typeDefinition.getCodeConstructors().length > 0
        && !PsiUtil.getAnnoAttributeValue(tupleConstructor, "force", false)) {
      return;
    }

    final GrLightMethodBuilder fieldsConstructor =
        new GrLightMethodBuilder(typeDefinition.getManager(), typeDefinition.getName());
    fieldsConstructor.setConstructor(true).setNavigationElement(typeDefinition);

    Set<String> excludes = new HashSet<String>();
    if (tupleConstructor != null) {
      for (String s : PsiUtil.getAnnoAttributeValue(tupleConstructor, "excludes", "").split(",")) {
        final String name = s.trim();
        if (StringUtil.isNotEmpty(name)) {
          excludes.add(name);
        }
      }
    }

    if (tupleConstructor != null) {
      final boolean superFields =
          PsiUtil.getAnnoAttributeValue(tupleConstructor, "includeSuperFields", false);
      final boolean superProperties =
          PsiUtil.getAnnoAttributeValue(tupleConstructor, "includeSuperProperties", false);
      if (superFields || superProperties) {
        addParametersForSuper(
            typeDefinition,
            fieldsConstructor,
            superFields,
            superProperties,
            new HashSet<PsiClass>(),
            excludes);
      }
    }

    addParameters(
        typeDefinition,
        fieldsConstructor,
        tupleConstructor == null
            || PsiUtil.getAnnoAttributeValue(tupleConstructor, "includeProperties", true),
        tupleConstructor != null
            ? PsiUtil.getAnnoAttributeValue(tupleConstructor, "includeFields", false)
            : canonical == null,
        !immutable,
        excludes);

    collector.add(fieldsConstructor.setContainingClass(typeDefinition));

    collector.add(
        new GrLightMethodBuilder(typeDefinition.getManager(), typeDefinition.getName())
            .addParameter("args", CommonClassNames.JAVA_UTIL_MAP, false)
            .setConstructor(true)
            .setContainingClass(typeDefinition));
  }
  public static boolean checkModifierProperty(
      @NotNull GrModifierList modifierList,
      @GrModifier.GrModifierConstant @NotNull String modifier) {
    final PsiElement owner = modifierList.getParent();
    if (owner instanceof GrVariableDeclaration
        && owner.getParent() instanceof GrTypeDefinitionBody) {
      PsiElement pParent = owner.getParent().getParent();
      if (!modifierList
          .hasExplicitVisibilityModifiers()) { // properties are backed by private fields
        if (!(pParent instanceof PsiClass) || !((PsiClass) pParent).isInterface()) {
          if (modifier.equals(GrModifier.PRIVATE)) return true;
          if (modifier.equals(GrModifier.PROTECTED)) return false;
          if (modifier.equals(GrModifier.PUBLIC)) return false;
        }
      }

      if (pParent instanceof PsiClass && ((PsiClass) pParent).isInterface()) {
        if (modifier.equals(GrModifier.STATIC)) return true;
        if (modifier.equals(GrModifier.FINAL)) return true;
      }
      if (pParent instanceof GrTypeDefinition) {
        PsiModifierList pModifierList = ((GrTypeDefinition) pParent).getModifierList();
        if (pModifierList != null
            && pModifierList.findAnnotation(ConstructorAnnotationsProcessor.IMMUTABLE) != null) {
          if (modifier.equals(GrModifier.FINAL)) return true;
        }
      }
    }

    // top level classes cannot have private and protected modifiers
    if (owner instanceof GrTypeDefinition
        && ((GrTypeDefinition) owner).getContainingClass() == null) {
      if (modifier.equals(PROTECTED) || modifier.equals(PRIVATE)) return false;
      if (modifier.equals(PACKAGE_LOCAL))
        return modifierList.hasExplicitModifier(PRIVATE)
            || modifierList.hasExplicitModifier(PROTECTED);
    }

    if (modifierList.hasExplicitModifier(modifier)) {
      return true;
    }

    if (modifier.equals(GrModifier.PUBLIC)) {
      if (owner instanceof GrPackageDefinition) return false;
      if (owner instanceof GrVariableDeclaration
              && !(owner.getParent() instanceof GrTypeDefinitionBody)
          || owner instanceof GrVariable) {
        return false;
      }
      // groovy type definitions and methods are public by default
      return !modifierList.hasExplicitModifier(GrModifier.PRIVATE)
          && !modifierList.hasExplicitModifier(GrModifier.PROTECTED);
    }

    if (owner instanceof GrTypeDefinition) {
      if (modifier.equals(GrModifier.STATIC)) {
        final PsiClass containingClass = ((GrTypeDefinition) owner).getContainingClass();
        return containingClass != null && containingClass.isInterface();
      }
      if (modifier.equals(GrModifier.ABSTRACT)) {
        return ((GrTypeDefinition) owner).isInterface();
      }
    }

    return false;
  }