Skip to content

Commit f800e2e

Browse files
committed
[22] Implement Elements#getEnumConstantBody() eclipse-jdt#2135
1 parent 89e70ce commit f800e2e

File tree

21 files changed

+519
-23
lines changed

21 files changed

+519
-23
lines changed

JCL/javax23api/src/javax/lang/model/util/Elements.java

+6-1
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,12 @@ boolean overrides(ExecutableElement overrider, ExecutableElement overridden,
177177
default boolean isAutomaticModule(ModuleElement module) {
178178
return false;
179179
}
180-
180+
default TypeElement getEnumConstantBody(VariableElement enumConstant) {
181+
switch(enumConstant.getKind()) {
182+
case ENUM_CONSTANT -> throw new UnsupportedOperationException();
183+
default -> throw new IllegalArgumentException("Argument not an enum constant");
184+
}
185+
}
181186
default RecordComponentElement recordComponentFor(ExecutableElement accessor) {
182187
if (accessor.getEnclosingElement().getKind() == ElementKind.RECORD) {
183188
for (RecordComponentElement rec : ElementFilter.recordComponentsIn(accessor.getEnclosingElement().getEnclosedElements())) {

org.eclipse.jdt.compiler.apt.tests/build.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
###############################################################################
2-
# Copyright (c) 2006, 2023 BEA Systems Inc. and others
2+
# Copyright (c) 2006, 2024 BEA Systems Inc. and others
33
#
44
# This program and the accompanying materials
55
# are made available under the terms of the Eclipse Public License 2.0

org.eclipse.jdt.compiler.apt.tests/buildjavaxapi.xml

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<!--
3-
Copyright (c) 2023 IBM Corporation and others.
3+
Copyright (c) 2023, 2024 IBM Corporation and others.
44
55
This program and the accompanying materials
66
are made available under the terms of the Eclipse Public License 2.0
@@ -16,8 +16,8 @@
1616
<property name="jclbase" value="${basedir}/../JCL"/>
1717
<target name="build">
1818
<antcall target="javaxAPI">
19-
<param name="compliance" value="20"/>
20-
<param name="suffix" value="20"/>
19+
<param name="compliance" value="23"/>
20+
<param name="suffix" value="23"/>
2121
</antcall>
2222
</target>
2323
<target name="javaxAPI">
Binary file not shown.
Binary file not shown.
-322 Bytes
Binary file not shown.

org.eclipse.jdt.compiler.apt.tests/processors8/META-INF/services/javax.annotation.processing.Processor

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ org.eclipse.jdt.compiler.apt.tests.processors.elements.Java9ModuleProcessor
44
org.eclipse.jdt.compiler.apt.tests.processors.elements.Java11ElementProcessor
55
org.eclipse.jdt.compiler.apt.tests.processors.elements.Java12ElementProcessor
66
org.eclipse.jdt.compiler.apt.tests.processors.elements.Java13ElementProcessor
7+
org.eclipse.jdt.compiler.apt.tests.processors.elements.Java22ElementProcessor
78
org.eclipse.jdt.compiler.apt.tests.processors.elements.RecordElementProcessor
89
org.eclipse.jdt.compiler.apt.tests.processors.elements.SealedTypeElementProcessor
910
org.eclipse.jdt.compiler.apt.tests.processors.elements.Java23ElementProcessor
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,294 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2024 IBM Corporation.
3+
*
4+
* This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* which accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*
11+
* Contributors:
12+
* IBM Corporation - initial API and implementation
13+
*******************************************************************************/
14+
15+
package org.eclipse.jdt.compiler.apt.tests.processors.elements;
16+
17+
import java.io.IOException;
18+
import java.lang.reflect.InvocationTargetException;
19+
import java.lang.reflect.Method;
20+
import java.util.List;
21+
import java.util.Map;
22+
import java.util.Set;
23+
import javax.annotation.processing.Filer;
24+
import javax.annotation.processing.Messager;
25+
import javax.annotation.processing.ProcessingEnvironment;
26+
import javax.annotation.processing.RoundEnvironment;
27+
import javax.annotation.processing.SupportedAnnotationTypes;
28+
import javax.annotation.processing.SupportedSourceVersion;
29+
import javax.lang.model.SourceVersion;
30+
import javax.lang.model.element.Element;
31+
import javax.lang.model.element.ElementKind;
32+
import javax.lang.model.element.ExecutableElement;
33+
import javax.lang.model.element.ModuleElement;
34+
import javax.lang.model.element.PackageElement;
35+
import javax.lang.model.element.TypeElement;
36+
import javax.lang.model.element.VariableElement;
37+
import org.eclipse.jdt.compiler.apt.tests.processors.base.BaseProcessor;
38+
39+
/**
40+
* A processor that explores the java 13 specific elements and validates the lambda and
41+
* type annotated elements. To enable this processor, add
42+
* -Aorg.eclipse.jdt.compiler.apt.tests.processors.elements.Java11ElementProcessor to the command line.
43+
* @since 3.14
44+
*/
45+
@SupportedAnnotationTypes("*")
46+
@SupportedSourceVersion(SourceVersion.RELEASE_8)
47+
public class Java22ElementProcessor extends BaseProcessor {
48+
boolean reportSuccessAlready = true;
49+
RoundEnvironment roundEnv = null;
50+
Messager _messager = null;
51+
Filer _filer = null;
52+
boolean isBinaryMode = false;
53+
String mode;
54+
@Override
55+
public synchronized void init(ProcessingEnvironment processingEnv) {
56+
super.init(processingEnv);
57+
_elementUtils = processingEnv.getElementUtils();
58+
_messager = processingEnv.getMessager();
59+
_filer = processingEnv.getFiler();
60+
}
61+
// Always return false from this processor, because it supports "*".
62+
// The return value does not signify success or failure!
63+
@Override
64+
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
65+
if (roundEnv.processingOver()) {
66+
return false;
67+
}
68+
69+
this.roundEnv = roundEnv;
70+
Map<String, String> options = processingEnv.getOptions();
71+
if (!options.containsKey(this.getClass().getName())) {
72+
// Disable this processor unless we are intentionally performing the test.
73+
return false;
74+
} else {
75+
try {
76+
if (options.containsKey("binary")) {
77+
this.isBinaryMode = true;
78+
this.mode = "binary";
79+
} else {
80+
this.mode = "source";
81+
}
82+
if (!invokeTestMethods(options)) {
83+
testAll();
84+
}
85+
if (this.reportSuccessAlready) {
86+
super.reportSuccess();
87+
}
88+
} catch (AssertionFailedError e) {
89+
super.reportError(getExceptionStackTrace(e));
90+
} catch (Throwable e) {
91+
e.printStackTrace();
92+
}
93+
}
94+
return false;
95+
}
96+
97+
private boolean invokeTestMethods(Map<String, String> options) throws Throwable {
98+
Method testMethod = null;
99+
Set<String> keys = options.keySet();
100+
boolean testsFound = false;
101+
for (String option : keys) {
102+
if (option.startsWith("test")) {
103+
try {
104+
testMethod = this.getClass().getDeclaredMethod(option, new Class[0]);
105+
if (testMethod != null) {
106+
testsFound = true;
107+
testMethod.invoke(this, new Object[0]);
108+
}
109+
} catch (InvocationTargetException e) {
110+
throw e.getCause();
111+
} catch (Exception e) {
112+
super.reportError(getExceptionStackTrace(e));
113+
}
114+
}
115+
}
116+
return testsFound;
117+
}
118+
119+
public void testAll() throws AssertionFailedError, IOException {
120+
testGetEnumConstantBody01();
121+
testGetEnumConstantBody02();
122+
}
123+
public void testGetEnumConstantBody01() throws IOException {
124+
Set<? extends Element> rootElements = this.roundEnv.getRootElements();
125+
TypeElement elem = find(rootElements, "EnumColor");
126+
assertNotNull("TypeElement for enum should not be null", elem);
127+
List<? extends Element> members = _elementUtils.getAllMembers(elem);
128+
VariableElement blue = null, red = null;
129+
for (Element member : members) {
130+
if ("BLUE".equals(member.getSimpleName().toString())) {
131+
blue = (VariableElement) member;
132+
} else if ("RED".equals(member.getSimpleName().toString())) {
133+
red = (VariableElement) member;
134+
}
135+
}
136+
assertNotNull("enum constant should not be null", blue);
137+
assertNotNull("enum constant should not be null", red);
138+
TypeElement enumConstantBody = _elementUtils.getEnumConstantBody(red);
139+
assertNotNull("constant body should not be null", enumConstantBody);
140+
Element enclosingElement = enumConstantBody.getEnclosingElement();
141+
assertSame("Incorrect element kind", ElementKind.ENUM_CONSTANT, enclosingElement.getKind());
142+
assertEquals("incorrect enum constant", "RED", enclosingElement.getSimpleName().toString());
143+
List<? extends Element> enclosedElements = enumConstantBody.getEnclosedElements();
144+
ExecutableElement method = null;
145+
for (Element element : enclosedElements) {
146+
if (element.getKind() == ElementKind.METHOD) {
147+
if (element.getSimpleName().toString().equals("hasOptionalBody")) {
148+
method = (ExecutableElement) element;
149+
}
150+
}
151+
}
152+
assertNotNull("method should not be null", method);
153+
enumConstantBody = _elementUtils.getEnumConstantBody(blue);
154+
assertNotNull("constant body should not be null", enumConstantBody);
155+
enclosingElement = enumConstantBody.getEnclosingElement();
156+
assertSame("Incorrect element kind", ElementKind.ENUM_CONSTANT, enclosingElement.getKind());
157+
assertEquals("incorrect enum constant", "BLUE", enclosingElement.getSimpleName().toString());
158+
enclosedElements = enumConstantBody.getEnclosedElements();
159+
method = null;
160+
for (Element element : enclosedElements) {
161+
if (element.getKind() == ElementKind.METHOD) {
162+
if (element.getSimpleName().toString().equals("foo")) {
163+
method = (ExecutableElement) element;
164+
}
165+
}
166+
}
167+
assertNotNull("method should not be null", method);
168+
}
169+
public void testGetEnumConstantBody02() throws IOException {
170+
Set<? extends Element> rootElements = this.roundEnv.getRootElements();
171+
TypeElement elem = find(rootElements, "EnumShape");
172+
assertNotNull("TypeElement for enum should not be null", elem);
173+
List<? extends Element> members = _elementUtils.getAllMembers(elem);
174+
VariableElement squ = null, cir = null;
175+
for (Element member : members) {
176+
if ("SQU".equals(member.getSimpleName().toString())) {
177+
squ = (VariableElement) member;
178+
} else if ("CIR".equals(member.getSimpleName().toString())) {
179+
cir = (VariableElement) member;
180+
}
181+
}
182+
assertNotNull("enum constant should not be null", squ);
183+
assertNotNull("enum constant should not be null", cir);
184+
TypeElement enumConstantBody = _elementUtils.getEnumConstantBody(squ);
185+
assertNull("constant body should be null", enumConstantBody);
186+
enumConstantBody = _elementUtils.getEnumConstantBody(cir);
187+
assertNull("constant body should be null", enumConstantBody);
188+
}
189+
public void testGetEnumConstantBody03() throws IOException {
190+
Set<? extends Element> rootElements = this.roundEnv.getRootElements();
191+
TypeElement elem = find(rootElements, "NonEnum");
192+
assertNotNull("TypeElement for enum should not be null", elem);
193+
List<? extends Element> members = _elementUtils.getAllMembers(elem);
194+
VariableElement xyz = null;
195+
for (Element member : members) {
196+
if ("XYZ".equals(member.getSimpleName().toString())) {
197+
xyz = (VariableElement) member;
198+
}
199+
}
200+
assertNotNull("enum constant should not be null", xyz);
201+
boolean failed = true;
202+
try {
203+
_elementUtils.getEnumConstantBody(xyz);
204+
} catch (IllegalArgumentException iae) {
205+
failed = false;
206+
}
207+
if (failed)
208+
reportError("Didn't throw an IllegalArgumentException as expected");
209+
}
210+
private TypeElement find(Set<? extends Element> elements, String name) {
211+
for (Element element : elements) {
212+
if (name.equals(element.getSimpleName().toString())) {
213+
return (TypeElement) element;
214+
}
215+
}
216+
return null;
217+
}
218+
@Override
219+
public void reportError(String msg) {
220+
throw new AssertionFailedError(msg + " [mode = " + this.mode + "]");
221+
}
222+
private String getExceptionStackTrace(Throwable t) {
223+
StringBuilder buf = new StringBuilder(t.getMessage());
224+
StackTraceElement[] traces = t.getStackTrace();
225+
for (int i = 0; i < traces.length; i++) {
226+
StackTraceElement trace = traces[i];
227+
buf.append("\n\tat " + trace);
228+
if (i == 12)
229+
break; // Don't dump all stacks
230+
}
231+
return buf.toString();
232+
}
233+
protected String getElementsAsString(List<? extends Element> list) {
234+
StringBuilder builder = new StringBuilder("[");
235+
for (Element element : list) {
236+
if (element instanceof PackageElement) {
237+
builder.append(((PackageElement) element).getQualifiedName());
238+
} else if (element instanceof ModuleElement) {
239+
builder.append(((ModuleElement) element).getQualifiedName());
240+
} else if (element instanceof TypeElement) {
241+
builder.append(((TypeElement) element).getQualifiedName());
242+
} else {
243+
builder.append(element.getSimpleName());
244+
}
245+
builder.append(", ");
246+
}
247+
builder.append("]");
248+
return builder.toString();
249+
}
250+
public void assertNotNull(String msg, Object obj) {
251+
if (obj == null) {
252+
reportError(msg);
253+
}
254+
}
255+
public void assertNull(String msg, Object obj) {
256+
if (obj != null) {
257+
reportError(msg);
258+
}
259+
}
260+
public void assertSame(String msg, Object expected, Object actual) {
261+
if (expected != actual) {
262+
reportError(msg + ", should be " + expected.toString() + " but " + actual.toString());
263+
}
264+
}
265+
public void assertEquals(String message, Object expected, Object actual) {
266+
if (equalsRegardingNull(expected, actual)) {
267+
return;
268+
} else {
269+
reportError(message + ", expected " + expected.toString() + " but was " + actual.toString());
270+
}
271+
}
272+
273+
public void assertEquals(String message, Object expected, Object alternateExpected, Object actual) {
274+
if (equalsRegardingNull(expected, actual) || equalsRegardingNull(alternateExpected, actual)) {
275+
return;
276+
} else {
277+
reportError(message + ", expected " + expected.toString() + " but was " + actual.toString());
278+
}
279+
}
280+
281+
static boolean equalsRegardingNull(Object expected, Object actual) {
282+
if (expected == null) {
283+
return actual == null;
284+
}
285+
return expected.equals(actual);
286+
}
287+
private static class AssertionFailedError extends Error {
288+
private static final long serialVersionUID = 1L;
289+
290+
public AssertionFailedError(String msg) {
291+
super(msg);
292+
}
293+
}
294+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package java22;
2+
@Deprecated
3+
public enum EnumColor {
4+
BLUE() {
5+
public boolean foo() {
6+
return true;
7+
}
8+
},
9+
RED() {
10+
public boolean hasOptionalBody() {
11+
return true;
12+
}
13+
}
14+
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package java22;
2+
@Deprecated
3+
public enum EnumShape {
4+
SQU("Square"),
5+
CIR("Circle");
6+
7+
private String shape = "";
8+
9+
EnumShape(String shape) {
10+
shape = shape;
11+
}
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package java22;
2+
public class NonEnum {
3+
NonEnum XYZ = new NonEnum() {
4+
public boolean foo() {
5+
return true;
6+
}
7+
};
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module mod.java22 {
2+
}
3+

0 commit comments

Comments
 (0)