Skip to content

Annotation processing with incremental compiler

homedirectory edited this page Jul 18, 2023 · 4 revisions

Annotation processing with incremental compiler

Abstract

This document describes the details of annotation processing performed by the incremental compiler of Eclipse. In order to be able to take advantage of incremental compilation, the annotation processing algorithm differs slightly from the standard definition.

Abbreviations

  • APT - Annotation Processing Tool

High-level overview of the incremental compilation process with annotation processing enabled:

  1. Process and compile input sources.
  2. Process and compile generated sources.
  3. Process and compile affected sources.

Step 3 is of particular interest, since from it stems the non-standard behaviour.

Standard behaviour of APT, that is, with standard Java compiler, is to run steps 1 & 2 only. Pseudocode of the whole APT run follows:

function process(inputs) {
    roundInputs = inputs
    do {
        generated = doRound(roundInputs);
        compile(roundInputs);
        roundInputs = generated
    } while (roundInputs not empty);
    
    // run last round with empty inputs
    doRound([]);
}

Using a standard compiler function process() would be called only once. Upon exiting the annotation processor instance would be destroyed.

Eclipse incremental compiler, on the other hand, handles this is in a more advanced way:

function eclipseProcess(inputs) {
    do {
        affected = [];
        generated = process(inputs + affected);
        if isStructuralChange(inputs)
            affected += findAffected(inputs)
        if isStructuralChange(generated)
            affected += findAffected(generated)
    } while (affected not empty);
}

Effectively, the standard process() routine might be repeated multiple times, depending on the number of affected sources found. Therefore, there might be multiple "last rounds", seemingly confusing at first sight, since it goes against the documentation of standard annotation processing API. Also, between calls to process() the annotation processor instance is never destroyed and is initialized only once - before calling eclipseProcess().

In the simplest case, where no structural changes were detected, eclipseProcess() is equivalent to process().

File events handling

The following describes the initial set of processing inputs given the occurence of an event applicable to a Java source file.

Such events include the following:

  • Rename/Move: file was renamed or moved to another location.
  • Delete: file was deleted.
  • Content change: file was changed.
  • New: file was created.

Language used:

  • source: target source file to which the event applies.
  • affected: set of sources affected by source.
  • inputs: set of initial inputs of an annotation processor.

Events and their handling:

  • Rename/Move: inputs = source + affected
  • Delete: inputs = affected
  • Content change: inputs = source
  • New: inputs = source
Clone this wiki locally