Compilation de code Java

Les plug-ins de JDT comprennent un compilateur Java incrémentiel et par lots qui permet de compiler des fichiers .class Java à partir d'un code source. Le compilateur ne fournit pas d'API directe. Il est installé comme compilateur dans les projets Java. La compilation est déclenchée au moyen des mécanismes de génération standard de la plateforme.

Le mécanisme de compilation de la plateforme est détaillé à la rubrique Compilateurs de projet incrémentaux .

Compilation du code

Grâce à l'API de compilation, vous pouvez compiler les fichiers source Java d'un projet par programme.

   IProject myProject;
   IProgressMonitor myProgressMonitor;
   myProject.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, myProgressMonitor);

Pour un projet Java, cette instruction appelle le compilateur de projet incrémentiel Java (avec les autres compilateurs de projet incrémentaux qui ont été ajoutés à la spécification de compilation du projet). Les fichiers .class générés sont enregistrés dans le dossier de sortie indiqué. Les fichiers de ressources supplémentaires sont également copiés dans le dossier de sortie. 

Dans le cas d'une compilation par lots complète, tous les fichiers .class du dossier de sortie peuvent être vérifiés pour s'assurer qu'aucun fichier périmé ne sera trouvé. Cette opération est contrôlée par une option du compilateur de l'API principale de JDT(CORE_JAVA_BUILD_CLEAN_OUTPUT_FOLDER).  Par défaut, cette option vide les dossiers de sortie.Sauf si l'option est réinitialisée, vous devez veiller à placer tous les fichiers .class pour lesquels vous ne disposez pas des fichiers source correspondants dans un dossier de fichiers classe distinct sur le chemin de classe et non dans le dossier de sortie.

Les compilateurs incrémentaux et par lots peuvent être configurés avec d'autres options qui contrôlent les ressources copiées dans le dossier de sortie.L'exemple suivant montre comment configurer un filtre de ressources de sorte que les fichiers se terminant par '.ignore' et les dossiers nommés 'META-INF' ne soient pas copiés dans le dossier de sortie :

   Hashtable options = JavaCore.getOptions();
   options.put(JavaCore.CORE_JAVA_BUILD_RESOURCE_COPY_FILTER, "*.ignore,META-INF/");
   JavaCore.setOptions(options);

Les noms des fichiers sont filtrés s'ils correspondent à l'un des modèles spécifiés. Des dossiers entiers sont filtrés si leur nom correspond à l'un des noms de dossier spécifié se terminant par un séparateur de chemin.

Vous pouvez également configurer les compilateurs incrémentaux et de lots pour ne générer qu'une seule erreur lorsque le fichier .classpath contient des erreurs. Cette option est définie par défaut et élimine de nombreuses erreurs. Pour obtenir la liste complète des options relatives au compilateur et leurs valeurs par défaut, reportez-vous à la rubrique Options du compilateur de l'API principale de JDT.

La compilateur peut également être configuré à l'aide des optionsJavaCore.  Vous pouvez par exemple définir la gravité devant être utilisée pour les différents types de problèmes rencontrés au cours de la compilation.  Pour obtenir la liste complète des options relatives au compilateur et leurs valeurs par défaut, reportez-vous à la rubrique Options du compilateur de l'API principale de JDT.

Lors de la configuration par programme des options du compilateur, vous devez déterminer la portée de l'option.  Par exemple, la configuration d'un filtre de ressources peut s'appliquer uniquement à un projet particulier.L'exemple suivant configure le même filtre de ressources que celui présenté précédemment, mais ne le définit que pour un projet individuel.

   
   Hashtable options = myProject.getOptions(false);  // obtention des options configurées dans ce projet uniquement
   options.put(JavaCore.CORE_JAVA_BUILD_RESOURCE_COPY_FILTER, "*.ignore,META-INF/");
   myProject.setOptions(options);

Utilisation du compilateur par lots

