8256950: Add record attribute support to symbol generator CreateSymbols
Reviewed-by: jjg, chegar
This commit is contained in:
parent
f148915d54
commit
6eff9315e1
@ -122,6 +122,7 @@ import com.sun.tools.classfile.Field;
|
|||||||
import com.sun.tools.classfile.InnerClasses_attribute;
|
import com.sun.tools.classfile.InnerClasses_attribute;
|
||||||
import com.sun.tools.classfile.InnerClasses_attribute.Info;
|
import com.sun.tools.classfile.InnerClasses_attribute.Info;
|
||||||
import com.sun.tools.classfile.Method;
|
import com.sun.tools.classfile.Method;
|
||||||
|
import com.sun.tools.classfile.MethodParameters_attribute;
|
||||||
import com.sun.tools.classfile.ModuleResolution_attribute;
|
import com.sun.tools.classfile.ModuleResolution_attribute;
|
||||||
import com.sun.tools.classfile.ModuleTarget_attribute;
|
import com.sun.tools.classfile.ModuleTarget_attribute;
|
||||||
import com.sun.tools.classfile.Module_attribute;
|
import com.sun.tools.classfile.Module_attribute;
|
||||||
@ -131,6 +132,8 @@ import com.sun.tools.classfile.Module_attribute.ProvidesEntry;
|
|||||||
import com.sun.tools.classfile.Module_attribute.RequiresEntry;
|
import com.sun.tools.classfile.Module_attribute.RequiresEntry;
|
||||||
import com.sun.tools.classfile.NestHost_attribute;
|
import com.sun.tools.classfile.NestHost_attribute;
|
||||||
import com.sun.tools.classfile.NestMembers_attribute;
|
import com.sun.tools.classfile.NestMembers_attribute;
|
||||||
|
import com.sun.tools.classfile.Record_attribute;
|
||||||
|
import com.sun.tools.classfile.Record_attribute.ComponentInfo;
|
||||||
import com.sun.tools.classfile.RuntimeAnnotations_attribute;
|
import com.sun.tools.classfile.RuntimeAnnotations_attribute;
|
||||||
import com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute;
|
import com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute;
|
||||||
import com.sun.tools.classfile.RuntimeInvisibleParameterAnnotations_attribute;
|
import com.sun.tools.classfile.RuntimeInvisibleParameterAnnotations_attribute;
|
||||||
@ -959,6 +962,22 @@ public class CreateSymbols {
|
|||||||
attributes.put(Attribute.NestMembers,
|
attributes.put(Attribute.NestMembers,
|
||||||
new NestMembers_attribute(attributeString, nestMembers));
|
new NestMembers_attribute(attributeString, nestMembers));
|
||||||
}
|
}
|
||||||
|
if (header.isRecord) {
|
||||||
|
assert header.recordComponents != null;
|
||||||
|
int attributeString = addString(constantPool, Attribute.Record);
|
||||||
|
ComponentInfo[] recordComponents = new ComponentInfo[header.recordComponents.size()];
|
||||||
|
int i = 0;
|
||||||
|
for (RecordComponentDescription rcd : header.recordComponents) {
|
||||||
|
int name = addString(constantPool, rcd.name);
|
||||||
|
Descriptor desc = new Descriptor(addString(constantPool, rcd.descriptor));
|
||||||
|
Map<String, Attribute> nestedAttrs = new HashMap<>();
|
||||||
|
addGenericAttributes(rcd, constantPool, nestedAttrs);
|
||||||
|
Attributes attrs = new Attributes(nestedAttrs);
|
||||||
|
recordComponents[i++] = new ComponentInfo(name, desc, attrs);
|
||||||
|
}
|
||||||
|
attributes.put(Attribute.Record,
|
||||||
|
new Record_attribute(attributeString, recordComponents));
|
||||||
|
}
|
||||||
addInnerClassesAttribute(header, constantPool, attributes);
|
addInnerClassesAttribute(header, constantPool, attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1017,6 +1036,18 @@ public class CreateSymbols {
|
|||||||
new RuntimeVisibleParameterAnnotations_attribute(attributeString,
|
new RuntimeVisibleParameterAnnotations_attribute(attributeString,
|
||||||
annotations));
|
annotations));
|
||||||
}
|
}
|
||||||
|
if (desc.methodParameters != null && !desc.methodParameters.isEmpty()) {
|
||||||
|
int attributeString =
|
||||||
|
addString(constantPool, Attribute.MethodParameters);
|
||||||
|
MethodParameters_attribute.Entry[] entries =
|
||||||
|
desc.methodParameters
|
||||||
|
.stream()
|
||||||
|
.map(p -> new MethodParameters_attribute.Entry(addString(constantPool, p.name),
|
||||||
|
p.flags))
|
||||||
|
.toArray(s -> new MethodParameters_attribute.Entry[s]);
|
||||||
|
attributes.put(Attribute.MethodParameters,
|
||||||
|
new MethodParameters_attribute(attributeString, entries));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addAttributes(FieldDescription desc, List<CPInfo> constantPool, Map<String, Attribute> attributes) {
|
private void addAttributes(FieldDescription desc, List<CPInfo> constantPool, Map<String, Attribute> attributes) {
|
||||||
@ -1595,7 +1626,9 @@ public class CreateSymbols {
|
|||||||
StringWriter data = new StringWriter();
|
StringWriter data = new StringWriter();
|
||||||
ModuleDescription module = modules.get(e.getKey());
|
ModuleDescription module = modules.get(e.getKey());
|
||||||
|
|
||||||
|
if (module != null) { //module == null should only be in tests.
|
||||||
module.write(data, desc.basePlatform, desc.version);
|
module.write(data, desc.basePlatform, desc.version);
|
||||||
|
}
|
||||||
|
|
||||||
for (ClassDescription clazz : e.getValue()) {
|
for (ClassDescription clazz : e.getValue()) {
|
||||||
clazz.write(data, desc.basePlatform, desc.version);
|
clazz.write(data, desc.basePlatform, desc.version);
|
||||||
@ -2153,6 +2186,37 @@ public class CreateSymbols {
|
|||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case Attribute.Record: {
|
||||||
|
assert feature instanceof ClassHeaderDescription;
|
||||||
|
Record_attribute record = (Record_attribute) attr;
|
||||||
|
List<RecordComponentDescription> components = new ArrayList<>();
|
||||||
|
for (ComponentInfo info : record.component_info_arr) {
|
||||||
|
RecordComponentDescription rcd = new RecordComponentDescription();
|
||||||
|
rcd.name = info.getName(cf.constant_pool);
|
||||||
|
rcd.descriptor = info.descriptor.getValue(cf.constant_pool);
|
||||||
|
for (Attribute nestedAttr : info.attributes) {
|
||||||
|
readAttribute(cf, rcd, nestedAttr);
|
||||||
|
}
|
||||||
|
components.add(rcd);
|
||||||
|
}
|
||||||
|
ClassHeaderDescription chd = (ClassHeaderDescription) feature;
|
||||||
|
chd.isRecord = true;
|
||||||
|
chd.recordComponents = components;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Attribute.MethodParameters: {
|
||||||
|
assert feature instanceof MethodDescription;
|
||||||
|
MethodParameters_attribute params = (MethodParameters_attribute) attr;
|
||||||
|
MethodDescription method = (MethodDescription) feature;
|
||||||
|
method.methodParameters = new ArrayList<>();
|
||||||
|
for (MethodParameters_attribute.Entry e : params.method_parameter_table) {
|
||||||
|
String name = cf.constant_pool.getUTF8Value(e.name_index);
|
||||||
|
MethodDescription.MethodParam param =
|
||||||
|
new MethodDescription.MethodParam(e.flags, name);
|
||||||
|
method.methodParameters.add(param);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
throw new IllegalStateException("Unhandled attribute: " +
|
throw new IllegalStateException("Unhandled attribute: " +
|
||||||
attrName);
|
attrName);
|
||||||
@ -2999,6 +3063,8 @@ public class CreateSymbols {
|
|||||||
List<String> implementsAttr;
|
List<String> implementsAttr;
|
||||||
String nestHost;
|
String nestHost;
|
||||||
List<String> nestMembers;
|
List<String> nestMembers;
|
||||||
|
boolean isRecord;
|
||||||
|
List<RecordComponentDescription> recordComponents;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
@ -3007,6 +3073,8 @@ public class CreateSymbols {
|
|||||||
hash = 17 * hash + Objects.hashCode(this.implementsAttr);
|
hash = 17 * hash + Objects.hashCode(this.implementsAttr);
|
||||||
hash = 17 * hash + Objects.hashCode(this.nestHost);
|
hash = 17 * hash + Objects.hashCode(this.nestHost);
|
||||||
hash = 17 * hash + Objects.hashCode(this.nestMembers);
|
hash = 17 * hash + Objects.hashCode(this.nestMembers);
|
||||||
|
hash = 17 * hash + Objects.hashCode(this.isRecord);
|
||||||
|
hash = 17 * hash + Objects.hashCode(this.recordComponents);
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3031,6 +3099,12 @@ public class CreateSymbols {
|
|||||||
if (!listEquals(this.nestMembers, other.nestMembers)) {
|
if (!listEquals(this.nestMembers, other.nestMembers)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (this.isRecord != other.isRecord) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!listEquals(this.recordComponents, other.recordComponents)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3048,8 +3122,12 @@ public class CreateSymbols {
|
|||||||
output.append(" nestHost " + nestHost);
|
output.append(" nestHost " + nestHost);
|
||||||
if (nestMembers != null && !nestMembers.isEmpty())
|
if (nestMembers != null && !nestMembers.isEmpty())
|
||||||
output.append(" nestMembers " + serializeList(nestMembers));
|
output.append(" nestMembers " + serializeList(nestMembers));
|
||||||
|
if (isRecord) {
|
||||||
|
output.append(" record true");
|
||||||
|
}
|
||||||
writeAttributes(output);
|
writeAttributes(output);
|
||||||
output.append("\n");
|
output.append("\n");
|
||||||
|
writeRecordComponents(output, baselineVersion, version);
|
||||||
writeInnerClasses(output, baselineVersion, version);
|
writeInnerClasses(output, baselineVersion, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3065,14 +3143,37 @@ public class CreateSymbols {
|
|||||||
nestHost = reader.attributes.get("nestHost");
|
nestHost = reader.attributes.get("nestHost");
|
||||||
String nestMembersList = reader.attributes.get("nestMembers");
|
String nestMembersList = reader.attributes.get("nestMembers");
|
||||||
nestMembers = deserializeList(nestMembersList);
|
nestMembers = deserializeList(nestMembersList);
|
||||||
|
isRecord = reader.attributes.containsKey("record");
|
||||||
|
|
||||||
readAttributes(reader);
|
readAttributes(reader);
|
||||||
reader.moveNext();
|
reader.moveNext();
|
||||||
|
if (isRecord) {
|
||||||
|
readRecordComponents(reader);
|
||||||
|
}
|
||||||
readInnerClasses(reader);
|
readInnerClasses(reader);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void writeRecordComponents(Appendable output,
|
||||||
|
String baselineVersion,
|
||||||
|
String version) throws IOException {
|
||||||
|
if (recordComponents != null) {
|
||||||
|
for (RecordComponentDescription rcd : recordComponents) {
|
||||||
|
rcd.write(output, "", "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void readRecordComponents(LineBasedReader reader) throws IOException {
|
||||||
|
recordComponents = new ArrayList<>();
|
||||||
|
|
||||||
|
while ("recordcomponent".equals(reader.lineKey)) {
|
||||||
|
RecordComponentDescription rcd = new RecordComponentDescription();
|
||||||
|
rcd.read(reader);
|
||||||
|
recordComponents.add(rcd);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static abstract class HeaderDescription extends FeatureDescription {
|
static abstract class HeaderDescription extends FeatureDescription {
|
||||||
@ -3145,6 +3246,7 @@ public class CreateSymbols {
|
|||||||
Object annotationDefaultValue;
|
Object annotationDefaultValue;
|
||||||
List<List<AnnotationDescription>> classParameterAnnotations;
|
List<List<AnnotationDescription>> classParameterAnnotations;
|
||||||
List<List<AnnotationDescription>> runtimeParameterAnnotations;
|
List<List<AnnotationDescription>> runtimeParameterAnnotations;
|
||||||
|
List<MethodParam> methodParameters;
|
||||||
|
|
||||||
public MethodDescription() {
|
public MethodDescription() {
|
||||||
flagsNormalization = METHODS_FLAGS_NORMALIZATION;
|
flagsNormalization = METHODS_FLAGS_NORMALIZATION;
|
||||||
@ -3221,6 +3323,15 @@ public class CreateSymbols {
|
|||||||
output.append(";");
|
output.append(";");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (methodParameters != null && !methodParameters.isEmpty()) {
|
||||||
|
Function<MethodParam, String> param2String =
|
||||||
|
p -> Integer.toHexString(p.flags) + ":" + p.name;
|
||||||
|
List<String> paramsAsStrings =
|
||||||
|
methodParameters.stream()
|
||||||
|
.map(param2String)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
output.append(" methodParameters " + serializeList(paramsAsStrings));
|
||||||
|
}
|
||||||
output.append("\n");
|
output.append("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3268,17 +3379,41 @@ public class CreateSymbols {
|
|||||||
runtimeParameterAnnotations = annos;
|
runtimeParameterAnnotations = annos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String inMethodParameters = reader.attributes.get("methodParameters");
|
||||||
|
if (inMethodParameters != null) {
|
||||||
|
Function<String, MethodParam> string2Param =
|
||||||
|
p -> {
|
||||||
|
int sep = p.indexOf(':');
|
||||||
|
return new MethodParam(Integer.parseInt(p.substring(0, sep)),
|
||||||
|
p.substring(sep + 1));
|
||||||
|
};
|
||||||
|
methodParameters =
|
||||||
|
deserializeList(inMethodParameters).stream()
|
||||||
|
.map(string2Param)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
reader.moveNext();
|
reader.moveNext();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class MethodParam {
|
||||||
|
public final int flags;
|
||||||
|
public final String name;
|
||||||
|
|
||||||
|
public MethodParam(int flags, String name) {
|
||||||
|
this.flags = flags;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class FieldDescription extends FeatureDescription {
|
static class FieldDescription extends FeatureDescription {
|
||||||
String name;
|
String name;
|
||||||
String descriptor;
|
String descriptor;
|
||||||
Object constantValue;
|
Object constantValue;
|
||||||
|
String keyName = "field";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
@ -3315,13 +3450,13 @@ public class CreateSymbols {
|
|||||||
if (shouldIgnore(baselineVersion, version))
|
if (shouldIgnore(baselineVersion, version))
|
||||||
return ;
|
return ;
|
||||||
if (!versions.contains(version)) {
|
if (!versions.contains(version)) {
|
||||||
output.append("-field");
|
output.append("-" + keyName);
|
||||||
output.append(" name " + quote(name, false));
|
output.append(" name " + quote(name, false));
|
||||||
output.append(" descriptor " + quote(descriptor, false));
|
output.append(" descriptor " + quote(descriptor, false));
|
||||||
output.append("\n");
|
output.append("\n");
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
output.append("field");
|
output.append(keyName);
|
||||||
output.append(" name " + name);
|
output.append(" name " + name);
|
||||||
output.append(" descriptor " + descriptor);
|
output.append(" descriptor " + descriptor);
|
||||||
if (constantValue != null) {
|
if (constantValue != null) {
|
||||||
@ -3333,7 +3468,7 @@ public class CreateSymbols {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean read(LineBasedReader reader) throws IOException {
|
public boolean read(LineBasedReader reader) throws IOException {
|
||||||
if (!"field".equals(reader.lineKey))
|
if (!keyName.equals(reader.lineKey))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
name = reader.attributes.get("name");
|
name = reader.attributes.get("name");
|
||||||
@ -3366,6 +3501,19 @@ public class CreateSymbols {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static final class RecordComponentDescription extends FieldDescription {
|
||||||
|
|
||||||
|
public RecordComponentDescription() {
|
||||||
|
this.keyName = "recordcomponent";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean shouldIgnore(String baselineVersion, String version) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static final class AnnotationDescription {
|
static final class AnnotationDescription {
|
||||||
String annotationType;
|
String annotationType;
|
||||||
Map<String, Object> values;
|
Map<String, Object> values;
|
||||||
|
@ -1516,7 +1516,7 @@ public abstract class Symbol extends AnnoConstruct implements PoolConstant, Elem
|
|||||||
}
|
}
|
||||||
RecordComponent rc = null;
|
RecordComponent rc = null;
|
||||||
if (addIfMissing) {
|
if (addIfMissing) {
|
||||||
recordComponents = recordComponents.append(rc = new RecordComponent(var, annotations));
|
recordComponents = recordComponents.append(rc = new RecordComponent(var.sym, annotations));
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -1527,6 +1527,10 @@ public abstract class Symbol extends AnnoConstruct implements PoolConstant, Elem
|
|||||||
return recordComponents;
|
return recordComponents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setRecordComponents(List<RecordComponent> recordComponents) {
|
||||||
|
this.recordComponents = recordComponents;
|
||||||
|
}
|
||||||
|
|
||||||
@DefinedBy(Api.LANGUAGE_MODEL)
|
@DefinedBy(Api.LANGUAGE_MODEL)
|
||||||
public NestingKind getNestingKind() {
|
public NestingKind getNestingKind() {
|
||||||
apiComplete();
|
apiComplete();
|
||||||
@ -1790,10 +1794,17 @@ public abstract class Symbol extends AnnoConstruct implements PoolConstant, Elem
|
|||||||
/**
|
/**
|
||||||
* Construct a record component, given its flags, name, type and owner.
|
* Construct a record component, given its flags, name, type and owner.
|
||||||
*/
|
*/
|
||||||
public RecordComponent(JCVariableDecl fieldDecl, List<JCAnnotation> annotations) {
|
public RecordComponent(Name name, Type type, Symbol owner) {
|
||||||
super(PUBLIC, fieldDecl.sym.name, fieldDecl.sym.type, fieldDecl.sym.owner);
|
super(PUBLIC, name, type, owner);
|
||||||
|
pos = -1;
|
||||||
|
originalAnnos = List.nil();
|
||||||
|
isVarargs = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RecordComponent(VarSymbol field, List<JCAnnotation> annotations) {
|
||||||
|
super(PUBLIC, field.name, field.type, field.owner);
|
||||||
this.originalAnnos = annotations;
|
this.originalAnnos = annotations;
|
||||||
this.pos = fieldDecl.pos;
|
this.pos = field.pos;
|
||||||
/* it is better to store the original information for this one, instead of relying
|
/* it is better to store the original information for this one, instead of relying
|
||||||
* on the info in the type of the symbol. This is because on the presence of APs
|
* on the info in the type of the symbol. This is because on the presence of APs
|
||||||
* the symbol will be blown out and we won't be able to know if the original
|
* the symbol will be blown out and we won't be able to know if the original
|
||||||
|
@ -1205,7 +1205,16 @@ public class ClassReader {
|
|||||||
if (sym.kind == TYP) {
|
if (sym.kind == TYP) {
|
||||||
sym.flags_field |= RECORD;
|
sym.flags_field |= RECORD;
|
||||||
}
|
}
|
||||||
bp = bp + attrLen;
|
int componentCount = nextChar();
|
||||||
|
ListBuffer<RecordComponent> components = new ListBuffer<>();
|
||||||
|
for (int i = 0; i < componentCount; i++) {
|
||||||
|
Name name = poolReader.getName(nextChar());
|
||||||
|
Type type = poolReader.getType(nextChar());
|
||||||
|
RecordComponent c = new RecordComponent(name, type, sym);
|
||||||
|
readAttrs(c, AttributeKind.MEMBER);
|
||||||
|
components.add(c);
|
||||||
|
}
|
||||||
|
((ClassSymbol) sym).setRecordComponents(components.toList());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new AttributeReader(names.PermittedSubclasses, V59, CLASS_ATTRIBUTE) {
|
new AttributeReader(names.PermittedSubclasses, V59, CLASS_ATTRIBUTE) {
|
||||||
|
@ -229,7 +229,7 @@ public class PrintingProcessor extends AbstractProcessor {
|
|||||||
writer.print("(");
|
writer.print("(");
|
||||||
writer.print(e.getRecordComponents()
|
writer.print(e.getRecordComponents()
|
||||||
.stream()
|
.stream()
|
||||||
.map(recordDes -> recordDes.asType().toString() + " " + recordDes.getSimpleName())
|
.map(recordDes -> annotationsToString(recordDes) + recordDes.asType().toString() + " " + recordDes.getSimpleName())
|
||||||
.collect(Collectors.joining(", ")));
|
.collect(Collectors.joining(", ")));
|
||||||
writer.print(")");
|
writer.print(")");
|
||||||
}
|
}
|
||||||
@ -448,7 +448,7 @@ public class PrintingProcessor extends AbstractProcessor {
|
|||||||
|
|
||||||
private void printModifiers(Element e) {
|
private void printModifiers(Element e) {
|
||||||
ElementKind kind = e.getKind();
|
ElementKind kind = e.getKind();
|
||||||
if (kind == PARAMETER) {
|
if (kind == PARAMETER || kind == RECORD_COMPONENT) {
|
||||||
// Print annotation inline
|
// Print annotation inline
|
||||||
writer.print(annotationsToString(e));
|
writer.print(annotationsToString(e));
|
||||||
} else {
|
} else {
|
||||||
@ -456,7 +456,7 @@ public class PrintingProcessor extends AbstractProcessor {
|
|||||||
indent();
|
indent();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kind == ENUM_CONSTANT)
|
if (kind == ENUM_CONSTANT || kind == RECORD_COMPONENT)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Set<Modifier> modifiers = new LinkedHashSet<>();
|
Set<Modifier> modifiers = new LinkedHashSet<>();
|
||||||
|
@ -362,16 +362,14 @@ public class ClassWriter {
|
|||||||
write(a, out);
|
write(a, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: due to the use of shared resources, this method is not reentrant.
|
|
||||||
public void write(Attribute attr, ClassOutputStream out) {
|
public void write(Attribute attr, ClassOutputStream out) {
|
||||||
out.writeShort(attr.attribute_name_index);
|
out.writeShort(attr.attribute_name_index);
|
||||||
sharedOut.reset();
|
ClassOutputStream nestedOut = new ClassOutputStream();
|
||||||
attr.accept(this, sharedOut);
|
attr.accept(this, nestedOut);
|
||||||
out.writeInt(sharedOut.size());
|
out.writeInt(nestedOut.size());
|
||||||
sharedOut.writeTo(out);
|
nestedOut.writeTo(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ClassOutputStream sharedOut = new ClassOutputStream();
|
|
||||||
protected AnnotationWriter annotationWriter = new AnnotationWriter();
|
protected AnnotationWriter annotationWriter = new AnnotationWriter();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -756,8 +754,8 @@ public class ClassWriter {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void writeAccessFlags(AccessFlags flags, ClassOutputStream p) {
|
protected void writeAccessFlags(AccessFlags flags, ClassOutputStream out) {
|
||||||
sharedOut.writeShort(flags.flags);
|
out.writeShort(flags.flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected StackMapTableWriter stackMapWriter;
|
protected StackMapTableWriter stackMapWriter;
|
||||||
|
@ -76,6 +76,11 @@ public class MethodParameters_attribute extends Attribute {
|
|||||||
flags = cr.readUnsignedShort();
|
flags = cr.readUnsignedShort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Entry(int name_index, int flags) {
|
||||||
|
this.name_index = name_index;
|
||||||
|
this.flags = flags;
|
||||||
|
}
|
||||||
|
|
||||||
public static int length() {
|
public static int length() {
|
||||||
return 6;
|
return 6;
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,12 @@ public class Record_attribute extends Attribute {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Record_attribute(int name_index, ComponentInfo[] component_info_arr) {
|
||||||
|
super(name_index, 2);
|
||||||
|
this.component_count = component_info_arr.length;
|
||||||
|
this.component_info_arr = component_info_arr;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <R, D> R accept(Visitor<R, D> visitor, D data) {
|
public <R, D> R accept(Visitor<R, D> visitor, D data) {
|
||||||
return visitor.visitRecord(this, data);
|
return visitor.visitRecord(this, data);
|
||||||
@ -59,6 +65,12 @@ public class Record_attribute extends Attribute {
|
|||||||
attributes = new Attributes(cr);
|
attributes = new Attributes(cr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ComponentInfo(int name_index, Descriptor descriptor, Attributes attributes) {
|
||||||
|
this.name_index = name_index;
|
||||||
|
this.descriptor = descriptor;
|
||||||
|
this.attributes = attributes;
|
||||||
|
}
|
||||||
|
|
||||||
public String getName(ConstantPool constant_pool) throws ConstantPoolException {
|
public String getName(ConstantPool constant_pool) throws ConstantPoolException {
|
||||||
return constant_pool.getUTF8Value(name_index);
|
return constant_pool.getUTF8Value(name_index);
|
||||||
}
|
}
|
||||||
|
@ -25,8 +25,14 @@
|
|||||||
* @test
|
* @test
|
||||||
* @bug 8072480
|
* @bug 8072480
|
||||||
* @summary Unit test for CreateSymbols
|
* @summary Unit test for CreateSymbols
|
||||||
|
* @modules java.compiler
|
||||||
|
* jdk.compiler/com.sun.tools.javac.api
|
||||||
|
* jdk.compiler/com.sun.tools.javac.jvm
|
||||||
|
* jdk.compiler/com.sun.tools.javac.main
|
||||||
|
* jdk.compiler/com.sun.tools.javac.util
|
||||||
|
* jdk.jdeps/com.sun.tools.classfile
|
||||||
* @clean *
|
* @clean *
|
||||||
* @run main CreateSymbolsTest
|
* @run main/othervm CreateSymbolsTest
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -38,7 +44,8 @@ import java.nio.file.Files;
|
|||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.nio.file.attribute.BasicFileAttributes;
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
import java.util.Arrays;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import javax.tools.JavaCompiler;
|
import javax.tools.JavaCompiler;
|
||||||
import javax.tools.StandardJavaFileManager;
|
import javax.tools.StandardJavaFileManager;
|
||||||
import javax.tools.ToolProvider;
|
import javax.tools.ToolProvider;
|
||||||
@ -56,37 +63,58 @@ public class CreateSymbolsTest {
|
|||||||
Path compileDir = testClasses.resolve("data");
|
Path compileDir = testClasses.resolve("data");
|
||||||
deleteRecursively(compileDir);
|
deleteRecursively(compileDir);
|
||||||
Files.createDirectories(compileDir);
|
Files.createDirectories(compileDir);
|
||||||
Path createSymbols = findFile("../../make/src/classes/build/tools/symbolgenerator/CreateSymbols.java");
|
Path createSymbols = findFile("../../make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java");
|
||||||
|
|
||||||
if (createSymbols == null) {
|
if (createSymbols == null) {
|
||||||
System.err.println("Warning: cannot find CreateSymbols, skipping.");
|
System.err.println("Warning: cannot find CreateSymbols, skipping.");
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
Path createTestImpl = findFile("../../make/test/sym/CreateSymbolsTestImpl.java");
|
Path createTestImpl = findFile("tools/javac/platform/createsymbols/CreateSymbolsTestImpl.java");
|
||||||
|
|
||||||
if (createTestImpl == null) {
|
if (createTestImpl == null) {
|
||||||
System.err.println("Warning: cannot find CreateSymbolsTestImpl, skipping.");
|
throw new AssertionError("Warning: cannot find CreateSymbolsTestImpl, skipping.");
|
||||||
return ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Path toolBox = findFile("../../test/tools/lib/ToolBox.java");
|
Path toolBox = findFile("tools/lib/toolbox/");
|
||||||
|
|
||||||
if (toolBox == null) {
|
if (toolBox == null) {
|
||||||
System.err.println("Warning: cannot find ToolBox, skipping.");
|
throw new AssertionError("Warning: cannot find ToolBox, skipping.");
|
||||||
return ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
||||||
|
|
||||||
try (StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null)) {
|
try (StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null)) {
|
||||||
|
List<Path> files = new ArrayList<>();
|
||||||
|
|
||||||
|
files.add(createSymbols);
|
||||||
|
files.add(createTestImpl);
|
||||||
|
|
||||||
|
files.add(toolBox.resolve("AbstractTask.java"));
|
||||||
|
files.add(toolBox.resolve("JavacTask.java"));
|
||||||
|
files.add(toolBox.resolve("Task.java"));
|
||||||
|
files.add(toolBox.resolve("ToolBox.java"));
|
||||||
|
|
||||||
|
Boolean res =
|
||||||
compiler.getTask(null,
|
compiler.getTask(null,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
Arrays.asList("-d", compileDir.toAbsolutePath().toString()),
|
List.of("-d",
|
||||||
|
compileDir.toAbsolutePath().toString(),
|
||||||
|
"-g",
|
||||||
|
"--add-modules", "jdk.jdeps",
|
||||||
|
"--add-exports", "jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED",
|
||||||
|
"--add-exports", "jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED",
|
||||||
|
"--add-exports", "jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED",
|
||||||
|
"--add-exports", "jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED",
|
||||||
|
"--add-exports", "jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
|
||||||
|
"--add-exports", "jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED"),
|
||||||
null,
|
null,
|
||||||
fm.getJavaFileObjects(createSymbols, createTestImpl, toolBox)
|
fm.getJavaFileObjectsFromPaths(files)
|
||||||
).call();
|
).call();
|
||||||
|
if (!res) {
|
||||||
|
throw new IllegalStateException("Cannot compile test.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
URLClassLoader cl = new URLClassLoader(new URL[] {testClasses.toUri().toURL(), compileDir.toUri().toURL()});
|
URLClassLoader cl = new URLClassLoader(new URL[] {testClasses.toUri().toURL(), compileDir.toUri().toURL()});
|
||||||
@ -100,9 +128,9 @@ public class CreateSymbolsTest {
|
|||||||
|
|
||||||
for (Path d = testSrc; d != null; d = d.getParent()) {
|
for (Path d = testSrc; d != null; d = d.getParent()) {
|
||||||
if (Files.exists(d.resolve("TEST.ROOT"))) {
|
if (Files.exists(d.resolve("TEST.ROOT"))) {
|
||||||
Path createSymbols = d.resolve(path);
|
Path file = d.resolve(path);
|
||||||
if (Files.exists(createSymbols)) {
|
if (Files.exists(file)) {
|
||||||
return createSymbols;
|
return file;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -29,7 +29,6 @@ import java.lang.annotation.RetentionPolicy;
|
|||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import com.sun.tools.javac.file.ZipFileIndexCache;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.FileVisitResult;
|
import java.nio.file.FileVisitResult;
|
||||||
import java.nio.file.FileVisitor;
|
import java.nio.file.FileVisitor;
|
||||||
@ -37,14 +36,20 @@ import java.nio.file.Files;
|
|||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.nio.file.attribute.BasicFileAttributes;
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
|
import java.util.Enumeration;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.jar.JarEntry;
|
||||||
|
import java.util.jar.JarFile;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
import toolbox.JavacTask;
|
||||||
|
import toolbox.Task;
|
||||||
|
import toolbox.Task.Expect;
|
||||||
|
import toolbox.ToolBox;
|
||||||
import build.tools.symbolgenerator.CreateSymbols;
|
import build.tools.symbolgenerator.CreateSymbols;
|
||||||
import build.tools.symbolgenerator.CreateSymbols.ClassDescription;
|
import build.tools.symbolgenerator.CreateSymbols.ClassDescription;
|
||||||
import build.tools.symbolgenerator.CreateSymbols.ClassList;
|
import build.tools.symbolgenerator.CreateSymbols.ClassList;
|
||||||
import build.tools.symbolgenerator.CreateSymbols.CtSymKind;
|
|
||||||
import build.tools.symbolgenerator.CreateSymbols.ExcludeIncludeList;
|
import build.tools.symbolgenerator.CreateSymbols.ExcludeIncludeList;
|
||||||
import build.tools.symbolgenerator.CreateSymbols.VersionDescription;
|
import build.tools.symbolgenerator.CreateSymbols.VersionDescription;
|
||||||
|
|
||||||
@ -59,8 +64,6 @@ public class CreateSymbolsTestImpl {
|
|||||||
void doTest() throws Exception {
|
void doTest() throws Exception {
|
||||||
boolean testRun = false;
|
boolean testRun = false;
|
||||||
for (Method m : CreateSymbolsTestImpl.class.getDeclaredMethods()) {
|
for (Method m : CreateSymbolsTestImpl.class.getDeclaredMethods()) {
|
||||||
if (!"testIncluded".equals(m.getName()))
|
|
||||||
continue;
|
|
||||||
if (m.isAnnotationPresent(Test.class)) {
|
if (m.isAnnotationPresent(Test.class)) {
|
||||||
m.invoke(this);
|
m.invoke(this);
|
||||||
testRun = true;
|
testRun = true;
|
||||||
@ -76,19 +79,19 @@ public class CreateSymbolsTestImpl {
|
|||||||
doTest("package t; public class T { public void m() { } }",
|
doTest("package t; public class T { public void m() { } }",
|
||||||
"package t; public class T { }",
|
"package t; public class T { }",
|
||||||
"package t; public class Test { { T t = null; t.m(); } }",
|
"package t; public class Test { { T t = null; t.m(); } }",
|
||||||
ToolBox.Expect.SUCCESS,
|
Expect.SUCCESS,
|
||||||
ToolBox.Expect.FAIL);
|
Expect.FAIL);
|
||||||
doTest("package t; public class T { public void b() { } public void m() { } public void a() { } }",
|
doTest("package t; public class T { public void b() { } public void m() { } public void a() { } }",
|
||||||
"package t; public class T { public void b() { } public void a() { } }",
|
"package t; public class T { public void b() { } public void a() { } }",
|
||||||
"package t; public class Test { { T t = null; t.b(); t.a(); } }",
|
"package t; public class Test { { T t = null; t.b(); t.a(); } }",
|
||||||
ToolBox.Expect.SUCCESS,
|
Expect.SUCCESS,
|
||||||
ToolBox.Expect.SUCCESS);
|
Expect.SUCCESS);
|
||||||
//with additional attribute (need to properly skip the member):
|
//with additional attribute (need to properly skip the member):
|
||||||
doTest("package t; public class T { public void m() throws IllegalStateException { } public void a() { } }",
|
doTest("package t; public class T { public void m() throws IllegalStateException { } public void a() { } }",
|
||||||
"package t; public class T { public void a() { } }",
|
"package t; public class T { public void a() { } }",
|
||||||
"package t; public class Test { { T t = null; t.a(); } }",
|
"package t; public class Test { { T t = null; t.a(); } }",
|
||||||
ToolBox.Expect.SUCCESS,
|
Expect.SUCCESS,
|
||||||
ToolBox.Expect.SUCCESS);
|
Expect.SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -96,13 +99,13 @@ public class CreateSymbolsTestImpl {
|
|||||||
doTest("package t; public class T { }",
|
doTest("package t; public class T { }",
|
||||||
"package t; public class T { public void m() { } }",
|
"package t; public class T { public void m() { } }",
|
||||||
"package t; public class Test { { T t = null; t.m(); } }",
|
"package t; public class Test { { T t = null; t.m(); } }",
|
||||||
ToolBox.Expect.FAIL,
|
Expect.FAIL,
|
||||||
ToolBox.Expect.SUCCESS);
|
Expect.SUCCESS);
|
||||||
doTest("package t; public class T { public void b() { } public void a() { } }",
|
doTest("package t; public class T { public void b() { } public void a() { } }",
|
||||||
"package t; public class T { public void b() { } public void m() { } public void a() { } }",
|
"package t; public class T { public void b() { } public void m() { } public void a() { } }",
|
||||||
"package t; public class Test { { T t = null; t.b(); t.a(); } }",
|
"package t; public class Test { { T t = null; t.b(); t.a(); } }",
|
||||||
ToolBox.Expect.SUCCESS,
|
Expect.SUCCESS,
|
||||||
ToolBox.Expect.SUCCESS);
|
Expect.SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//verify fields added/modified/removed
|
//verify fields added/modified/removed
|
||||||
@ -112,8 +115,8 @@ public class CreateSymbolsTestImpl {
|
|||||||
doTest("class Dummy {}",
|
doTest("class Dummy {}",
|
||||||
"package t; public class T { }",
|
"package t; public class T { }",
|
||||||
"package t; public class Test { { T t = new T(); } }",
|
"package t; public class Test { { T t = new T(); } }",
|
||||||
ToolBox.Expect.FAIL,
|
Expect.FAIL,
|
||||||
ToolBox.Expect.SUCCESS);
|
Expect.SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -121,8 +124,8 @@ public class CreateSymbolsTestImpl {
|
|||||||
doTest("package t; public class T { public void m() { } }",
|
doTest("package t; public class T { public void m() { } }",
|
||||||
"package t; public class T implements java.io.Serializable { public void m() { } }",
|
"package t; public class T implements java.io.Serializable { public void m() { } }",
|
||||||
"package t; public class Test { { java.io.Serializable t = new T(); } }",
|
"package t; public class Test { { java.io.Serializable t = new T(); } }",
|
||||||
ToolBox.Expect.FAIL,
|
Expect.FAIL,
|
||||||
ToolBox.Expect.SUCCESS);
|
Expect.SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -130,17 +133,17 @@ public class CreateSymbolsTestImpl {
|
|||||||
doTest("package t; public class T { }",
|
doTest("package t; public class T { }",
|
||||||
"class Dummy {}",
|
"class Dummy {}",
|
||||||
"package t; public class Test { { T t = new T(); } }",
|
"package t; public class Test { { T t = new T(); } }",
|
||||||
ToolBox.Expect.SUCCESS,
|
Expect.SUCCESS,
|
||||||
ToolBox.Expect.FAIL);
|
Expect.FAIL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testInnerClassAttributes() throws Exception {
|
void testInnerClassAttributes() throws Exception {
|
||||||
doTest("package t; public class T { public static class Inner { } }",
|
doTest("package t; public class T { public static class Inner { } }",
|
||||||
"package t; public class T { public static class Inner { } }",
|
"package t; public class T { public static class Inner { } public void extra() {} }",
|
||||||
"package t; import t.T.Inner; public class Test { Inner i; }",
|
"package t; import t.T.Inner; public class Test { Inner i; }",
|
||||||
ToolBox.Expect.SUCCESS,
|
Expect.SUCCESS,
|
||||||
ToolBox.Expect.SUCCESS);
|
Expect.SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -148,8 +151,8 @@ public class CreateSymbolsTestImpl {
|
|||||||
doTest("package t; public class T { }",
|
doTest("package t; public class T { }",
|
||||||
"package t; public class T { public static final int A = 0; }",
|
"package t; public class T { public static final int A = 0; }",
|
||||||
"package t; public class Test { void t(int i) { switch (i) { case T.A: break;} } }",
|
"package t; public class Test { void t(int i) { switch (i) { case T.A: break;} } }",
|
||||||
ToolBox.Expect.FAIL,
|
Expect.FAIL,
|
||||||
ToolBox.Expect.SUCCESS);
|
Expect.SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -173,8 +176,8 @@ public class CreateSymbolsTestImpl {
|
|||||||
" public SuppressWarnings annotationValue() default @SuppressWarnings(\"cast\");\n" +
|
" public SuppressWarnings annotationValue() default @SuppressWarnings(\"cast\");\n" +
|
||||||
"}\n",
|
"}\n",
|
||||||
"package t; public @T class Test { }",
|
"package t; public @T class Test { }",
|
||||||
ToolBox.Expect.SUCCESS,
|
Expect.SUCCESS,
|
||||||
ToolBox.Expect.SUCCESS);
|
Expect.SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -214,7 +217,7 @@ public class CreateSymbolsTestImpl {
|
|||||||
void testAnnotations() throws Exception {
|
void testAnnotations() throws Exception {
|
||||||
doPrintElementTest("package t;" +
|
doPrintElementTest("package t;" +
|
||||||
"import java.lang.annotation.*;" +
|
"import java.lang.annotation.*;" +
|
||||||
"public @Visible @Invisible class T { }" +
|
"public @Visible @Invisible class T { public void extra() { } }" +
|
||||||
"@Retention(RetentionPolicy.RUNTIME) @interface Visible { }" +
|
"@Retention(RetentionPolicy.RUNTIME) @interface Visible { }" +
|
||||||
"@Retention(RetentionPolicy.CLASS) @interface Invisible { }",
|
"@Retention(RetentionPolicy.CLASS) @interface Invisible { }",
|
||||||
"package t;" +
|
"package t;" +
|
||||||
@ -227,11 +230,12 @@ public class CreateSymbolsTestImpl {
|
|||||||
"@t.Invisible\n" +
|
"@t.Invisible\n" +
|
||||||
"@t.Visible\n" +
|
"@t.Visible\n" +
|
||||||
"public class T {\n\n" +
|
"public class T {\n\n" +
|
||||||
" public T();\n" +
|
" public T();\n\n" +
|
||||||
|
" public void extra();\n" +
|
||||||
"}\n",
|
"}\n",
|
||||||
"t.Visible",
|
"t.Visible",
|
||||||
"package t;\n\n" +
|
"package t;\n\n" +
|
||||||
"@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)\n" +
|
"@java.lang.annotation.Retention(RUNTIME)\n" +
|
||||||
"@interface Visible {\n" +
|
"@interface Visible {\n" +
|
||||||
"}\n");
|
"}\n");
|
||||||
doPrintElementTest("package t;" +
|
doPrintElementTest("package t;" +
|
||||||
@ -247,6 +251,7 @@ public class CreateSymbolsTestImpl {
|
|||||||
"import java.util.*;" +
|
"import java.util.*;" +
|
||||||
"public class T {" +
|
"public class T {" +
|
||||||
" public void test(int h, @Invisible int i, @Visible List<String> j, int k) { }" +
|
" public void test(int h, @Invisible int i, @Visible List<String> j, int k) { }" +
|
||||||
|
" public void extra() { }" +
|
||||||
"}" +
|
"}" +
|
||||||
"@Retention(RetentionPolicy.RUNTIME) @interface Visible { }" +
|
"@Retention(RetentionPolicy.RUNTIME) @interface Visible { }" +
|
||||||
"@Retention(RetentionPolicy.CLASS) @interface Invisible { }",
|
"@Retention(RetentionPolicy.CLASS) @interface Invisible { }",
|
||||||
@ -261,7 +266,7 @@ public class CreateSymbolsTestImpl {
|
|||||||
"}\n",
|
"}\n",
|
||||||
"t.Visible",
|
"t.Visible",
|
||||||
"package t;\n\n" +
|
"package t;\n\n" +
|
||||||
"@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)\n" +
|
"@java.lang.annotation.Retention(RUNTIME)\n" +
|
||||||
"@interface Visible {\n" +
|
"@interface Visible {\n" +
|
||||||
"}\n");
|
"}\n");
|
||||||
doPrintElementTest("package t;" +
|
doPrintElementTest("package t;" +
|
||||||
@ -291,10 +296,10 @@ public class CreateSymbolsTestImpl {
|
|||||||
@Test
|
@Test
|
||||||
void testStringConstant() throws Exception {
|
void testStringConstant() throws Exception {
|
||||||
doTest("package t; public class T { public static final String C = \"\"; }",
|
doTest("package t; public class T { public static final String C = \"\"; }",
|
||||||
"package t; public class T { public static final String C = \"\"; }",
|
"package t; public class T { public static final String C = \"\"; public void extra() { } }",
|
||||||
"package t; public class Test { { System.err.println(T.C); } }",
|
"package t; public class Test { { System.err.println(T.C); } }",
|
||||||
ToolBox.Expect.SUCCESS,
|
Expect.SUCCESS,
|
||||||
ToolBox.Expect.SUCCESS);
|
Expect.SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -302,8 +307,8 @@ public class CreateSymbolsTestImpl {
|
|||||||
String oldProfileAnnotation = CreateSymbols.PROFILE_ANNOTATION;
|
String oldProfileAnnotation = CreateSymbols.PROFILE_ANNOTATION;
|
||||||
try {
|
try {
|
||||||
CreateSymbols.PROFILE_ANNOTATION = "Lt/Ann;";
|
CreateSymbols.PROFILE_ANNOTATION = "Lt/Ann;";
|
||||||
doTestEquivalence("package t; public class T { public void t() {} } @interface Ann { }",
|
doTestEquivalence("package t; public @Ann class T { public void t() {} } @interface Ann { }",
|
||||||
"package t; public @Ann class T { public void t() {} } @interface Ann { }",
|
"package t; public class T { public void t() {} }",
|
||||||
"t.T");
|
"t.T");
|
||||||
} finally {
|
} finally {
|
||||||
CreateSymbols.PROFILE_ANNOTATION = oldProfileAnnotation;
|
CreateSymbols.PROFILE_ANNOTATION = oldProfileAnnotation;
|
||||||
@ -351,13 +356,13 @@ public class CreateSymbolsTestImpl {
|
|||||||
doTest("package t; public class T { public class TT { public Object t() { return null; } } }",
|
doTest("package t; public class T { public class TT { public Object t() { return null; } } }",
|
||||||
"package t; public class T<E> { public class TT { public E t() { return null; } } }",
|
"package t; public class T<E> { public class TT { public E t() { return null; } } }",
|
||||||
"package t; public class Test { { T.TT tt = null; tt.t(); } }",
|
"package t; public class Test { { T.TT tt = null; tt.t(); } }",
|
||||||
ToolBox.Expect.SUCCESS,
|
Expect.SUCCESS,
|
||||||
ToolBox.Expect.SUCCESS);
|
Expect.SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
void doTest(String code7, String code8, String testCode, ToolBox.Expect result7, ToolBox.Expect result8) throws Exception {
|
void doTest(String code7, String code8, String testCode, Expect result7, Expect result8) throws Exception {
|
||||||
ToolBox tb = new ToolBox();
|
ToolBox tb = new ToolBox();
|
||||||
Path classes = prepareVersionedCTSym(code7, code8);
|
Path classes = prepareVersionedCTSym(code7, code8);
|
||||||
Path output = classes.getParent();
|
Path output = classes.getParent();
|
||||||
@ -365,21 +370,23 @@ public class CreateSymbolsTestImpl {
|
|||||||
|
|
||||||
Files.createDirectories(scratch);
|
Files.createDirectories(scratch);
|
||||||
|
|
||||||
tb.new JavacTask()
|
new JavacTask(tb)
|
||||||
.sources(testCode)
|
.sources(testCode)
|
||||||
.options("-d", scratch.toAbsolutePath().toString(), "-classpath", computeClassPath(classes, "7"), "-XDuseOptimizedZip=false")
|
.options("-d", scratch.toAbsolutePath().toString(), "-classpath", computeClassPath(classes, "7"))
|
||||||
.run(result7)
|
.run(result7)
|
||||||
.writeAll();
|
.writeAll();
|
||||||
tb.new JavacTask()
|
new JavacTask(tb)
|
||||||
.sources(testCode)
|
.sources(testCode)
|
||||||
.options("-d", scratch.toAbsolutePath().toString(), "-classpath", computeClassPath(classes, "8"), "-XDuseOptimizedZip=false")
|
.options("-d", scratch.toAbsolutePath().toString(), "-classpath", computeClassPath(classes, "8"))
|
||||||
.run(result8)
|
.run(result8)
|
||||||
.writeAll();
|
.writeAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String computeClassPath(Path classes, String version) throws IOException {
|
private static String computeClassPath(Path classes, String version) throws IOException {
|
||||||
try (Stream<Path> elements = Files.list(classes)) {
|
try (Stream<Path> elements = Files.list(classes)) {
|
||||||
return elements.map(el -> el.toAbsolutePath().toString())
|
return elements.filter(el -> el.getFileName().toString().contains(version))
|
||||||
|
.map(el -> el.resolve("java.base"))
|
||||||
|
.map(el -> el.toAbsolutePath().toString())
|
||||||
.collect(Collectors.joining(File.pathSeparator));
|
.collect(Collectors.joining(File.pathSeparator));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -393,17 +400,19 @@ public class CreateSymbolsTestImpl {
|
|||||||
Files.createDirectories(scratch);
|
Files.createDirectories(scratch);
|
||||||
|
|
||||||
String out;
|
String out;
|
||||||
out = tb.new JavacTask(ToolBox.Mode.CMDLINE)
|
out = new JavacTask(tb, Task.Mode.CMDLINE)
|
||||||
.options("-d", scratch.toAbsolutePath().toString(), "-classpath", computeClassPath(classes, "7"), "-XDuseOptimizedZip=false", "-Xprint", className7)
|
.options("-d", scratch.toAbsolutePath().toString(), "-classpath", computeClassPath(classes, "7"), "-Xprint", className7)
|
||||||
.run(ToolBox.Expect.SUCCESS)
|
.run(Expect.SUCCESS)
|
||||||
.getOutput(ToolBox.OutputKind.STDOUT);
|
.getOutput(Task.OutputKind.STDOUT)
|
||||||
|
.replaceAll("\\R", "\n");
|
||||||
if (!out.equals(printed7)) {
|
if (!out.equals(printed7)) {
|
||||||
throw new AssertionError("out=" + out + "; printed7=" + printed7);
|
throw new AssertionError("out=" + out + "; printed7=" + printed7);
|
||||||
}
|
}
|
||||||
out = tb.new JavacTask(ToolBox.Mode.CMDLINE)
|
out = new JavacTask(tb, Task.Mode.CMDLINE)
|
||||||
.options("-d", scratch.toAbsolutePath().toString(), "-classpath", computeClassPath(classes, "8"), "-XDuseOptimizedZip=false", "-Xprint", className8)
|
.options("-d", scratch.toAbsolutePath().toString(), "-classpath", computeClassPath(classes, "8"), "-Xprint", className8)
|
||||||
.run(ToolBox.Expect.SUCCESS)
|
.run(Expect.SUCCESS)
|
||||||
.getOutput(ToolBox.OutputKind.STDOUT);
|
.getOutput(Task.OutputKind.STDOUT)
|
||||||
|
.replaceAll("\\R", "\n");
|
||||||
if (!out.equals(printed8)) {
|
if (!out.equals(printed8)) {
|
||||||
throw new AssertionError("out=" + out + "; printed8=" + printed8);
|
throw new AssertionError("out=" + out + "; printed8=" + printed8);
|
||||||
}
|
}
|
||||||
@ -411,7 +420,7 @@ public class CreateSymbolsTestImpl {
|
|||||||
|
|
||||||
void doTestEquivalence(String code7, String code8, String testClass) throws Exception {
|
void doTestEquivalence(String code7, String code8, String testClass) throws Exception {
|
||||||
Path classes = prepareVersionedCTSym(code7, code8);
|
Path classes = prepareVersionedCTSym(code7, code8);
|
||||||
Path classfile = classes.resolve("78").resolve(testClass.replace('.', '/') + ".class");
|
Path classfile = classes.resolve("78").resolve("java.base").resolve(testClass.replace('.', '/') + ".class");
|
||||||
|
|
||||||
if (!Files.isReadable(classfile)) {
|
if (!Files.isReadable(classfile)) {
|
||||||
throw new AssertionError("Cannot find expected class.");
|
throw new AssertionError("Cannot find expected class.");
|
||||||
@ -470,12 +479,105 @@ public class CreateSymbolsTestImpl {
|
|||||||
"t.PPI");
|
"t.PPI");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRecords() throws Exception {
|
||||||
|
doPrintElementTest("package t;" +
|
||||||
|
"public class T {" +
|
||||||
|
" public record R(int i, java.util.List<String> l) { }" +
|
||||||
|
"}",
|
||||||
|
"package t;" +
|
||||||
|
"public class T {" +
|
||||||
|
" public record R(@Ann int i, long j, java.util.List<String> l) { }" +
|
||||||
|
" public @interface Ann {} " +
|
||||||
|
"}",
|
||||||
|
"t.T$R",
|
||||||
|
"""
|
||||||
|
|
||||||
|
public static record R(int i, java.util.List<java.lang.String> l) {
|
||||||
|
|
||||||
|
public R(int i,
|
||||||
|
java.util.List<java.lang.String> l);
|
||||||
|
|
||||||
|
public final java.lang.String toString();
|
||||||
|
|
||||||
|
public final int hashCode();
|
||||||
|
|
||||||
|
public final boolean equals(java.lang.Object arg0);
|
||||||
|
|
||||||
|
public int i();
|
||||||
|
|
||||||
|
public java.util.List<java.lang.String> l();
|
||||||
|
}
|
||||||
|
""",
|
||||||
|
"t.T$R",
|
||||||
|
"""
|
||||||
|
|
||||||
|
public static record R(@t.T.Ann int i, long j, java.util.List<java.lang.String> l) {
|
||||||
|
|
||||||
|
public final java.lang.String toString();
|
||||||
|
|
||||||
|
public final int hashCode();
|
||||||
|
|
||||||
|
public final boolean equals(java.lang.Object arg0);
|
||||||
|
|
||||||
|
public java.util.List<java.lang.String> l();
|
||||||
|
|
||||||
|
public R(@t.T.Ann int i,
|
||||||
|
long j,
|
||||||
|
java.util.List<java.lang.String> l);
|
||||||
|
|
||||||
|
@t.T.Ann
|
||||||
|
public int i();
|
||||||
|
|
||||||
|
public long j();
|
||||||
|
}
|
||||||
|
""");
|
||||||
|
doPrintElementTest("package t;" +
|
||||||
|
"public record R() {" +
|
||||||
|
"}",
|
||||||
|
"package t;" +
|
||||||
|
"public record R(int i) {" +
|
||||||
|
"}",
|
||||||
|
"t.R",
|
||||||
|
"""
|
||||||
|
package t;
|
||||||
|
\n\
|
||||||
|
public record R() {
|
||||||
|
\n\
|
||||||
|
public R();
|
||||||
|
\n\
|
||||||
|
public final java.lang.String toString();
|
||||||
|
\n\
|
||||||
|
public final int hashCode();
|
||||||
|
\n\
|
||||||
|
public final boolean equals(java.lang.Object arg0);
|
||||||
|
}
|
||||||
|
""",
|
||||||
|
"t.R",
|
||||||
|
"""
|
||||||
|
package t;
|
||||||
|
\n\
|
||||||
|
public record R(int i) {
|
||||||
|
\n\
|
||||||
|
public final java.lang.String toString();
|
||||||
|
\n\
|
||||||
|
public final int hashCode();
|
||||||
|
\n\
|
||||||
|
public final boolean equals(java.lang.Object arg0);
|
||||||
|
\n\
|
||||||
|
public R(int i);
|
||||||
|
\n\
|
||||||
|
public int i();
|
||||||
|
}
|
||||||
|
""");
|
||||||
|
}
|
||||||
|
|
||||||
void doTestIncluded(String code, String... includedClasses) throws Exception {
|
void doTestIncluded(String code, String... includedClasses) throws Exception {
|
||||||
boolean oldIncludeAll = includeAll;
|
boolean oldIncludeAll = includeAll;
|
||||||
try {
|
try {
|
||||||
includeAll = false;
|
includeAll = false;
|
||||||
Path classes = prepareVersionedCTSym(code, "package other; public class Other {}");
|
Path classes = prepareVersionedCTSym(code, "package other; public class Other {}");
|
||||||
Path root = classes.resolve("7");
|
Path root = classes.resolve("7").resolve("java.base");
|
||||||
try (Stream<Path> classFiles = Files.walk(root)) {
|
try (Stream<Path> classFiles = Files.walk(root)) {
|
||||||
Set<String> names = classFiles.map(p -> root.relativize(p))
|
Set<String> names = classFiles.map(p -> root.relativize(p))
|
||||||
.map(p -> p.toString())
|
.map(p -> p.toString())
|
||||||
@ -503,11 +605,7 @@ public class CreateSymbolsTestImpl {
|
|||||||
Path ver8Jar = output.resolve("8.jar");
|
Path ver8Jar = output.resolve("8.jar");
|
||||||
compileAndPack(output, ver8Jar, code8);
|
compileAndPack(output, ver8Jar, code8);
|
||||||
|
|
||||||
ZipFileIndexCache.getSharedInstance().clearCache();
|
Path classes = output.resolve("classes.zip");
|
||||||
|
|
||||||
Path classes = output.resolve("classes");
|
|
||||||
|
|
||||||
Files.createDirectories(classes);
|
|
||||||
|
|
||||||
Path ctSym = output.resolve("ct.sym");
|
Path ctSym = output.resolve("ct.sym");
|
||||||
|
|
||||||
@ -518,7 +616,21 @@ public class CreateSymbolsTestImpl {
|
|||||||
|
|
||||||
testGenerate(ver7Jar, ver8Jar, ctSym, "8", classes.toAbsolutePath().toString());
|
testGenerate(ver7Jar, ver8Jar, ctSym, "8", classes.toAbsolutePath().toString());
|
||||||
|
|
||||||
return classes;
|
Path classesDir = output.resolve("classes");
|
||||||
|
|
||||||
|
try (JarFile jf = new JarFile(classes.toFile())) {
|
||||||
|
Enumeration<JarEntry> en = jf.entries();
|
||||||
|
|
||||||
|
while (en.hasMoreElements()) {
|
||||||
|
JarEntry je = en.nextElement();
|
||||||
|
if (je.isDirectory()) continue;
|
||||||
|
Path target = classesDir.resolve(je.getName());
|
||||||
|
Files.createDirectories(target.getParent());
|
||||||
|
Files.copy(jf.getInputStream(je), target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return classesDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean includeAll = true;
|
boolean includeAll = true;
|
||||||
@ -540,17 +652,18 @@ public class CreateSymbolsTestImpl {
|
|||||||
protected boolean includeEffectiveAccess(ClassList classes, ClassDescription clazz) {
|
protected boolean includeEffectiveAccess(ClassList classes, ClassDescription clazz) {
|
||||||
return includeAll ? true : super.includeEffectiveAccess(classes, clazz);
|
return includeAll ? true : super.includeEffectiveAccess(classes, clazz);
|
||||||
}
|
}
|
||||||
}.createBaseLine(versions, acceptAll, descDest, null);
|
}.createBaseLine(versions, acceptAll, descDest, new String[0]);
|
||||||
Path symbolsDesc = descDest.resolve("symbols");
|
Path symbolsDesc = descDest.resolve("symbols");
|
||||||
try (Writer symbolsFile = Files.newBufferedWriter(symbolsDesc)) {
|
Path systemModules = descDest.resolve("systemModules");
|
||||||
symbolsFile.write("generate platforms 7:8");
|
|
||||||
symbolsFile.write(System.lineSeparator());
|
Files.newBufferedWriter(systemModules).close();
|
||||||
symbolsFile.write("platform version 7 files java.base-7.sym.txt");
|
|
||||||
symbolsFile.write(System.lineSeparator());
|
try {
|
||||||
symbolsFile.write("platform version 8 base 7 files java.base-8.sym.txt");
|
new CreateSymbols().createSymbols(null, symbolsDesc.toAbsolutePath().toString(), classDest, 0, "8", systemModules.toString());
|
||||||
symbolsFile.write(System.lineSeparator());
|
} catch (Throwable t) {
|
||||||
|
t.printStackTrace();
|
||||||
|
throw t;
|
||||||
}
|
}
|
||||||
new CreateSymbols().createSymbols(symbolsDesc.toAbsolutePath().toString(), classDest, CtSymKind.JOINED_VERSIONS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void compileAndPack(Path output, Path outputFile, String... code) throws Exception {
|
void compileAndPack(Path output, Path outputFile, String... code) throws Exception {
|
||||||
@ -559,7 +672,7 @@ public class CreateSymbolsTestImpl {
|
|||||||
deleteRecursively(scratch);
|
deleteRecursively(scratch);
|
||||||
Files.createDirectories(scratch);
|
Files.createDirectories(scratch);
|
||||||
System.err.println(Arrays.asList(code));
|
System.err.println(Arrays.asList(code));
|
||||||
tb.new JavacTask().sources(code).options("-d", scratch.toAbsolutePath().toString()).run(ToolBox.Expect.SUCCESS);
|
new JavacTask(tb).sources(code).options("-d", scratch.toAbsolutePath().toString()).run(Expect.SUCCESS);
|
||||||
List<String> classFiles = collectClassFile(scratch);
|
List<String> classFiles = collectClassFile(scratch);
|
||||||
try (Writer out = Files.newBufferedWriter(outputFile)) {
|
try (Writer out = Files.newBufferedWriter(outputFile)) {
|
||||||
for (String classFile : classFiles) {
|
for (String classFile : classFiles) {
|
129
test/langtools/tools/javac/records/RecordReading.java
Normal file
129
test/langtools/tools/javac/records/RecordReading.java
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @summary test the records can be read by javac properly
|
||||||
|
* @library /tools/lib
|
||||||
|
* @modules jdk.compiler/com.sun.tools.javac.api
|
||||||
|
* jdk.compiler/com.sun.tools.javac.main
|
||||||
|
* @build toolbox.ToolBox toolbox.JavacTask
|
||||||
|
* @run main RecordReading
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.Objects;
|
||||||
|
import toolbox.TestRunner;
|
||||||
|
import toolbox.ToolBox;
|
||||||
|
import toolbox.JavacTask;
|
||||||
|
import toolbox.Task;
|
||||||
|
|
||||||
|
public class RecordReading extends TestRunner {
|
||||||
|
ToolBox tb;
|
||||||
|
|
||||||
|
RecordReading() {
|
||||||
|
super(System.err);
|
||||||
|
tb = new ToolBox();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void runTests() throws Exception {
|
||||||
|
runTests(m -> new Object[]{Paths.get(m.getName())});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String... args) throws Exception {
|
||||||
|
RecordReading t = new RecordReading();
|
||||||
|
t.runTests();
|
||||||
|
}
|
||||||
|
|
||||||
|
Path[] findJavaFiles(Path... paths) throws IOException {
|
||||||
|
return tb.findJavaFiles(paths);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRecordClassFileReading(Path base) throws Exception {
|
||||||
|
Path src = base.resolve("src");
|
||||||
|
|
||||||
|
tb.writeJavaFiles(src,
|
||||||
|
"""
|
||||||
|
public record R(int i, @A long j, java.util.List<String> l) {}
|
||||||
|
""",
|
||||||
|
"""
|
||||||
|
public @interface A {}
|
||||||
|
""");
|
||||||
|
|
||||||
|
Path out = base.resolve("out");
|
||||||
|
Files.createDirectories(out);
|
||||||
|
|
||||||
|
new JavacTask(tb)
|
||||||
|
.outdir(out)
|
||||||
|
.files(findJavaFiles(src))
|
||||||
|
.run();
|
||||||
|
|
||||||
|
//read the class file back, to verify javac's ClassReader
|
||||||
|
//reads the Record attribute properly:
|
||||||
|
String output = new JavacTask(tb)
|
||||||
|
.options("-Xprint")
|
||||||
|
.classpath(out.toString())
|
||||||
|
.classes("R")
|
||||||
|
.run()
|
||||||
|
.writeAll()
|
||||||
|
.getOutput(Task.OutputKind.STDOUT)
|
||||||
|
.replaceAll("\\R", "\n");
|
||||||
|
|
||||||
|
String expected =
|
||||||
|
"""
|
||||||
|
\n\
|
||||||
|
public record R(int i, @A long j, java.util.List<java.lang.String> l) {
|
||||||
|
private final int i;
|
||||||
|
@A
|
||||||
|
private final long j;
|
||||||
|
private final java.util.List<java.lang.String> l;
|
||||||
|
\n\
|
||||||
|
public R(int i,
|
||||||
|
@A long j,
|
||||||
|
java.util.List<java.lang.String> l);
|
||||||
|
\n\
|
||||||
|
public final java.lang.String toString();
|
||||||
|
\n\
|
||||||
|
public final int hashCode();
|
||||||
|
\n\
|
||||||
|
public final boolean equals(java.lang.Object arg0);
|
||||||
|
\n\
|
||||||
|
public int i();
|
||||||
|
\n\
|
||||||
|
@A
|
||||||
|
public long j();
|
||||||
|
\n\
|
||||||
|
public java.util.List<java.lang.String> l();
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
if (!Objects.equals(expected, output)) {
|
||||||
|
throw new AssertionError("Unexpected output: " + output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user