| /******************************************************************************* |
| * 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; |
| } |
| |
| } |