Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 320441 - apt (Java 6 Annotations) sorts methods in source code before passing them to an annotation processor - different behaviour from Java 6 javac
Summary: apt (Java 6 Annotations) sorts methods in source code before passing them to ...
Status: CLOSED DUPLICATE of bug 300408
Alias: None
Product: JDT
Classification: Eclipse Project
Component: APT (show other bugs)
Version: 3.7   Edit
Hardware: PC Windows 7
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Generic inbox for the JDT-APT component CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-07-20 16:46 EDT by Dave Boden CLA
Modified: 2010-07-21 02:59 EDT (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Dave Boden CLA 2010-07-20 16:46:47 EDT
Build Identifier: 20100617-1415 (Helios)

In an AnnotationProcessor, you can take a TypeElement (representing a Class) and use a SimpleElementVisitor6 or ElementScanner6 to "visit" each of the fields and methods in the class.

The order in which the fields and methods are visited is defined by the way that the TypeElement is constructed.

In javac, care is taken to ensure that the object tree is constructed in the exact order specified in the source .java file. This allows annotation processor writers to generate class constructors and other output artifacts using the natural ordering that the author has used in the input .java file.

The Eclipse apt parser behaves differently. It sorts the methods when constructing the object tree. This results in different behaviour when scanning / visiting the tree and results in a different output class file if you rely on the natural ordering of the input.

The sort is carried out in:

org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding
public MethodBinding[] methods()

	// lazily sort methods
	if ((this.tagBits & TagBits.AreMethodsSorted) == 0) {
		int length = this.methods.length;
		if (length > 1)
			ReferenceBinding.sortMethods(this.methods, 0, length);
		this.tagBits |= TagBits.AreMethodsSorted;
	}

Reproducible: Always

Steps to Reproduce:
This project uses an annotation processor that relies on the natural ordering of methods in the .java input:

http://immutablebean.googlecode.com/svn/ImmutableBeanExample/

This project builds successfully under Maven.

Configuring the annotation processor to run under Eclipse results in:

Input ordering:
	@BusinessKey String getIdentifier();
	@BusinessKey int getVersion();
	Date getCreationDate();
	BigDecimal getPrice();
	BigDecimal getQuantity();
	List<String> getDescriptions();
	@NotInToString boolean isActive();

Output ordering:
    private java.util.Date creationDate;
    private java.util.List<java.lang.String> descriptions;
    private java.lang.String identifier;
    private java.math.BigDecimal price;
    private java.math.BigDecimal quantity;
    private int version;
    private boolean active;


WORKAROUND - is to build under Maven (javac) and not configure Eclipse to do the annotation processing. You can configure Maven to perform the generate-sources part of the build whenever a file is saved so you can delegate these tasks to Maven.
Comment 1 Dave Boden CLA 2010-07-20 16:50:35 EDT
The link to "apt" is:
org.eclipse.jdt.internal.compiler.apt.model.TypeElementImpl
public List<? extends Element> getEnclosedElements()

This is the method used by Element Visitors and Scanners. It iterates through:

ReferenceBinding binding
binding.methods() //This returns the sorted list of methods. In javac, it isn't sorted
Comment 2 Walter Harley CLA 2010-07-21 02:59:04 EDT
Yes. Not sure what to do about this...  it was a late change to the JSR269 spec based (I believe) on how javac happens to do it, and it's not at all clear how to make the Eclipse compiler provide this info.

*** This bug has been marked as a duplicate of bug 300408 ***