blob: ace386f43b4e500a919795f3f4a67c18927f087e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007 BEA Systems, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* wharley@bea.com - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.compiler.apt.tests.processors.elementutils;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.Elements;
import org.eclipse.jdt.compiler.apt.tests.processors.base.BaseProcessor;
/**
* A processor that exercises the methods on the Elements utility. To enable this processor, add
* -Aorg.eclipse.jdt.compiler.apt.tests.processors.elementutils.ElementUtilsProc to the command line.
* @since 3.3
*/
@SupportedAnnotationTypes("*")
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class ElementUtilsProc extends BaseProcessor
{
// Initialized in collectElements()
private TypeElement _elementF;
private TypeElement _elementFChild;
private TypeElement _elementFEnum;
private TypeElement _elementG;
private TypeElement _elementH;
private TypeElement _elementJ;
private TypeElement _elementAnnoX;
private ExecutableElement _annoXValue;
private TypeElement _elementAnnoY;
private ExecutableElement _annoYValue;
// Always return false from this processor, because it supports "*".
// The return value does not signify success or failure!
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv)
{
if (roundEnv.processingOver()) {
// We're not interested in the postprocessing round.
return false;
}
Map<String, String> options = processingEnv.getOptions();
if (!options.containsKey(this.getClass().getName())) {
// Disable this processor unless we are intentionally performing the test.
return false;
}
if (!collectElements()) {
return false;
}
if (!examineGetAllAnnotations()) {
return false;
}
if (!examineGetAllMembers()) {
return false;
}
if (!examineIsDeprecated()) {
return false;
}
if (!examineBinaryName()) {
return false;
}
if (!examineGetDocComment()) {
return false;
}
if (!examineHidesField()) {
return false;
}
if (!examineHidesClass()) {
return false;
}
if (!examineHidesMethod()) {
return false;
}
if (!examineOverrides()) {
return false;
}
reportSuccess();
return false;
}
/**
* Collect some elements that will be reused in various tests
* @return true if successful
*/
private boolean collectElements()
{
_elementF = _elementUtils.getTypeElement("targets.model.pc.F");
if (_elementF == null || _elementF.getKind() != ElementKind.CLASS) {
reportError("element F was not found or was not a class");
return false;
}
_elementFChild = _elementUtils.getTypeElement("targets.model.pc.F.FChild");
if (_elementFChild == null || _elementFChild.getKind() != ElementKind.CLASS) {
reportError("element FChild was not found or was not a class");
return false;
}
_elementFEnum = _elementUtils.getTypeElement("targets.model.pc.F.FEnum");
if (_elementFEnum == null || _elementFEnum.getKind() != ElementKind.ENUM) {
reportError("enum F.FEnum was not found or was not an enum");
return false;
}
_elementG = _elementUtils.getTypeElement("targets.model.pc.G");
if (_elementG == null || _elementG.getKind() != ElementKind.CLASS) {
reportError("element G was not found or was not a class");
return false;
}
_elementH = _elementUtils.getTypeElement("targets.model.pc.H");
if (_elementH == null || _elementH.getKind() != ElementKind.CLASS) {
reportError("element H was not found or was not a class");
return false;
}
_elementJ = _elementUtils.getTypeElement("targets.model.pc.J");
if (_elementJ == null || _elementJ.getKind() != ElementKind.CLASS) {
reportError("element J was not found or was not a class");
return false;
}
_elementAnnoX = _elementUtils.getTypeElement("targets.model.pc.AnnoX");
if (null == _elementAnnoX || _elementAnnoX.getKind() != ElementKind.ANNOTATION_TYPE) {
reportError("annotation type annoX was not found or was not an annotation");
return false;
}
for (ExecutableElement method : ElementFilter.methodsIn(_elementAnnoX.getEnclosedElements())) {
if ("value".equals(method.getSimpleName().toString())) {
_annoXValue = method;
}
}
if (null == _annoXValue) {
reportError("Could not find value() method in annotation type AnnoX");
return false;
}
_elementAnnoY = _elementUtils.getTypeElement("targets.model.pc.AnnoY");
if (null == _elementAnnoY || _elementAnnoY.getKind() != ElementKind.ANNOTATION_TYPE) {
reportError("annotation type annoY was not found or was not an annotation");
return false;
}
for (ExecutableElement method : ElementFilter.methodsIn(_elementAnnoY.getEnclosedElements())) {
if ("value".equals(method.getSimpleName().toString())) {
_annoYValue = method;
}
}
if (null == _annoYValue) {
reportError("Could not find value() method in annotation type AnnoY");
return false;
}
return true;
}
/**
* Test the {@link Elements#getAllAnnotationMirrors()} method
* @return true if all tests passed
*/
private boolean examineGetAllAnnotations()
{
List<? extends AnnotationMirror> annotationsH = _elementUtils.getAllAnnotationMirrors(_elementH);
if (null == annotationsH) {
reportError("examineGetAllAnnotations: getAllAnnotationMirrors(_elementH) returned null");
return false;
}
// H has AnnoY("on H"), G has AnnoX("on G"), and F has hidden AnnoY("on F").
int foundF = 0;
int foundG = 0;
int foundH = 0;
for (AnnotationMirror anno : annotationsH) {
Map<? extends ExecutableElement, ? extends AnnotationValue> values = anno.getElementValues();
AnnotationValue valueY = values.get(_annoYValue);
if (null != valueY) {
if ("on F".equals(valueY.getValue())) {
foundF++;
}
else if ("on H".equals(valueY.getValue())) {
foundH++;
}
else {
reportError("examineGetAllAnnotations: unexpected value for annotation AnnoY");
return false;
}
}
else {
AnnotationValue valueX = values.get(_annoXValue);
if (null != valueX) {
if ("on G".equals(valueX.getValue())) {
foundG++;
}
else {
reportError("examineGetAllAnnotations: unexpected value for annotation AnnoX");
return false;
}
}
else {
reportError("examineGetAllAnnotations: getAllAnnotationMirrors(_elementH) returned a mirror with no value()");
return false;
}
}
}
if (0 != foundF || 1 != foundG || 1 != foundH) {
reportError("examineGetAllAnnotations: getAllAnnotationMirrors() found wrong number of annotations on H");
return false;
}
return true;
}
/**
* Test the {@link Elements#getAllMembers()} method
* @return true if all tests passed
*/
private boolean examineGetAllMembers()
{
List<? extends Element> members = _elementUtils.getAllMembers(_elementG);
if (null == members) {
reportError("examineGetAllMembers: getAllMembers(_elementG) returned null");
return false;
}
// G member list should contain Object methods, e.g., hashCode()
boolean foundHashCode = false;
for (ExecutableElement method : ElementFilter.methodsIn(members)) {
if ("hashCode".equals(method.getSimpleName().toString())) {
foundHashCode = true;
break;
}
}
if (!foundHashCode) {
reportError("examineGetAllMembers: getAllMembers(_elementG) did not include method hashCode()");
return false;
}
// G member list should contain F's nested FChild class
boolean foundFChild = false;
for (TypeElement type : ElementFilter.typesIn(members)) {
if (type.equals(_elementFChild)) {
foundFChild = true;
break;
}
}
if (!foundFChild) {
reportError("examineGetAllMembers: getAllMembers(_elementG) did not include class FChild");
return false;
}
// G member list should contain F's _fieldT1_protected
// G member list should not contain F's _fieldT1_private, because it is hidden
boolean foundFProtectedField = false;
for (VariableElement field : ElementFilter.fieldsIn(members)) {
if ("_fieldT1_protected".equals(field.getSimpleName().toString())) {
foundFProtectedField = true;
}
else if ("_fieldT1_private".equals(field.getSimpleName().toString())) {
reportError("examineGetAllMembers: getAllMembers(_elementG) included the private inherited field _fieldT1_private");
return false;
}
}
if (!foundFProtectedField) {
reportError("examineGetAllMembers: getAllMembers(_elementG) did not return the protected inherited field _fieldT1_protected");
return false;
}
// G member list should contain G() constructor
// G member list should not contain F() constructor
boolean foundGConstructor = false;
for (ExecutableElement method : ElementFilter.constructorsIn(members)) {
Element enclosing = method.getEnclosingElement();
if (_elementG.equals(enclosing)) {
foundGConstructor = true;
}
else {
reportError("examineGetAllMembers: getAllMembers(_elementG) returned a constructor for an element other than G");
return false;
}
}
if (!foundGConstructor) {
reportError("examineGetAllMembers: getAllMembers(_elementG) did not include G's constructor");
return false;
}
// G member list should contain G's method_T1(String)
// G member list should not contain F's method_T1(T1), because it is overridden by G
boolean foundGMethodT1 = false;
for (ExecutableElement method : ElementFilter.methodsIn(members)) {
Element enclosing = method.getEnclosingElement();
if ("method_T1".equals(method.getSimpleName().toString())) {
if (_elementG.equals(enclosing)) {
foundGMethodT1 = true;
}
else {
reportError("examineGetAllMembers: getAllMembers(_elementG) included an overridden version of method_T1()");
return false;
}
}
}
if (!foundGMethodT1) {
reportError("examineGetAllMembers: getAllMembers(_elementG) did not include G's method_T1(String)");
return false;
}
return true;
}
/**
* Test the {@link Elements#isDeprecated()} method
* @return true if all tests passed
*/
private boolean examineIsDeprecated()
{
Element _deprecatedElem = _elementUtils.getTypeElement("targets.model.pc.Deprecation");
if (null == _deprecatedElem) {
reportError("examineIsDeprecated: Couldn't find targets.model.pc.Deprecation");
return false;
}
ExecutableElement methodDeprecated = null;
ExecutableElement methodNotDeprecated = null;
for (ExecutableElement method : ElementFilter.methodsIn(_deprecatedElem.getEnclosedElements())) {
if ("deprecatedMethod".equals(method.getSimpleName().toString())) {
methodDeprecated = method;
}
else if ("nonDeprecatedMethod".equals(method.getSimpleName().toString())) {
methodNotDeprecated = method;
}
}
if (null == methodDeprecated || null == methodNotDeprecated) {
reportError("examineIsDeprecated: Could not find methods Deprecation.deprecatedMethod() or Deprecation.nonDeprecatedMethod()");
return false;
}
if (_elementUtils.isDeprecated(methodNotDeprecated)) {
reportError("examineIsDeprecated: ElementUtils.isDeprecated(Deprecation.nonDeprecatedMethod()) is true");
return false;
}
if (!_elementUtils.isDeprecated(methodDeprecated)) {
reportError("examineIsDeprecated: ElementUtils.isDeprecated(Deprecation.deprecatedMethod()) is false");
return false;
}
TypeElement classDeprecated = null;
TypeElement classNotDeprecated = null;
TypeElement interfaceDeprecated = null;
TypeElement interfaceNotDeprecated = null;
for (TypeElement type : ElementFilter.typesIn(_deprecatedElem.getEnclosedElements())) {
if ("deprecatedClass".equals(type.getSimpleName().toString())) {
classDeprecated = type;
}
else if ("nonDeprecatedClass".equals(type.getSimpleName().toString())) {
classNotDeprecated = type;
}
else if ("deprecatedInterface".equals(type.getSimpleName().toString())) {
interfaceDeprecated = type;
}
else if ("nonDeprecatedInterface".equals(type.getSimpleName().toString())) {
interfaceNotDeprecated = type;
}
}
if (null == classDeprecated || null == classNotDeprecated) {
reportError("examineIsDeprecated: Could not find methods Deprecation.deprecatedClass() or Deprecation.nonDeprecatedClass()");
return false;
}
if (null == interfaceDeprecated || null == interfaceNotDeprecated) {
reportError("examineIsDeprecated: Could not find methods Deprecation.deprecatedInterface() or Deprecation.nonDeprecatedInterface()");
return false;
}
if (_elementUtils.isDeprecated(classNotDeprecated)) {
reportError("examineIsDeprecated: ElementUtils.isDeprecated(Deprecation.nonDeprecatedClass()) is true");
return false;
}
if (!_elementUtils.isDeprecated(classDeprecated)) {
reportError("examineIsDeprecated: ElementUtils.isDeprecated(Deprecation.deprecatedClass()) is false");
return false;
}
if (_elementUtils.isDeprecated(interfaceNotDeprecated)) {
reportError("examineIsDeprecated: ElementUtils.isDeprecated(Deprecation.nonDeprecatedInterface()) is true");
return false;
}
if (!_elementUtils.isDeprecated(interfaceDeprecated)) {
reportError("examineIsDeprecated: ElementUtils.isDeprecated(Deprecation.deprecatedInterface()) is false");
return false;
}
TypeElement deprecatedInnerClass = _elementUtils.getTypeElement("targets.model.pc.Deprecation.deprecatedClass");
if (null == deprecatedInnerClass) {
reportError("examineIsDeprecated: Couldn't find class Deprecation.deprecatedClass");
return false;
}
return true;
}
/**
* Test the {@link Elements#getBinaryName(TypeElement)} method
* @return true if all tests passed
*/
private boolean examineBinaryName() {
final String refNameF = "targets.model.pc.F";
final String refBNameFChild = "targets.model.pc.F$FChild";
final String refBNameFEnum = "targets.model.pc.F$FEnum";
String bnameF = _elementUtils.getBinaryName(_elementF).toString();
if (!refNameF.equals(bnameF)) {
reportError("examineBinaryName: getBinaryName(F) should be " + refNameF + ", was: " + bnameF);
return false;
}
String bnameFChild = _elementUtils.getBinaryName(_elementFChild).toString();
if (!refBNameFChild.equals(bnameFChild)) {
reportError("examineBinaryName: getBinaryName(F) should be " + refBNameFChild + ", was: " + bnameF);
return false;
}
String bnameFEnum = _elementUtils.getBinaryName(_elementFEnum).toString();
if (!refBNameFEnum.equals(bnameFEnum)) {
reportError("examineBinaryName: getBinaryName(F) should be " + refBNameFEnum + ", was: " + bnameF);
return false;
}
return true;
}
/**
* Test the {@link Elements#getDocComment(TypeElement)} method
* @return true if all tests passed
*/
private boolean examineGetDocComment() {
// Javadoc for element F and its enclosed elements - map of element simple name to javadoc
Map<String, String> nameToDoc = new HashMap<String, String>();
nameToDoc.put("F", " Javadoc on element F\n @param <T1> a type parameter\n");
nameToDoc.put("FChild", " Javadoc on nested element FChild\n");
nameToDoc.put("FEnum", " Javadoc on nested enum FEnum\n Two lines long\n");
nameToDoc.put("FChildI", " Javadoc on nested interface FChildI\n");
nameToDoc.put("_fieldT1_protected", "Javadoc on field _fieldT1_protected, inline format ");
nameToDoc.put("fieldInt", null);
nameToDoc.put("method_T1", " Javadoc on F.method_T1\n");
nameToDoc.put("method_String", null);
String actual = _elementUtils.getDocComment(_elementF);
String expected = nameToDoc.get("F");
if (!expected.equals(actual)) {
reportError("examineGetDocComment: Unexpected result from getDocComment(F): " + actual);
return false;
}
for (Element e : _elementF.getEnclosedElements()) {
String name = e.getSimpleName().toString();
if (nameToDoc.containsKey(name)) {
actual = _elementUtils.getDocComment(e);
expected = nameToDoc.get(name);
if (expected == null && actual != null) {
reportError("examineGetDocComment: Expected getDocComment(" + name + ") to return null, but got " + actual);
return false;
}
else if (expected != null) {
if (!expected.equals(actual)) {
reportError("examineGetDocComment: Unexpected result from getDocComment(" + name + "): " + actual);
return false;
}
}
}
}
return true;
}
/**
* Test the {@link Elements#hides(Element, Element)} method for fields
* @return true if all tests passed
*/
private boolean examineHidesField() {
VariableElement fieldIntJ = null;
VariableElement fieldIntH = null;
VariableElement fieldIntG = null;
VariableElement fieldIntF = null;
ExecutableElement methodFieldIntJ = null;
for (VariableElement field : ElementFilter.fieldsIn(_elementF.getEnclosedElements())) {
if ("fieldInt".equals(field.getSimpleName().toString())) {
fieldIntF = field;
break;
}
}
for (VariableElement field : ElementFilter.fieldsIn(_elementG.getEnclosedElements())) {
if ("fieldInt".equals(field.getSimpleName().toString())) {
fieldIntG = field;
break;
}
}
for (VariableElement field : ElementFilter.fieldsIn(_elementH.getEnclosedElements())) {
if ("fieldInt".equals(field.getSimpleName().toString())) {
fieldIntH = field;
break;
}
}
for (VariableElement field : ElementFilter.fieldsIn(_elementJ.getEnclosedElements())) {
if ("fieldInt".equals(field.getSimpleName().toString())) {
fieldIntJ = field;
break;
}
}
for (ExecutableElement method : ElementFilter.methodsIn(_elementJ.getEnclosedElements())) {
if ("fieldInt".equals(method.getSimpleName().toString())) {
methodFieldIntJ = method;
break;
}
}
if (null == fieldIntJ || null == fieldIntH || null == fieldIntG || null == fieldIntF) {
reportError("examineHidesField: Failed to find field \"fieldInt\" in either F, G, H, or J");
return false;
}
if (null == methodFieldIntJ) {
reportError("examineHidesField: Failed to find method \"fieldInt()\" in J");
return false;
}
// Should hide:
if (!_elementUtils.hides(fieldIntH, fieldIntF)) {
reportError("examineHidesField: H.fieldInt should hide F.fieldInt");
return false;
}
// Should not hide:
if (_elementUtils.hides(fieldIntF, fieldIntF)) {
reportError("examineHidesField: F.fieldInt should not hide itself");
return false;
}
if (_elementUtils.hides(fieldIntF, fieldIntG)) {
reportError("examineHidesField: F.fieldInt should not hide G.fieldInt");
return false;
}
if (!_elementUtils.hides(fieldIntG, fieldIntF)) {
reportError("examineHidesField: G.fieldInt should hide F.fieldInt");
return false;
}
if (_elementUtils.hides(fieldIntJ, fieldIntG)) {
reportError("examineHidesField: J.fieldInt should not hide G.fieldInt");
return false;
}
if (_elementUtils.hides(fieldIntJ, methodFieldIntJ)) {
reportError("examineHidesField: field J.fieldInt should not hide method J.fieldInt()");
return false;
}
return true;
}
/**
* Test the {@link Elements#hides(Element, Element)} method for nested classes
* @return true if all tests passed
*/
private boolean examineHidesClass() {
TypeElement elementFChildOnF = null;
TypeElement elementFChildOnH = null;
TypeElement elementFOnJ = null;
TypeElement elementFChildOnJ = null;
TypeElement elementIFChildOnIF = null;
TypeElement elementIFChildOnH = null;
TypeElement elementIF = _elementUtils.getTypeElement("targets.model.pc.IF");
for (TypeElement element : ElementFilter.typesIn(elementIF.getEnclosedElements())) {
String name = element.getSimpleName().toString();
if ("IFChild".equals(name)) {
elementIFChildOnIF = element;
break;
}
}
for (TypeElement element : ElementFilter.typesIn(_elementF.getEnclosedElements())) {
String name = element.getSimpleName().toString();
if ("FChild".equals(name)) {
elementFChildOnF = element;
break;
}
}
for (TypeElement element : ElementFilter.typesIn(_elementH.getEnclosedElements())) {
String name = element.getSimpleName().toString();
if ("FChild".equals(name)) {
elementFChildOnH = element;
}
else if ("IFChild".equals(name)) {
elementIFChildOnH = element;
}
}
for (TypeElement element : ElementFilter.typesIn(_elementJ.getEnclosedElements())) {
String name = element.getSimpleName().toString();
if ("FChild".equals(name)) {
elementFChildOnJ = element;
}
else if ("F".equals(name)) {
elementFOnJ = element;
}
}
Element elementFPackage = _elementF.getEnclosingElement();
// Should hide:
if (!_elementUtils.hides(elementFChildOnH, elementFChildOnF)) {
reportError("examineHidesClass: H.FChild should hide F.FChild");
return false;
}
if (!_elementUtils.hides(elementIFChildOnH, elementIFChildOnIF)) {
reportError("examineHidesClass: H.IFChild should hide IF.IFChild");
return false;
}
// Should not hide:
if (_elementUtils.hides(elementFChildOnF, elementFChildOnF)) {
reportError("examineHidesClass: F.FChild should not hide itself");
return false;
}
if (_elementUtils.hides(elementIFChildOnH, elementFChildOnF)) {
reportError("examineHidesClass: H.IFChild should not hide F.FChild");
return false;
}
if (_elementUtils.hides(elementFChildOnF, elementFChildOnH)) {
reportError("examineHidesClass: F.FChild should not hide H.FChild");
return false;
}
if (_elementUtils.hides(elementFChildOnJ, elementFChildOnF)) {
reportError("examineHidesClass: J.FChild should not hide F.FChild");
return false;
}
if (_elementUtils.hides(_elementF, elementFOnJ)) {
reportError("examineHidesClass: J.F should not hide F");
return false;
}
if (_elementUtils.hides(_elementF, elementFPackage) || _elementUtils.hides(elementFPackage, _elementF)) {
reportError("examineHidesClass: F should not hide its enclosing package, and vice versa");
return false;
}
return true;
}
/**
* Test the {@link Elements#hides(Element, Element)} method for methods
* @return true if all tests passed
*/
private boolean examineHidesMethod() {
ExecutableElement methodStaticOnF = null;
ExecutableElement methodStatic2OnF = null;
ExecutableElement methodT1OnF = null;
ExecutableElement methodStaticOnG = null;
ExecutableElement methodT1OnG = null;
ExecutableElement methodStaticOnH = null;
ExecutableElement methodStaticIntOnH = null;
ExecutableElement methodStaticOnJ = null;
for (ExecutableElement method : ElementFilter.methodsIn(_elementF.getEnclosedElements())) {
String name = method.getSimpleName().toString();
if ("staticMethod".equals(name)) {
methodStaticOnF = method;
}
else if ("staticMethod2".equals(name)) {
methodStatic2OnF = method;
}
else if ("method_T1".equals(name)) {
methodT1OnF = method;
}
}
for (ExecutableElement method : ElementFilter.methodsIn(_elementG.getEnclosedElements())) {
String name = method.getSimpleName().toString();
if ("staticMethod".equals(name)) {
methodStaticOnG = method;
}
else if ("method_T1".equals(name)) {
methodT1OnG = method;
}
}
for (ExecutableElement method : ElementFilter.methodsIn(_elementH.getEnclosedElements())) {
String name = method.getSimpleName().toString();
if ("staticMethod".equals(name)) {
if (method.getParameters().isEmpty()) {
methodStaticOnH = method;
}
else {
methodStaticIntOnH = method;
}
}
}
for (ExecutableElement method : ElementFilter.methodsIn(_elementJ.getEnclosedElements())) {
String name = method.getSimpleName().toString();
if ("staticMethod".equals(name)) {
methodStaticOnJ = method;
break;
}
}
if (methodStaticOnF == null || methodStatic2OnF == null || methodT1OnF == null) {
reportError("examineHidesMethod: Failed to find an expected method on F");
return false;
}
if (methodStaticOnG == null || methodT1OnG == null) {
reportError("examineHidesMethod: Failed to find an expected method on G");
return false;
}
if (methodStaticOnH == null || methodStaticIntOnH == null) {
reportError("examineHidesMethod: Failed to find an expected method on H");
return false;
}
if (methodStaticOnJ == null) {
reportError("examineHidesMethod: Failed to find an expected method on J");
return false;
}
// The should-hide cases
if (!_elementUtils.hides(methodStaticOnH, methodStaticOnG)) {
reportError("examineHidesMethod: H.staticMethod() should hide G.staticMethod()");
return false;
}
// The should-not-hide cases
if (_elementUtils.hides(methodStaticOnG, methodStaticOnG)) {
reportError("examineHidesMethod: G.staticMethod() should not hide itself");
return false;
}
if (_elementUtils.hides(methodStaticOnG, methodStaticOnF)) {
reportError("examineHidesMethod: G.staticMethod() should not hide (private) F.staticMethod()");
return false;
}
if (_elementUtils.hides(methodStaticOnG, methodStaticOnH)) {
reportError("examineHidesMethod: G.staticMethod() should not hide H.staticMethod()");
return false;
}
if (_elementUtils.hides(methodStaticOnG, methodStatic2OnF)) {
reportError("examineHidesMethod: G.staticMethod() should not hide F.staticMethod2()");
return false;
}
if (_elementUtils.hides(methodStaticOnJ, methodStaticOnG)) {
reportError("examineHidesMethod: J.staticMethod() should not hide G.staticMethod()");
return false;
}
if (_elementUtils.hides(methodStaticIntOnH, methodStaticOnG)) {
reportError("examineHidesMethod: H.staticMethod(int) should not hide G.staticMethod()");
return false;
}
if (_elementUtils.hides(methodT1OnG, methodT1OnF)) {
reportError("examineHidesMethod: G.methodT1() should not hide F.methodT1(), because they aren't static (JLS 8.4.8.2)");
return false;
}
return true;
}
/**
* Test the {@link Elements#overrides(ExecutableElement, ExecutableElement, TypeElement)} implementation
* @return true if all tests passed
*/
private boolean examineOverrides() {
// D extends (C extends A implements B). X is unrelated.
TypeElement typeA = _elementUtils.getTypeElement("targets.model.pc.Overriding.A");
TypeElement typeB = _elementUtils.getTypeElement("targets.model.pc.Overriding.B");
TypeElement typeC = _elementUtils.getTypeElement("targets.model.pc.Overriding.C");
TypeElement typeD = _elementUtils.getTypeElement("targets.model.pc.Overriding.D");
TypeElement typeX = _elementUtils.getTypeElement("targets.model.pc.F");
if (typeA == null || typeB == null || typeC == null || typeD == null) {
reportError("Unable to find types in targets.model.pc.Overriding");
return false;
}
ExecutableElement methodAF = null;
ExecutableElement methodAG = null;
ExecutableElement methodAH = null;
ExecutableElement methodAJ = null;
ExecutableElement methodBF = null;
ExecutableElement methodBG = null;
ExecutableElement methodBH = null;
ExecutableElement methodCH = null;
ExecutableElement methodDF = null;
ExecutableElement methodDG = null;
ExecutableElement methodDJ = null;
ExecutableElement methodXF = null;
for (ExecutableElement method : ElementFilter.methodsIn(typeA.getEnclosedElements())) {
String name = method.getSimpleName().toString();
if ("f".equals(name)) {
methodAF = method;
}
else if ("g".equals(name)) {
methodAG = method;
}
else if ("h".equals(name)) {
methodAH = method;
}
else if ("j".equals(name)) {
methodAJ = method;
}
}
for (ExecutableElement method : ElementFilter.methodsIn(typeB.getEnclosedElements())) {
String name = method.getSimpleName().toString();
if ("f".equals(name)) {
methodBF = method;
}
else if ("g".equals(name)) {
methodBG = method;
}
else if ("h".equals(name)) {
methodBH = method;
}
}
for (ExecutableElement method : ElementFilter.methodsIn(typeC.getEnclosedElements())) {
String name = method.getSimpleName().toString();
if ("h".equals(name)) {
methodCH = method;
break;
}
}
for (ExecutableElement method : ElementFilter.methodsIn(typeD.getEnclosedElements())) {
String name = method.getSimpleName().toString();
if ("f".equals(name)) {
methodDF = method;
}
else if ("g".equals(name)) {
methodDG = method;
}
else if ("j".equals(name)) {
methodDJ = method;
}
}
for (ExecutableElement method : ElementFilter.methodsIn(typeX.getEnclosedElements())) {
String name = method.getSimpleName().toString();
if ("f".equals(name)) {
methodXF = method;
break;
}
}
if (null == methodAF || null == methodAG || null == methodAH || null == methodAJ ||
null == methodBF || null == methodBG || null == methodBH ||
null == methodCH ||
null == methodDF || null == methodDG || null == methodDJ ||
null == methodXF) {
reportError("examineOverrides: could not find some methods");
return false;
}
// Should override:
if (!_elementUtils.overrides(methodAF, methodBF, typeC)) {
reportError("examineOverrides: A.f() should override B.f() in the context of C");
return false;
}
if (!_elementUtils.overrides(methodCH, methodAH, typeC)) {
reportError("examineOverrides: C.h() should override A.h() in the context of C");
return false;
}
if (!_elementUtils.overrides(methodCH, methodAH, typeD)) {
reportError("examineOverrides: C.h() should override A.h() in the context of D");
return false;
}
if (!_elementUtils.overrides(methodDF, methodBF, typeD)) {
reportError("examineOverrides: D.f() should override B.f() in the context of D");
return false;
}
if (!_elementUtils.overrides(methodDG, methodBG, typeD)) {
reportError("examineOverrides: D.g() should override B.g() in the context of D");
return false;
}
if (!_elementUtils.overrides(methodDJ, methodAJ, typeD)) {
reportError("examineOverrides: D.j() should override A.j() in the context of D");
return false;
}
if (!_elementUtils.overrides(methodAH, methodBH, typeC)) {
reportError("examineOverrides: A.h() should override B.h() in the context of C (even though C.h does too)");
return false;
}
// Should not override:
if (_elementUtils.overrides(methodAF, methodAF, typeA)) {
reportError("examineOverrides: A.f() should not override itself in the context of A");
return false;
}
if (_elementUtils.overrides(methodAF, methodAF, typeC)) {
reportError("examineOverrides: A.f() should not override itself in the context of C");
return false;
}
if (_elementUtils.overrides(methodAF, methodBF, typeA)) {
reportError("examineOverrides: A.f() should not override B.f() in the context of A");
return false;
}
if (_elementUtils.overrides(methodAG, methodBG, typeC)) {
reportError("examineOverrides: private A.g() should not override B.g() in the context of C");
return false;
}
if (_elementUtils.overrides(methodDG, methodAG, typeD)) {
reportError("examineOverrides: D.g() should not override private A.g() in the context of D");
return false;
}
if (_elementUtils.overrides(methodXF, methodAF, typeD)) {
reportError("examineOverrides: unrelated X.f() should not override A.f() in the context of D");
return false;
}
if (_elementUtils.overrides(methodXF, methodBF, typeX)) {
reportError("examineOverrides: X.f() should not override unrelated B.f() in the context of X");
return false;
}
// These cases seem like they should return false, but javac returns true:
if (!_elementUtils.overrides(methodDJ, methodAJ, typeC)) {
reportError("examineOverrides: to match javac, D.j() should override A.j() in the context of C");
return false;
}
if (!_elementUtils.overrides(methodDF, methodAF, typeC)) {
reportError("examineOverrides: to match javac, D.f() should override A.f() in the context of C");
return false;
}
if (!_elementUtils.overrides(methodDF, methodBF, typeC)) {
reportError("examineOverrides: to match javac, D.f() should override B.f() in the context of C");
return false;
}
return true;
}
}