Recherche du compilateur par lots

La classe du compilateur par lots se situe dans les classes internes du plug-in JDT/Core. Elle réside donc dans le fichierjdtcore.jar du répertoire plugins/org.eclipse.jdt.core. Le nom de la classe est le suivant : org.eclipse.jdt.internal.compiler.batch.Main.

Exécution du compilateur par lots

Quelles sont les options disponibles ?

Les options suggérées sont représentées avec un arrière-plan de couleur orange.

Nom Syntaxe
Options de chemin de classe
-bootclasspath <dir 1>;<dir 2>;...;<dir P> Liste des répertoires ou des fichiers JAR utilisés pour amorcer les fichiers de classe utilisés par le compilateur. Par défaut, les bibliothèques de la machine virtuelle en cours d'exécution sont utilisées. Les entrées sont séparées par le séparateur de chemin de plateforme.
-cp
-classpath <dir 1>;<dir 2>;...;<dir P>
Liste des répertoires ou des fichiers JAR utilisés pour compiler les fichiers sources. La valeur par défaut est la valeur de la propriété "java.class.path". Les entrées sont séparées par le séparateur de chemin de plateforme.
-extdirs <dir 1>;<dir 2>;...;<dir P> Liste des répertoires utilisés pour définir l'emplacement des fichiers d'extension zip/jar. Les entrées sont séparées par le séparateur de chemin de plateforme.
-sourcepath <dir 1>;<dir 2>;...;<dir P> Liste des répertoires utilisés pour définir les fichiers sources. Les entrées sont séparées par le séparateur de chemin de plateforme.
-d <dir 1>|none Permet de définir dans quel répertoire les fichiers .class générés doivent être vidés. En cas d'oubli, aucune structure de répertoire de package n'est créée.
Si vous ne souhaitez pas générer de fichiers .class, utilisez -d none.
-encoding <encoding name> Définit le format d'encodage de la source par défaut (il est également possible de définir un encodage personnalisé fichier par fichier en ajoutant à chaque nom de dossier/fichier source le suffixe [encoding <encoding name>]).
Options de conformité
-target 1.1|1.2|1.3|1.4|1.5|5|5.0 Définit le paramètre cible du fichier .class. Les valeurs possibles sont les suivantes :
  • 1.1 (version majeure : 45 mineure : 3)
  • 1.2 (version majeure : 46 mineure : 0)
  • 1.3 (version majeure : 47 mineure : 0)
  • 1.4 (version majeure : 48 mineure : 0)
  • 1.5, 5 ou 5.0 (version majeure : 49 mineure : 0)
La valeurs par défaut sont :
  • 1.1 en mode -1.3
  • 1.2 en mode -1.4
  • 1.5 en mode -1.5
-1.3 Définit le niveau de conformité sur 1.3. Implicitement -source 1.3 -cible 1.1.
-1.4 Définit le niveau de conformité sur 1.4 (par défaut). Implicitement -source 1.3 -cible 1.2.
-1.5 Définit le niveau de conformité sur 1.5. Implicitement -source 1.5 -cible 1.5.
-source 1.3|1.4|1.5|5|5.0 Permet d'activer le niveau de source du compilateur.
Les valeurs possibles sont les suivantes :
  • 1.3
  • 1.4
  • 1.5, 5 ou 5.0
La valeurs par défaut sont :
  • 1.3 en mode -1.3
  • 1.4 en mode -1.4
  • 1.5 en mode -1.5
