mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
external build: ensure NotNull and PatterValidator instrumenters do not break the build because of failed class resolution when they actually do not modify the bytecode (IDEA-96384 Cannot compile : Class not found: org/springframework/beans/factory/InitializingBean)
This commit is contained in:
+2
-2
@@ -67,7 +67,7 @@ public class InstrumentationClassFinder {
|
||||
protected Class findClass(String name) throws ClassNotFoundException {
|
||||
final InputStream is = lookupClassBeforeClasspath(name.replace('.', '/'));
|
||||
if (is == null) {
|
||||
throw new ClassNotFoundException(name);
|
||||
throw new ClassNotFoundException("Class not found: " + name.replace('/', '.')); // ensure presentable class name in error message
|
||||
}
|
||||
try {
|
||||
final byte[] bytes = loadBytes(is);
|
||||
@@ -104,7 +104,7 @@ public class InstrumentationClassFinder {
|
||||
final InputStream is = getClassBytesAsStream(internalName);
|
||||
|
||||
if (is == null) {
|
||||
throw new ClassNotFoundException("Class not found: " + internalName);
|
||||
throw new ClassNotFoundException("Class not found: " + name.replace('/', '.')); // ensure presentable class name in error message
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
+28
-10
@@ -39,6 +39,7 @@ public class NotNullVerifyingInstrumenter extends ClassVisitor implements Opcode
|
||||
|
||||
private String myClassName;
|
||||
private boolean myIsModification = false;
|
||||
private RuntimeException myPostponedError;
|
||||
|
||||
public NotNullVerifyingInstrumenter(final ClassVisitor classVisitor) {
|
||||
super(Opcodes.ASM4, classVisitor);
|
||||
@@ -66,12 +67,8 @@ public class NotNullVerifyingInstrumenter extends ClassVisitor implements Opcode
|
||||
private boolean myIsNotNull = false;
|
||||
private Label myStartGeneratedCodeLabel;
|
||||
|
||||
public AnnotationVisitor visitParameterAnnotation(
|
||||
final int parameter,
|
||||
final String anno,
|
||||
final boolean visible) {
|
||||
AnnotationVisitor av;
|
||||
av = mv.visitParameterAnnotation(parameter, anno, visible);
|
||||
public AnnotationVisitor visitParameterAnnotation(final int parameter, final String anno, final boolean visible) {
|
||||
final AnnotationVisitor av = mv.visitParameterAnnotation(parameter, anno, visible);
|
||||
if (isReferenceType(args[parameter]) && anno.equals(NOT_NULL_TYPE)) {
|
||||
myNotNullParams.add(new Integer(parameter));
|
||||
}
|
||||
@@ -85,8 +82,7 @@ public class NotNullVerifyingInstrumenter extends ClassVisitor implements Opcode
|
||||
@Override
|
||||
public AnnotationVisitor visitAnnotation(String anno, boolean isRuntime) {
|
||||
final AnnotationVisitor av = mv.visitAnnotation(anno, isRuntime);
|
||||
if (isReferenceType(returnType) &&
|
||||
anno.equals(NOT_NULL_TYPE)) {
|
||||
if (isReferenceType(returnType) && anno.equals(NOT_NULL_TYPE)) {
|
||||
myIsNotNull = true;
|
||||
}
|
||||
|
||||
@@ -144,6 +140,7 @@ public class NotNullVerifyingInstrumenter extends ClassVisitor implements Opcode
|
||||
mv.visitLabel(end);
|
||||
|
||||
myIsModification = true;
|
||||
processPostponedErrors();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -151,8 +148,8 @@ public class NotNullVerifyingInstrumenter extends ClassVisitor implements Opcode
|
||||
try {
|
||||
super.visitMaxs(maxStack, maxLocals);
|
||||
}
|
||||
catch (ArrayIndexOutOfBoundsException e) {
|
||||
throw new ArrayIndexOutOfBoundsException("Maximums processing failed for " + myClassName + "." + name + ": " + e.getMessage());
|
||||
catch (Throwable e) {
|
||||
registerError(name, "visitMaxs", e);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -161,4 +158,25 @@ public class NotNullVerifyingInstrumenter extends ClassVisitor implements Opcode
|
||||
private static boolean isReferenceType(final Type type) {
|
||||
return type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY;
|
||||
}
|
||||
|
||||
private void registerError(String methodName, String operationName, Throwable e) {
|
||||
if (myPostponedError == null) {
|
||||
// throw the first error that occurred
|
||||
Throwable err = e.getCause();
|
||||
if (err == null) {
|
||||
err = e;
|
||||
}
|
||||
myPostponedError = new RuntimeException("Operation '" + operationName + "' failed for " + myClassName + "." + methodName + "(): " + err.getMessage(), err);
|
||||
}
|
||||
if (myIsModification) {
|
||||
processPostponedErrors();
|
||||
}
|
||||
}
|
||||
|
||||
private void processPostponedErrors() {
|
||||
final RuntimeException error = myPostponedError;
|
||||
if (error != null) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+22
-17
@@ -134,30 +134,35 @@ class InstrumentationAdapter extends MethodVisitor implements Opcodes {
|
||||
}
|
||||
|
||||
public void visitMaxs(int maxStack, int maxLocals) {
|
||||
if (myAssertLabel != null) {
|
||||
try {
|
||||
if (myAssertLabel != null) {
|
||||
|
||||
// next index for synthetic variable that holds return value
|
||||
final int var = maxLocals + 1;
|
||||
// next index for synthetic variable that holds return value
|
||||
final int var = maxLocals + 1;
|
||||
|
||||
mv.visitLabel(myAssertLabel);
|
||||
mv.visitLabel(myAssertLabel);
|
||||
|
||||
mv.visitVarInsn(Opcodes.ASTORE, var);
|
||||
mv.visitVarInsn(Opcodes.ASTORE, var);
|
||||
|
||||
final Label end = new Label();
|
||||
addPatternTest(myMethodPattern.patternIndex, end, var);
|
||||
final Label end = new Label();
|
||||
addPatternTest(myMethodPattern.patternIndex, end, var);
|
||||
|
||||
addPatternAssertion(MessageFormat.format("Return value of method {0}.{1} annotated as @{2} does not match pattern {3}",
|
||||
myInstrumenter.myClassName, myMethodName, myMethodPattern.annotation,
|
||||
myMethodPattern.pattern), true);
|
||||
addPatternAssertion(MessageFormat.format("Return value of method {0}.{1} annotated as @{2} does not match pattern {3}",
|
||||
myInstrumenter.myClassName, myMethodName, myMethodPattern.annotation,
|
||||
myMethodPattern.pattern), true);
|
||||
|
||||
mv.visitLabel(end);
|
||||
mv.visitLocalVariable(RETURN_VALUE_NAME, PatternInstrumenter.JAVA_LANG_STRING, null, myAssertLabel, end, var);
|
||||
mv.visitLabel(end);
|
||||
mv.visitLocalVariable(RETURN_VALUE_NAME, PatternInstrumenter.JAVA_LANG_STRING, null, myAssertLabel, end, var);
|
||||
|
||||
mv.visitVarInsn(Opcodes.ALOAD, var);
|
||||
mv.visitInsn(Opcodes.ARETURN);
|
||||
mv.visitVarInsn(Opcodes.ALOAD, var);
|
||||
mv.visitInsn(Opcodes.ARETURN);
|
||||
}
|
||||
|
||||
super.visitMaxs(maxStack, maxLocals);
|
||||
}
|
||||
catch (Throwable e) {
|
||||
myInstrumenter.registerError(myMethodName, "visitMaxs", e);
|
||||
}
|
||||
|
||||
super.visitMaxs(maxStack, maxLocals);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"HardCodedStringLiteral"})
|
||||
@@ -194,7 +199,7 @@ class InstrumentationAdapter extends MethodVisitor implements Opcodes {
|
||||
addThrow("java/lang/IllegalArgumentException", "(Ljava/lang/String;)V", message);
|
||||
}
|
||||
}
|
||||
myInstrumenter.myInstrumented = true;
|
||||
myInstrumenter.markInstrumented();
|
||||
}
|
||||
|
||||
private void addThrow(@NonNls String throwableClass, @NonNls String ctorSignature, String message) {
|
||||
|
||||
+29
-1
@@ -46,7 +46,8 @@ class PatternInstrumenter extends ClassVisitor implements Opcodes {
|
||||
private final Set<String> myProcessedAnnotations = new HashSet<String>(); // checked annotation classes
|
||||
|
||||
String myClassName;
|
||||
boolean myInstrumented;
|
||||
private boolean myInstrumented;
|
||||
private RuntimeException myPostponedError;
|
||||
boolean myIsNonStaticInnerClass;
|
||||
|
||||
public PatternInstrumenter(@NotNull String patternAnnotationClassName, ClassVisitor classvisitor,
|
||||
@@ -66,6 +67,11 @@ class PatternInstrumenter extends ClassVisitor implements Opcodes {
|
||||
return myInstrumented;
|
||||
}
|
||||
|
||||
void markInstrumented() {
|
||||
myInstrumented = true;
|
||||
processPostponedErrors();
|
||||
}
|
||||
|
||||
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
|
||||
super.visit(version, access, name, signature, superName, interfaces);
|
||||
myClassName = name;
|
||||
@@ -273,4 +279,26 @@ class PatternInstrumenter extends ClassVisitor implements Opcodes {
|
||||
// todo
|
||||
}
|
||||
}
|
||||
|
||||
void registerError(String methodName, String operationName, Throwable e) {
|
||||
if (myPostponedError == null) {
|
||||
// throw the first error that occurred
|
||||
Throwable err = e.getCause();
|
||||
if (err == null) {
|
||||
err = e;
|
||||
}
|
||||
myPostponedError = new RuntimeException("Operation '" + operationName + "' failed for " + myClassName + "." + methodName + "(): " + err.getMessage(), err);
|
||||
}
|
||||
if (myInstrumented) {
|
||||
processPostponedErrors();
|
||||
}
|
||||
}
|
||||
|
||||
private void processPostponedErrors() {
|
||||
final RuntimeException error = myPostponedError;
|
||||
if (error != null) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user