Comment vérifier si le package existe depuis le processeur d’annotation (au moment de la compilation)?

Je construis un processeur d’annotation pour Android (pour des raisons d’explications futures, appelons-le TestProcessor ).

Il est prévu que le processeur fonctionne dans deux modes:


Mode 2 ne doit être sélectionné que si le package supplémentaire (facultatif) existe dans l’environnement pour lequel le processeur génère du code.

Existe-t-il un moyen de savoir dans la méthode de process du processeur d’annotation si le package facultatif existe?


EDIT 1:

Petite précision sur le “paquet (optionnel)”. Par paquet supplémentaire, j’entends un paquetage java qui peut, mais ne doit pas nécessairement exister dans le projet (utiliser le processeur). Le package facultatif peut par exemple représenter le contenu d’une bibliothèque externe. La bibliothèque externe peut mais ne doit pas nécessairement être incluse dans le projet.

Laissez-moi juste faire un petit exemple:

  • Supposons que nous ayons un exemple de projet (un module).
  • Sample utilise mon TestProcessor .
  • Prenons Picasso Square's comme exemple de bibliothèque externe
  • Si Sample HAS Square's Picasso Square's partie de ses dépendances, TestProcessor fonctionne en Mode 2 et génère les codes A et B En d’autres termes: si vous pouvez utiliser les classes de com.square.picasso (dans Sample ) sans aucun problème, le processeur doit alors fonctionner en Mode 2 .
  • S’il n’y a pas Sample's dépendances Picasso Square's dans Sample's , TestProcessor fonctionne en Mode 1 et génère uniquement le code A

EDIT 2:

J’ai pensé à deux solutions de contournement pour ce problème:

  1. Utilisation de deux types d’annotations pour deux Modes processor (exemple: @DoStuffModeOne , @DoStuffModeTwo )
  2. Utilisation d’un second type d’annotation (à utiliser par exemple sur l’ Application ) qui déclenche l’utilisation du Mode 2 (exemple: @TriggerModeTwo )

Pour mon cas, la deuxième solution de contournement est beaucoup plus préférable, mais elle est encore bien pire que si le TestProcessor lui-même pouvait décider du Mode à choisir.

Vous pouvez faire une vérification pour l’une des classes ButterKnife dans le classpath de l’application. Exécutez ensuite votre logique en fonction du résultat de la vérification.

 Class butterKnifeClass = null; try { butterKnifeClass = Class.forName("butterknife.ButterKnife"); } catch (ClassNotFoundException e) { // no butterknife present } if (butterKnifeClass != null) { // blah... stuff with butterknife } 

Vous pouvez utiliser ce code pour savoir si une classe est présente dans l’environnement de traitement des annotations.

 TypeElement typeElement = processingEnvironment.getElementUtils(). getTypeElement("com.squareup.picasso.Picasso"); 

Je n’ai pas réussi à utiliser la méthode Elements.getPackageElement() , car elle renvoyait avec succès des packages inexistants (du moins sous Eclipse) et l’exécution de la méthode PackageElement.getEnclosedElements() sur des packages ainsi créés était vide, même pour les non- PackageElement.getEnclosedElements() paquets vides. Je vous suggèrerais de choisir une classe spécifique dans votre paquet d’intérêt, comme dans mon exemple précédent, car elle fonctionnait comme prévu pour les éléments de type existants et renvoyait la valeur null pour les types non existants.

Actuellement, je n’ai pas trouvé de méthode basée sur l’API Annotation Processing pour décider si l’élément de type ainsi trouvé est basé sur un fichier de code source figurant sur le chemin source de votre projet ou sur un fichier de classe binary figurant sur le chemin de classe de compilation. Il pourrait y avoir une méthode pour cela avec processingEnvironment.getFiler().getResource(StandardLocation.SOURCE_PATH, ...) mais, malheureusement, n’est pas portable, car StandardLocation.SOURCE_PATH n’est pas pris en charge dans Eclipse.

J’espère que ça aide.

En plus de la solution proposée par JBirdVegas; Cette fonction peut être utilisée pour vérifier si un package existe dans les bibliothèques externes au moment de l’exécution.

 public static boolean packageExists(Ssortingng packagePath) { return Thread.currentThread().getContextClassLoader().getResource(packagePath) != null; } 

Utilisation:

 packageExists("apackage/innerpackage")