Dans 1.4, assert est considéré comme un mot clé. Dans 1.5, enum et assert sont considérés comme un mot clé.
Options d'avertissement
-warn:
allDeprecation
allJavadoc
assertIdentifier
boxing
charConcat
conditionAssign
constructorName
dep-ann
deprecation
emptyBlock
enumSwitch
fieldHiding
finalBound
finally
hiding
incomplete-switch
indirectStatic
intfAnnotation
intfNonInherited
javadoc
localHiding
maskedCatchBlocks
nls
noEffectAssign
null
over-ann
pkgDefaultMethod
semicolon
serial
specialParamHiding
static-access
staticReceiver
suppress
synthetic-access
syntheticAccess
tasks(<task1>|...|<taskN>)
typeHiding
décochée
unnecessaryElse
unqualified-field-access
unqualifiedField
uselessTypeCheck
unused
unusedArgument
unusedImport
unusedLocal
unusedPrivate
unusedThrown
varargsCast
warningToken
Définit le niveau d'avertissement.
Par exemple : -warn:unusedLocals,deprecation

Les paramètres par défaut sont indiqués en rouge.

    -warn:<avertissements séparés par ,>    active exactement les avertissements répertoriés
    -warn:+<avertissements séparés par ,>   active des avertissements supplémentaires
    -warn:-<avertissements séparés par ,>   désactive certains avertissements en particulier
