Commit 271b59a6 authored by Remi Forax's avatar Remi Forax

manually port NEST_MATES branch changes to be compatible with ASM 6.1

parent 3cee35fc
Pipeline #564 failed with stage
in 1 minute
......@@ -154,6 +154,16 @@ public class ClassRemapper extends ClassVisitor {
desc == null ? null : remapper.mapMethodDesc(desc));
}
@Override
public void visitNestHost(String nestHost) {
super.visitNestHost(remapper.mapType(nestHost));
}
@Override
public void visitNestMember(String nestMember) {
super.visitNestMember(remapper.mapType(nestMember));
}
protected FieldVisitor createFieldRemapper(FieldVisitor fv) {
return new FieldRemapper(api, fv, remapper);
}
......
......@@ -140,6 +140,16 @@ public class RemappingClassAdapter extends ClassVisitor {
desc == null ? null : remapper.mapMethodDesc(desc));
}
@Override
public void visitNestHost(String nestHost) {
throw new RuntimeException("RemappingClassAdapter is deprecated, use ClassRemapper instead");
}
@Override
public void visitNestMember(String nestMember) {
throw new RuntimeException("RemappingClassAdapter is deprecated, use ClassRemapper instead");
}
protected FieldVisitor createRemappingFieldAdapter(FieldVisitor fv) {
return new RemappingFieldAdapter(fv, remapper);
}
......
......@@ -121,6 +121,12 @@ public class ClassNode extends ClassVisitor {
/** The inner classes of this class. */
public List<InnerClassNode> innerClasses;
/** The nest host class of this class */
  • "The internal name of the nest host class of this class." would be more precise. Nit: note also the final dot.

  • You also need to update the check() method in this class, to throw an exception for classes that contain a nest host or a nest member, and if API is strictly less than ASM7. Or at least add a TODO for that.

  • Those methods "check" are new, and i've not seen them during the review, you can not add them in ASM 6.1 because they are public so the API is modified.

    ASM4 means that you want to use the ASM4 semantics for a visitor (or a Node), not that you can not support features otherwise you can not construct a pipeline of visitors with visitors from different versions.

    The more i think about these flags, the more i see them has not worth their inherent complexity. We should stick to a far more simple strategy, for all deprecated methods, throw an exception asking people to more to the more modern API.

  • There is only one check() method in ClassNode, since ASM 4.0. I was saying that the content of this method must be updated, not that new methods must be added. Basically, if nestHostClass is not null or nestMembers not empty, and the api version is strictly less than ASM7, this method must throw an exception.

  • After a night of that, i agree, i've pushed 955858d0 it adds ASM7, and all the associated changes.

    I've not yet added a test case (the specific version of the JDK for that, is still compiling ...)

    I still think the tests that suppose that ASM can not read a class of jdk11 if configured with ASM6 are playing with the fire. And currently i can not generate with a javac that contains a condy and some nestmates attributes because they are hosted in two different workspace and the two doesn't merge cleanly.

Please register or sign in to reply
public String nestHostClass;
/** The nest members of this class */
  • "The internal names of the nest members of this class." would be more precise.

Please register or sign in to reply
public List<String> nestMembers;
/** The fields of this class. */
public List<FieldNode> fields;
......@@ -186,6 +192,11 @@ public class ClassNode extends ClassVisitor {
return module;
}
@Override
public void visitNestHost(String nestHost) {
this.nestHostClass = nestHost;
}
@Override
public void visitOuterClass(final String owner, final String name, final String descriptor) {
outerClass = owner;
......@@ -236,6 +247,14 @@ public class ClassNode extends ClassVisitor {
attrs.add(attribute);
}
@Override
public void visitNestMember(String nestMember) {
if (nestMembers == null) {
nestMembers = new ArrayList<String>();
}
nestMembers.add(nestMember);
}
@Override
public void visitInnerClass(
final String name, final String outerName, final String innerName, final int access) {
......@@ -343,6 +362,10 @@ public class ClassNode extends ClassVisitor {
if (module != null) {
module.accept(classVisitor);
}
// Visit nest host class
  • Nit: use proper sentences (missing 'the' and a final dot): "Visit the nest host class.".

Please register or sign in to reply
if (nestHostClass != null) {
classVisitor.visitNestHost(nestHostClass);
}
// Visit the outer class.
if (outerClass != null) {
classVisitor.visitOuterClass(outerClass, outerMethod, outerMethodDesc);
......@@ -382,6 +405,12 @@ public class ClassNode extends ClassVisitor {
classVisitor.visitAttribute(attrs.get(i));
}
}
// visit nest members
  • Same comment here (and first letter should be capitalized): "Visit the nest members.".

Please register or sign in to reply
if (nestMembers != null) {
for (int i = 0, n = nestMembers.size(); i < n; ++i) {
classVisitor.visitNestMember(nestMembers.get(i));
}
}
// Visit the inner classes.
for (int i = 0, n = innerClasses.size(); i < n; ++i) {
innerClasses.get(i).accept(classVisitor);
......
......@@ -235,6 +235,15 @@ public class ASMifier extends Printer {
return asmifier;
}
@Override
public void visitNestHost(final String nestHost) {
stringBuilder.setLength(0);
stringBuilder.append("cw.visitNestHost(");
appendConstant(nestHost);
stringBuilder.append(");\n\n");
text.add(stringBuilder.toString());
}
@Override
public void visitOuterClass(final String owner, final String name, final String descriptor) {
stringBuilder.setLength(0);
......@@ -264,6 +273,15 @@ public class ASMifier extends Printer {
visitAttribute(attribute);
}
@Override
public void visitNestMember(final String nestMember) {
stringBuilder.setLength(0);
stringBuilder.append("cw.visitNestMember(");
appendConstant(nestMember);
stringBuilder.append(");\n\n");
text.add(stringBuilder.toString());
}
@Override
public void visitInnerClass(
final String name, final String outerName, final String innerName, final int access) {
......
......@@ -128,6 +128,14 @@ public class CheckClassAdapter extends ClassVisitor {
/** Whether the {@link #visitOuterClass} method has been called. */
private boolean visitOuterClassCalled;
/** Whether the {@link #visitNestHost} method has been called. */
private boolean visitNestHostCalled;
/**
* Package of all nest members. Not <tt>null</tt> if the visitNestMember method has been called.
Please register or sign in to reply
*/
private String nestMemberPackageName;
/** Whether the {@link #visitEnd} method has been called. */
private boolean visitEndCalled;
......@@ -403,12 +411,48 @@ public class CheckClassAdapter extends ClassVisitor {
visitModuleCalled = true;
checkFullyQualifiedName(name, "module name");
checkAccess(access, Opcodes.ACC_OPEN | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_MANDATED);
CheckModuleAdapter checkModuleAdapter = new CheckModuleAdapter(
api, super.visitModule(name, access, version), (access & Opcodes.ACC_OPEN) != 0);
CheckModuleAdapter checkModuleAdapter =
new CheckModuleAdapter(
api, super.visitModule(name, access, version), (access & Opcodes.ACC_OPEN) != 0);
checkModuleAdapter.classVersion = this.version;
return checkModuleAdapter;
}
@Override
public void visitNestHost(final String nestHost) {
checkState();
CheckMethodAdapter.checkInternalName(nestHost, "nestHost");
if (visitNestHostCalled) {
throw new IllegalStateException("visitNestHost can be called only once.");
}
if (nestMemberPackageName != null) {
throw new IllegalStateException(
"visitNestHost and and visitNestMember are mutually exclusive.");
}
visitNestHostCalled = true;
super.visitNestHost(nestHost);
}
@Override
public void visitNestMember(final String nestMember) {
checkState();
CheckMethodAdapter.checkInternalName(nestMember, "nestMember");
if (visitNestHostCalled) {
throw new IllegalStateException(
"visitMemberOfNest and and visitNestHost are mutually exclusive.");
}
String packageName = packageName(nestMember);
if (nestMemberPackageName == null) {
nestMemberPackageName = packageName;
} else {
if (!nestMemberPackageName.equals(packageName)) {
throw new IllegalStateException(
"nest member " + nestMember + " should be in the package " + nestMemberPackageName);
}
}
super.visitNestMember(nestMember);
}
@Override
public void visitOuterClass(final String owner, final String name, final String descriptor) {
checkState();
......@@ -1014,4 +1058,18 @@ public class CheckClassAdapter extends ClassVisitor {
"Invalid type reference 0x" + Integer.toHexString(typeRef));
}
}
/**
* Returns the package name of an internal name.
*
* @param name an internal name.
* @return the package name or "" if there is no package
Please register or sign in to reply
*/
private static String packageName(String name) {
Please register or sign in to reply
int index = name.lastIndexOf('/');
if (index == -1) {
return "";
}
return name.substring(0, index);
}
}
......@@ -384,6 +384,21 @@ public abstract class Printer {
throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
}
/**
* Nest host class. See {@link org.objectweb.asm.ClassVisitor#visitNestHost}.
*
* <p>Visits the nest host class of the current class. A nest is a set of classes of the same
* package that share access to their private members. The host class should list the current
* class as {@link #visitNestMember(String) nest member}. This method must be called only once and
* only if the current class is a member of a nest. A class is implicitly its own nest, so it's
* invalid to call this method with the current class as argument.
*
* @param nestHost the internal name of the host class of the nest.
*/
public void visitNestHost(final String nestHost) {
throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
}
/**
* Class outer class. See {@link org.objectweb.asm.ClassVisitor#visitOuterClass}.
*
......@@ -431,6 +446,19 @@ public abstract class Printer {
*/
public abstract void visitClassAttribute(Attribute attribute);
/**
* Nest member name. See {@link org.objectweb.asm.ClassVisitor#visitNestMember}.
*
* <p>Visits a member of the nest. A nest is a set of classes of the same package that share
* access to their private members. The nest member should declare the current class as its {@link
* #visitNestMember(String) host class}.
*
* @param nestMember the internal name of a nest member.
*/
public void visitNestMember(final String nestMember) {
throw new RuntimeException("Must be overriden");
}
/**
* Class inner name. See {@link org.objectweb.asm.ClassVisitor#visitInnerClass}.
*
......
......@@ -234,6 +234,15 @@ public class Textifier extends Printer {
return addNewTextifier(null);
}
@Override
public void visitNestHost(String nestHost) {
stringBuilder.setLength(0);
stringBuilder.append(tab).append("NESTHOST ");
appendDescriptor(INTERNAL_NAME, nestHost);
stringBuilder.append('\n');
text.add(stringBuilder.toString());
}
@Override
public void visitOuterClass(final String owner, final String name, final String descriptor) {
stringBuilder.setLength(0);
......@@ -267,6 +276,15 @@ public class Textifier extends Printer {
visitAttribute(attribute);
}
@Override
public void visitNestMember(final String nestMember) {
stringBuilder.setLength(0);
stringBuilder.append(tab).append("NESTMEMBER ");
appendDescriptor(INTERNAL_NAME, nestMember);
stringBuilder.append('\n');
text.add(stringBuilder.toString());
}
@Override
public void visitInnerClass(
final String name, final String outerName, final String innerName, final int access) {
......
......@@ -147,6 +147,12 @@ public final class TraceClassVisitor extends ClassVisitor {
return new TraceModuleVisitor(super.visitModule(name, flags, version), modulePrinter);
}
@Override
public void visitNestHost(final String nestHost) {
p.visitNestHost(nestHost);
super.visitNestHost(nestHost);
}
@Override
public void visitOuterClass(final String owner, final String name, final String descriptor) {
p.visitOuterClass(owner, name, descriptor);
......@@ -174,6 +180,12 @@ public final class TraceClassVisitor extends ClassVisitor {
super.visitAttribute(attribute);
}
@Override
public void visitNestMember(final String nestMember) {
p.visitNestMember(nestMember);
super.visitNestMember(nestMember);
}
@Override
public void visitInnerClass(
final String name, final String outerName, final String innerName, final int access) {
......
......@@ -400,6 +400,10 @@ public class ClassReader {
int modulePackagesOffset = 0;
// - The string corresponding to the ModuleMainClass attribute, or null.
String moduleMainClass = null;
// - The string corresponding to the NestHost attribute, or null
Please register or sign in to reply
String nestHostClass = null;
// the offset of the NestMembers attribute, or 0.
Please register or sign in to reply
int nestMembersOffset = 0;
// - The non standard attributes (linked with their {@link Attribute#nextAttribute} field).
// This list in the <i>reverse order</i> or their order in the ClassFile structure.
Attribute attributes = null;
......@@ -418,6 +422,10 @@ public class ClassReader {
innerClassesOffset = currentAttributeOffset;
} else if (Constants.ENCLOSING_METHOD.equals(attributeName)) {
enclosingMethodOffset = currentAttributeOffset;
} else if (Constants.NEST_HOST.equals(attributeName)) {
nestHostClass = readClass(currentAttributeOffset, charBuffer);
} else if (Constants.NEST_MEMBERS.equals(attributeName)) {
nestMembersOffset = currentAttributeOffset;
} else if (Constants.SIGNATURE.equals(attributeName)) {
signature = readUTF8(currentAttributeOffset, charBuffer);
} else if (Constants.RUNTIME_VISIBLE_ANNOTATIONS.equals(attributeName)) {
......@@ -486,6 +494,11 @@ public class ClassReader {
readModule(classVisitor, context, moduleOffset, modulePackagesOffset, moduleMainClass);
}
// Visit the NestHost attribute
Please register or sign in to reply
if (nestHostClass != null) {
classVisitor.visitNestHost(nestHostClass);
}
// Visit the EnclosingMethod attribute.
if (enclosingMethodOffset != 0) {
String className = readClass(enclosingMethodOffset, charBuffer);
......@@ -588,6 +601,16 @@ public class ClassReader {
attributes = nextAttribute;
}
// Visit the NestedMembers attribute
Please register or sign in to reply
if (nestMembersOffset != 0) {
int numberOfNestMembers = readUnsignedShort(nestMembersOffset);
int currentNestMemberOffset = nestMembersOffset + 2;
while (numberOfNestMembers-- > 0) {
classVisitor.visitNestMember(readClass(currentNestMemberOffset, charBuffer));
currentNestMemberOffset += 2;
}
}
// Visit the InnerClasses attribute.
if (innerClassesOffset != 0) {
int numberOfClasses = readUnsignedShort(innerClassesOffset);
......
......@@ -29,9 +29,10 @@ package org.objectweb.asm;
/**
* A visitor to visit a Java class. The methods of this class must be called in the following order:
* <tt>visit</tt> [ <tt>visitSource</tt> ] [ <tt>visitModule</tt> ][ <tt>visitOuterClass</tt> ] (
* <tt>visitAnnotation</tt> | <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* (
* <tt>visitInnerClass</tt> | <tt>visitField</tt> | <tt>visitMethod</tt> )* <tt>visitEnd</tt>.
* <tt>visit</tt> [ <tt>visitSource</tt> ] [ <tt>visitModule</tt> ][ <tt>visitNestHost</tt> ][
* <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> | <tt>visitTypeAnnotation</tt> |
* <tt>visitAttribute</tt> )* ( <tt>visitNestMember</tt> | <tt>visitInnerClass</tt> |
* <tt>visitField</tt> | <tt>visitMethod</tt> )* <tt>visitEnd</tt>.
*
* @author Eric Bruneton
*/
......@@ -134,6 +135,21 @@ public abstract class ClassVisitor {
return null;
}
/**
* Visits the nest host class of the current class. A nest is a set of classes of the same package
* that share access to their private members. The host class should list the current class as
* {@link #visitNestMember(String) nest member}. This method must be called only once and only if
* the current class is a member of a nest. A class is implicitly its own nest, so it's invalid to
* call this method with the current class as argument.
*
* @param nestHost the internal name of the host class of the nest.
*/
public void visitNestHost(final String nestHost) {
if (cv != null) {
cv.visitNestHost(nestHost);
}
}
/**
* Visits the enclosing class of the class. This method must be called only if the class has an
* enclosing class.
......@@ -202,6 +218,19 @@ public abstract class ClassVisitor {
}
}
/**
* Visits a member of the nest. A nest is a set of classes of the same package that share access
* to their private members. The nest member should declare the current class as its {@link
* #visitNestMember(String) host class}.
*
* @param nestMember the internal name of a nest member.
*/
public void visitNestMember(String nestMember) {
if (cv != null) {
cv.visitNestMember(nestMember);
}
}
/**
* Visits information about an inner class. This inner class is not necessarily a member of the
* class being visited.
......
......@@ -115,11 +115,20 @@ public class ClassWriter extends ClassVisitor {
*/
private MethodWriter lastMethod;
/** The host_class_index field of the NestHost attribute, or 0. */
Please register or sign in to reply
private int nestHostClassIndex;
/** The number_of_classes field of the NestMembers attribute, or 0. */
private int numberOfNestMemberClasses;
/** The 'classes' array of the NestMembers attribute, or <tt>null</tt>. */
private ByteVector nestMemberClasses;
/** The number_of_classes field of the InnerClasses attribute, or 0. */
private int numberOfClasses;
private int numberOfInnerClasses;
/** The 'classes' array of the InnerClasses attribute, or <tt>null</tt>. */
private ByteVector classes;
private ByteVector innerClasses;
/** The class_index field of the EnclosingMethod attribute, or 0. */
private int enclosingClassIndex;
......@@ -280,6 +289,11 @@ public class ClassWriter extends ClassVisitor {
version == null ? 0 : symbolTable.addConstantUtf8(version));
}
@Override
public void visitNestHost(final String nestHost) {
nestHostClassIndex = symbolTable.addConstantClass(nestHost).index;
}
@Override
public final void visitOuterClass(
final String owner, final String name, final String descriptor) {
......@@ -332,11 +346,20 @@ public class ClassWriter extends ClassVisitor {
firstAttribute = attribute;
}
@Override
public void visitNestMember(final String nestMember) {
if (nestMemberClasses == null) {
nestMemberClasses = new ByteVector();
}
++numberOfNestMemberClasses;
innerClasses.putShort(symbolTable.addConstantClass(nestMember).index);
}
@Override
public final void visitInnerClass(
final String name, final String outerName, final String innerName, final int access) {
if (classes == null) {
classes = new ByteVector();
if (innerClasses == null) {
innerClasses = new ByteVector();
}
// Section 4.7.6 of the JVMS states "Every CONSTANT_Class_info entry in the constant_pool table
// which represents a class or interface C that is not a package member must have exactly one
......@@ -346,12 +369,12 @@ public class ClassWriter extends ClassVisitor {
// the info field. This trick allows duplicate detection in O(1) time.
Symbol nameSymbol = symbolTable.addConstantClass(name);
if (nameSymbol.info == 0) {
++numberOfClasses;
classes.putShort(nameSymbol.index);
classes.putShort(outerName == null ? 0 : symbolTable.addConstantClass(outerName).index);
classes.putShort(innerName == null ? 0 : symbolTable.addConstantUtf8(innerName));
classes.putShort(access);
nameSymbol.info = numberOfClasses;
++numberOfInnerClasses;
innerClasses.putShort(nameSymbol.index);
innerClasses.putShort(outerName == null ? 0 : symbolTable.addConstantClass(outerName).index);
innerClasses.putShort(innerName == null ? 0 : symbolTable.addConstantUtf8(innerName));
innerClasses.putShort(access);
nameSymbol.info = numberOfInnerClasses;
} else {
// Compare the inner classes entry nameSymbol.info - 1 with the arguments of this method and
// throw an exception if there is a difference?
......@@ -428,9 +451,9 @@ public class ClassWriter extends ClassVisitor {
}
// For ease of reference, we use here the same attribute order as in Section 4.7 of the JVMS.
int attributesCount = 0;
if (classes != null) {
if (innerClasses != null) {
++attributesCount;
size += 8 + classes.length;
size += 8 + innerClasses.length;
symbolTable.addConstantUtf8(Constants.INNER_CLASSES);
}
if (enclosingClassIndex != 0) {
......@@ -438,6 +461,16 @@ public class ClassWriter extends ClassVisitor {
size += 10;
symbolTable.addConstantUtf8(Constants.ENCLOSING_METHOD);
}
if (nestHostClassIndex != 0) {
Please register or sign in to reply
++attributesCount;
size += 8;
symbolTable.addConstantUtf8(Constants.NEST_HOST);
}
if (nestMemberClasses != null) {
++attributesCount;
size += 8 + nestMemberClasses.length;
symbolTable.addConstantUtf8(Constants.NEST_MEMBERS);
}
if ((accessFlags & Opcodes.ACC_SYNTHETIC) != 0 && (version & 0xFFFF) < Opcodes.V1_5) {
++attributesCount;
size += 6;
......@@ -535,12 +568,12 @@ public class ClassWriter extends ClassVisitor {
}
// For ease of reference, we use here the same attribute order as in Section 4.7 of the JVMS.
result.putShort(attributesCount);
if (classes != null) {
if (innerClasses != null) {
result
.putShort(symbolTable.addConstantUtf8(Constants.INNER_CLASSES))
.putInt(classes.length + 2)
.putShort(numberOfClasses)
.putByteArray(classes.data, 0, classes.length);
.putInt(innerClasses.length + 2)
.putShort(numberOfInnerClasses)
.putByteArray(innerClasses.data, 0, innerClasses.length);
}
if (enclosingClassIndex != 0) {
result
......@@ -549,6 +582,19 @@ public class ClassWriter extends ClassVisitor {
.putShort(enclosingClassIndex)
.putShort(enclosingMethodIndex);
}
if (nestHostClassIndex != 0) {
Please register or sign in to reply
result
.putShort(symbolTable.addConstantUtf8(Constants.NEST_HOST))
.putInt(2)
.putShort(nestHostClassIndex);
}
if (nestMemberClasses != null) {
result
.putShort(symbolTable.addConstantUtf8(Constants.NEST_MEMBERS))
.putInt(nestMemberClasses.length + 2)
.putShort(numberOfNestMemberClasses)
.putByteArray(nestMemberClasses.data, 0, nestMemberClasses.length);
}
if ((accessFlags & Opcodes.ACC_SYNTHETIC) != 0 && (version & 0xFFFF) < Opcodes.V1_5) {
result.putShort(symbolTable.addConstantUtf8(Constants.SYNTHETIC)).putInt(0);
}
......
......@@ -31,7 +31,7 @@ package org.objectweb.asm;
* Defines additional JVM opcodes, access flags and constants which are not part of the ASM public
* API.
*
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-6.html">JVMS 6</a>
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-6.html">JVMS 6</a>
* @author Eric Bruneton
*/
final class Constants implements Opcodes {
......@@ -39,7 +39,7 @@ final class Constants implements Opcodes {
private Constants() {}
// The ClassFile attribute names, in the order they are defined in
// https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7-300.
// https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html#jvms-4.7-300.
static final String CONSTANT_VALUE = "ConstantValue";
static final String CODE = "Code";
......@@ -68,6 +68,8 @@ final class Constants implements Opcodes {
static final String MODULE = "Module";
static final String MODULE_PACKAGES = "ModulePackages";
static final String MODULE_MAIN_CLASS = "ModuleMainClass";
static final String NEST_HOST = "NestHost";
static final String NEST_MEMBERS = "NestMembers";
// ASM specific access flags.
// WARNING: the 16 least significant bits must NOT be used, to avoid conflicts with standard
......
......@@ -34,7 +34,7 @@ package org.objectweb.asm;
* xSTORE_n opcodes are therefore not defined in this interface. Likewise for LDC, automatically
* replaced by LDC_W or LDC2_W when necessary, WIDE, GOTO_W and JSR_W.
*
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-6.html">JVMS 6</a>
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-6.html">JVMS 6</a>
* @author Eric Bruneton
* @author Eugene Kuleshov
*/
......@@ -59,6 +59,7 @@ public interface Opcodes {
int V1_8 = 0 << 16 | 52;
int V9 = 0 << 16 | 53;
int V10 = 0 << 16 | 54;
int V11 = 0 << 16 | 55;
// Access flags values, defined in
// - https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.1-200-E.1
......
......@@ -44,7 +44,7 @@ subprojects {
apply plugin: 'org.junit.platform.gradle.plugin'
junitPlatform { filters { engines { 'junit-jupiter' } } }
group = 'org.ow2.asm'
version = 6.1
version = 7.0
sourceCompatibility = '1.6'
targetCompatibility = '1.6'
ext.provides = [] // The provided java packages, e.g. ['org.objectweb.asm']
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment