• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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