allDeprecation obsolescence même au sein du code obsolète
allJavadoc Javadoc invalide ou manquant
assertIdentifier occurrence de assert utilisé comme un identifiant
boxing conversion autoboxing
charConcat lorsqu'un tableau de caractères est utilisé dans une concaténation de chaînes sans être explicitement converti en une chaîne
conditionAssign affectation booléenne accidentelle possible
constructorName méthode et nom du constructeur
dep-ann annotation @obsolète manquante
deprecation utilisation de type obsolète ou de membre hors du code obsolète
emptyBlock bloc vide non renseigné
enumSwitch,
incomplete-switch
Commutateur d'énumération incomplet
fieldHiding zone masquant une autre variable
finalBound paramètre de type et association finale
finally bloc ne se terminant pas normalement
hiding macro pour fieldHiding, localHiding, typeHiding et maskedCatchBlock
indirectStatic référence indirecte à un membre statique
intfAnnotation type d'annotation utilisé comme super interface
intfNonInherited compatibilité de méthode non héritée d'interface
javadoc javadoc invalide
localHiding variable locale masquant une autre variable
maskedCatchBlocks bloc catch masqué
nls libellés de chaîne non-nls (manque de balises //$NON-NLS-<n>)
noEffectAssign pour une affectation sans effet
null contrôle null manquant ou redondant
over-ann annotation @Substitution manquante
pkgDefaultMethod tentative de substitution de la méthode de package par défaut
serial serialVersionUID manquante
semicolon point-virgule inutile ou instruction vide
specialParamHiding paramètre constructeur ou setter masquant une autre zone
static-access macro pour indirectStatic et staticReceiver
staticReceiver si un récepteur non statique est utilisé pour obtenir un champ statique ou appeler une méthode statique
suppress active @SuppressWarnings
syntheticAccess,
synthetic-access
lorsqu'un accès synthétique est réalisé pour innerclass
tasks active le support des balises de tâches du code source
typeHiding paramètre de type masquant un autre type
décochée opération de type décochée
unnecessaryElse clause else inutile
unqualified-field-access,
unqualifiedField
accès non qualifié à une zone
unused macro pour unusedArgument, unusedImport, unusedLocal, unusedPrivate et unusedThrown
unusedArgument argument de méthode inutilisé
unusedImport référence d'importation inutilisée
unusedLocal variable locale inutilisée
unusedPrivate déclaration de membre privé non-utilisé
unusedThrown exception émise déclarée et non-utilisée
uselessTypeCheck transtypage/instance de l'opération non requis
varargsCast l'argument varargs requiert un transtypage explicite
warningToken jeton d'avertissement non traité dans @SuppressWarningsb

-nowarn Pas d'avertissement (équivalent de -warn:none)
-deprecation Equivalent de -warn:deprecation.
Options de débogage
-g[:none|:lines,vars,source] Définit le niveau des attributs de débogage
-g Toutes les infos de débogage (équivalent de -g:lines,vars,source)
-g:none Aucune information de débogage
-g:[lines,vars,source] Informations de débogage sélectives
-preserveAllLocals Demande explicitement au compilateur de préserver toutes les variables locales (à des fins de débogage). En cas d'oubli, le compilateur supprime les variables locales inutilisées.
Options avancées
@<file> Arguments de ligne de commande de type lecture provenant du fichier
-maxProblems <n> Nombre maximal de problèmes par unité de compilation (100, par défaut)
-log <filename> Définit un fichier journal dans lequel sont vidées toutes les sorties du compilateur. Ceci s'avère particulièrement utile si vous souhaitez déboguer le compilateur par lots ou récupérer un fichier contenant toutes les erreurs et tous les avertissements ayant pour origine une compilation par lots. Si l'extension est du type .xml, le journal généré sera un fichier xml.
-proceedOnError Poursuit la compilation en cas d'erreur, en vidant les fichiers de classe comportant des méthodes ou des types posant des problèmes. Cette procédure est recommandée uniquement si vous souhaitez pouvoir exécuter votre application même si des erreurs persistent.
-verbose Imprime les unités de compilation accédées/traitées dans la console ou le fichier journal si défini.
-referenceInfo Traite les informations de référence. Utile uniquement en cas de connexion au compilateur. Dans le cas contraire, les informations de référence ne sont d'aucune utilité.
-progress Affiche l'avancement (uniquement en mode -log)
-time Affiche les informations relatives à la vitesse
-noExit Ne pas appeler System.exit(n) au terme de la compilation (n=0 en l'absence d'erreur)
-repeat <n> Répète le processus de compilation <n> fois (analyse des performances).
-inlineJSR Intègre le bytecode JSR (implicite si cible >= 1.5)
-enableJavadoc Prend en compte les références contenues dans le javadoc
Options d'aide
-? -help Affiche le message d'aide
-v -version Affiche le numéro de version du compilateur. Cette information est particulièrement utile pour signaler un bogue.
-showversion Affiche le numéro de version du compilateur et poursuit. Cette information est particulièrement utile pour signaler un bogue.

Exemples

d:\temp -classpath rt.jar -time -g -d d:/tmp Compile tous les fichiers sources dans d:\temp et ses sous-dossiers. Le chemin de classe est tout simplement rt.jar. Il génère tous les attributs de débogage et tous les fichiers .class générés sont vidés dans d:\tmp. La vitesse du compilateur est affichée une fois le processus par lots achevé.
d:\temp\Test.java -classpath d:\temp;rt.jar -g:none Compile uniquement Test.java et récupère tout fichier dépendant dans d:\temp. Le chemin de classe est rt.jar et d:\temp, ce qui signifie que toutes les classes nécessaires sont recherchées initialement dans d:\temp, puis dans rt.jar. Ne génère aucun attribut de débogage et tous les fichiers .class sont vidés dans d:\tmp.

Utilisation de l'adaptateur Ant javac

Vous pouvez utiliser le compilateur Eclipse dans un script Ant utilisant l'adaptateur javac. Pour ce faire, il suffit de définir la propriété build.compiler dans votre script. En voici un petit exemple.
<?xml version="1.0" encoding="UTF-8" ?>
<project name="compile" default="main" basedir="../.">

	<property name="build.compiler" value="org.eclipse.jdt.core.JDTCompilerAdapter"/>

	<property name="root" value="${basedir}/src"/>

	<property name="destdir" value="d:/temp/bin" />

	<target name="main">
		<javac srcdir="${root}" destdir="${destdir}" debug="on" nowarn="on" extdirs="d:/extdirs" source="1.4">
		    <classpath>
		      <pathelement location="${basedir}/../org.eclipse.jdt.core/bin"/>
		    </classpath>
		</javac>		
	</target>
</project>
La syntaxe utilisée pour la tâche Ant javac se trouve dans la documentation sur les tâches Ant javac. L'adaptateur actuel prend en charge la tâche Ant Javac, des versions 1.4.1 à 1.6.5.

Si vous utilisez une version supérieure à la version 1.5.0, vous pouvez utiliser l'élément d'argument de compilateur intégré pour définir des options propres au compilateur.

...
		<javac srcdir="${root}" destdir="${destdir}" debug="on" nowarn="on" extdirs="d:/extdirs" source="1.4">
    		    <classpath>
      		      <pathelement location="${basedir}/../org.eclipse.jdt.core/bin"/>
    		    </classpath>
    <compilerarg compiler="org.eclipse.jdt.core.JDTCompilerAdapter" line="-1.5 -warn:+boxing"/>
</javac>		
...

Afin d'éviter d'obtenir des scripts dépendant du compilateur, il est recommandé d'utiliser l'argument du compilateur défini sur org.eclipse.jdt.core.JDTCompilerAdapter. Si cet argument n'est pas défini, le script ne peut être utilisé qu'avec le compilateur Eclipse. S'il est défini, l'argument de compilateur imbriqué est ignoré si le nom est différent du nom de compilateur indiqué dans la propriété build.compiler.

Identification des incidents

L'API principale (core) du JDT définit un marqueur spécialisé (type "org.eclipse.jdt.core.problem") pour indiquer les incidents de compilation. Pour découvrir par programme les incidents détectés par le compilateur, vous devez utiliser le protocole de marqueurs standard de la plateforme. Pour plus d'informations sur l'utilisation des marqueurs, reportez-vous à la rubrique Marqueurs de ressources.

Le fragment de code suivant identifie tous les marqueurs Java problématiques dans une unité de compilation.

   public IMarker[] findJavaProblemMarkers(ICompilationUnit cu) 
      throws CoreException {
      IResource javaSourceFile = cu.getUnderlyingResource();
      IMarker[] markers = 
         javaSourceFile.findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER,
            true, IResource.DEPTH_INFINITE);
   }

