1 /* 2 * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.google.doclava.javadoc; 27 28 import com.google.doclava.annotation.Unused; 29 import com.google.doclava.annotation.Used; 30 import com.sun.javadoc.AnnotationDesc; 31 import com.sun.javadoc.ClassDoc; 32 import com.sun.javadoc.PackageDoc; 33 import com.sun.javadoc.ProgramElementDoc; 34 import java.util.Set; 35 import javax.lang.model.element.Element; 36 import javax.lang.model.element.ElementKind; 37 import javax.lang.model.element.Modifier; 38 import javax.lang.model.element.PackageElement; 39 import javax.lang.model.element.TypeElement; 40 41 abstract class ProgramElementDocImpl<T extends Element> extends DocImpl<T> implements 42 ProgramElementDoc { 43 44 /** 45 * Direct mapping of {@link javax.lang.model.element.Modifier} to {@link 46 * java.lang.reflect.Modifier}. 47 * 48 * @implNote Can be updated by subclasses ({@link ClassDocImpl} and {@link 49 * AnnotationTypeDocImpl} to add {@link java.lang.reflect.Modifier#INTERFACE} modifier. 50 * @see javax.lang.model.element.Modifier 51 * @see java.lang.reflect.Modifier 52 * @see ClassDocImpl 53 * @see AnnotationTypeDocImpl 54 */ 55 protected int reflectModifiers; 56 57 protected T element; 58 59 private AnnotationDescImpl[] annotations; 60 ProgramElementDocImpl(T e, Context context)61 protected ProgramElementDocImpl(T e, Context context) { 62 super(e, context); 63 64 this.element = e; 65 this.reflectModifiers = elementModifiersToReflectModifiers(e.getModifiers()); 66 } 67 elementModifiersToReflectModifiers(Set<Modifier> modifiers)68 private int elementModifiersToReflectModifiers(Set<Modifier> modifiers) { 69 int mods = 0; 70 for (Modifier m : modifiers) { 71 switch (m) { 72 case ABSTRACT -> mods |= java.lang.reflect.Modifier.ABSTRACT; 73 case FINAL -> mods |= java.lang.reflect.Modifier.FINAL; 74 case PRIVATE -> mods |= java.lang.reflect.Modifier.PRIVATE; 75 case PROTECTED -> mods |= java.lang.reflect.Modifier.PROTECTED; 76 case PUBLIC -> mods |= java.lang.reflect.Modifier.PUBLIC; 77 case NATIVE -> mods |= java.lang.reflect.Modifier.NATIVE; 78 case STATIC -> mods |= java.lang.reflect.Modifier.STATIC; 79 case STRICTFP -> mods |= java.lang.reflect.Modifier.STRICT; 80 case SYNCHRONIZED -> mods |= java.lang.reflect.Modifier.SYNCHRONIZED; 81 case TRANSIENT -> mods |= java.lang.reflect.Modifier.TRANSIENT; 82 case VOLATILE -> mods |= java.lang.reflect.Modifier.VOLATILE; 83 case DEFAULT, NON_SEALED, SEALED -> { 84 // Exhaust the remaining element modifiers that are not present in 85 // java.lang.reflect.Modifier. 86 } 87 default -> throw new UnsupportedOperationException("Unexpected modifier: " + m); 88 } 89 } 90 return mods; 91 } 92 93 @Override 94 @Used(implemented = true) containingClass()95 public ClassDoc containingClass() { 96 Element cur = element.getEnclosingElement(); 97 while (cur != null && cur.getKind() != ElementKind.ANNOTATION_TYPE 98 && cur.getKind() != ElementKind.CLASS 99 && cur.getKind() != ElementKind.ENUM 100 && cur.getKind() != ElementKind.INTERFACE 101 && cur.getKind() != ElementKind.RECORD) { 102 cur = cur.getEnclosingElement(); 103 } 104 if (cur == null) { 105 return null; 106 } 107 return switch (cur.getKind()) { 108 case CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, RECORD -> ClassDocImpl.create((TypeElement) cur, 109 context); 110 default -> null; 111 }; 112 } 113 114 @Override 115 @Used(implemented = true) containingPackage()116 public PackageDoc containingPackage() { 117 Element cur = element.getEnclosingElement(); 118 while (cur.getKind() != ElementKind.PACKAGE) { 119 cur = cur.getEnclosingElement(); 120 } 121 return PackageDocImpl.create((PackageElement) cur, context); 122 } 123 124 @Override 125 @Unused(implemented = true) modifierSpecifier()126 public int modifierSpecifier() { 127 return reflectModifiers; 128 } 129 130 @Override 131 @Unused(implemented = true) modifiers()132 public String modifiers() { 133 return java.lang.reflect.Modifier.toString(reflectModifiers); 134 } 135 136 @Override 137 @Used(implemented = true) annotations()138 public AnnotationDesc[] annotations() { 139 if (annotations == null) { 140 annotations = element.getAnnotationMirrors() 141 .stream() 142 // b/270334687: Filter out elements that are not ANNOTATION_TYPE 143 .filter(am -> ((TypeElement) am.getAnnotationType().asElement()).getKind() == ElementKind.ANNOTATION_TYPE) 144 .map(am -> new AnnotationDescImpl(am, context)) 145 .toArray(AnnotationDescImpl[]::new); 146 } 147 return annotations; 148 } 149 150 @Override 151 @Used(implemented = true) isPublic()152 public boolean isPublic() { 153 return java.lang.reflect.Modifier.isPublic(reflectModifiers); 154 } 155 156 @Override 157 @Used(implemented = true) isProtected()158 public boolean isProtected() { 159 return java.lang.reflect.Modifier.isProtected(reflectModifiers); 160 } 161 162 @Override 163 @Used(implemented = true) isPrivate()164 public boolean isPrivate() { 165 return java.lang.reflect.Modifier.isPrivate(reflectModifiers); 166 } 167 168 @Override 169 @Used(implemented = true) isPackagePrivate()170 public boolean isPackagePrivate() { 171 return !(isPublic() || isPrivate() || isProtected()); 172 } 173 174 @Override 175 @Used(implemented = true) isStatic()176 public boolean isStatic() { 177 return java.lang.reflect.Modifier.isStatic(reflectModifiers); 178 } 179 180 @Override 181 @Used(implemented = true) isFinal()182 public boolean isFinal() { 183 return java.lang.reflect.Modifier.isFinal(reflectModifiers); 184 } 185 } 186