Les marqueurs d'incidents Java sont gérés par le compilateur de projet Java. Ils sont supprimés automatiquement à mesure que les incidents sont résolus et que la source Java est recompilée.

La valeur de l'ID de l'incident est définie par l'une des constantes indiquées dans IProblem . L'ID de l'incident est fiable mais le message est traduit et peut par conséquent changer selon l'environnement local par défaut. La description des constantes définies dans IProblem est explicite.

Une implémentation d' IProblemRequestor doit être définie pour regrouper les incidents détectés lors d'une opération Java. Les copies de travail peuvent être adaptées à la détection des incidents si un élément IProblemRequestor a été fourni pour leur création. Pour ce faire, vous pouvez utiliser la méthode reconcile. Exemple :

  ICompilationUnit unit = ..; // obtention d'une unité de compilation
			
  // création d'un demandeur pour le regroupement des incidents détectés
  IProblemRequestor problemRequestor = new IProblemRequestor() {
    public void acceptProblem(IProblem problem) {
      System.out.println(problem.getID() + ": " + problem.getMessage());
    }
    public void beginReporting() {}
    public void endReporting() {}
    public boolean isActive() {	return true; } // détecte les incidents si actif
  };
    
  // utilisation de la copie de travail pour conserver la source contenant l'erreur
  ICompilationUnit workingCopy = unit.getWorkingCopy(new WorkingCopyOwner() {}, problemRequestor, null);
  ((IOpenable)workingCopy).getBuffer().setContents("public class X extends Zork {}");

  // déclenchement de la réconciliation
  workingCopy.reconcile(NO_AST, true, null, null);
Vous pouvez ajouter une opération sur les incidents détectés dans la méthode acceptProblem(IProblem). Dans cet exemple, l'incident détecté est le suivant : Zork ne peut pas être résolu ou n'est pas une superclasse valide et son ID est IProblem.SuperclassNotFound.