diff --git a/java/compiler/instrumentation-util/src/com/intellij/compiler/notNullVerification/NotNullVerifyingInstrumenter.java b/java/compiler/instrumentation-util/src/com/intellij/compiler/notNullVerification/NotNullVerifyingInstrumenter.java index adb7e1d389db..cbcf081feef7 100644 --- a/java/compiler/instrumentation-util/src/com/intellij/compiler/notNullVerification/NotNullVerifyingInstrumenter.java +++ b/java/compiler/instrumentation-util/src/com/intellij/compiler/notNullVerification/NotNullVerifyingInstrumenter.java @@ -15,6 +15,7 @@ */ package com.intellij.compiler.notNullVerification; +import com.intellij.compiler.instrumentation.FailSafeClassReader; import com.intellij.compiler.instrumentation.FailSafeMethodVisitor; import org.jetbrains.org.objectweb.asm.*; @@ -55,7 +56,7 @@ public class NotNullVerifyingInstrumenter extends ClassVisitor implements Opcode myMethodParamNames = getAllParameterNames(reader); } - public static boolean processClassFile(final ClassReader reader, final ClassVisitor writer) { + public static boolean processClassFile(final FailSafeClassReader reader, final ClassVisitor writer) { final NotNullVerifyingInstrumenter instrumenter = new NotNullVerifyingInstrumenter(writer, reader); reader.accept(instrumenter, 0); return instrumenter.isModification(); @@ -124,7 +125,7 @@ public class NotNullVerifyingInstrumenter extends ClassVisitor implements Opcode @Override public MethodVisitor visitMethod(final int access, final String name, String desc, String signature, String[] exceptions) { if ((access & Opcodes.ACC_BRIDGE) != 0) { - return super.visitMethod(access, name, desc, signature, exceptions); + return new FailSafeMethodVisitor(Opcodes.ASM5, super.visitMethod(access, name, desc, signature, exceptions)); } final Type[] args = Type.getArgumentTypes(desc); diff --git a/java/compiler/javac2/src/com/intellij/ant/Javac2.java b/java/compiler/javac2/src/com/intellij/ant/Javac2.java index 94b14306be0c..60de09471eb6 100644 --- a/java/compiler/javac2/src/com/intellij/ant/Javac2.java +++ b/java/compiler/javac2/src/com/intellij/ant/Javac2.java @@ -432,7 +432,7 @@ public class Javac2 extends Javac { try { final FileInputStream inputStream = new FileInputStream(file); try { - ClassReader reader = new FailSafeClassReader(inputStream); + FailSafeClassReader reader = new FailSafeClassReader(inputStream); int version = getClassFileVersion(reader); diff --git a/java/java-tests/testData/compiler/notNullVerification/MalformedBytecode.java b/java/java-tests/testData/compiler/notNullVerification/MalformedBytecode.java new file mode 100644 index 000000000000..ffac2bf2b7f4 --- /dev/null +++ b/java/java-tests/testData/compiler/notNullVerification/MalformedBytecode.java @@ -0,0 +1,34 @@ +import java.lang.annotation.*; +import java.util.*; +import org.jetbrains.annotations.NotNull; + +public abstract class MalformedBytecode { + + public static void main() { + List list = new ArrayList<>(); + list.add("aaa"); + list.add(null); + list.add("bbb"); + new NullTest2().processList(list); + } + + public static abstract class NullTest1 { + protected abstract void processList(T list); + } + + public static class NullTest2> extends NullTest1 { + public void processList(C list) { + for (@Nullable T s1 : list) { + handle(s1); + } + } + + void handle(@NotNull T arg) { + } + + } +} + +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.TYPE_USE }) +@interface Nullable { } \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/compiler/notNullVerification/NotNullVerifyingInstrumenterTest.java b/java/java-tests/testSrc/com/intellij/compiler/notNullVerification/NotNullVerifyingInstrumenterTest.java index db302ddf0770..aa9f566cfa70 100644 --- a/java/java-tests/testSrc/com/intellij/compiler/notNullVerification/NotNullVerifyingInstrumenterTest.java +++ b/java/java-tests/testSrc/com/intellij/compiler/notNullVerification/NotNullVerifyingInstrumenterTest.java @@ -16,19 +16,14 @@ package com.intellij.compiler.notNullVerification; import com.intellij.JavaTestUtil; -import com.intellij.compiler.PsiClassWriter; -import com.intellij.openapi.util.SystemInfo; +import com.intellij.compiler.instrumentation.FailSafeClassReader; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.testFramework.UsefulTestCase; -import com.intellij.testFramework.fixtures.IdeaProjectTestFixture; -import com.intellij.testFramework.fixtures.JavaTestFixtureFactory; -import com.intellij.testFramework.fixtures.TestFixtureBuilder; import com.intellij.util.ArrayUtil; import com.intellij.util.ExceptionUtil; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.Nullable; -import org.jetbrains.org.objectweb.asm.ClassReader; import org.jetbrains.org.objectweb.asm.ClassWriter; import java.io.File; @@ -44,28 +39,6 @@ import java.util.List; * @author yole */ public class NotNullVerifyingInstrumenterTest extends UsefulTestCase { - private boolean myJava6; - private IdeaProjectTestFixture myFixture; - - @Override - protected void setUp() throws Exception { - super.setUp(); - final JavaTestFixtureFactory fixtureFactory = JavaTestFixtureFactory.getFixtureFactory(); - final TestFixtureBuilder testFixtureBuilder = fixtureFactory.createLightFixtureBuilder(); - myFixture = testFixtureBuilder.getFixture(); - myFixture.setUp(); - myJava6 = SystemInfo.isJavaVersionAtLeast("1.6"); - } - - @Override - protected void tearDown() throws Exception { - try { - myFixture.tearDown(); - } - finally { - super.tearDown(); - } - } public void testSimpleReturn() throws Exception { Class testClass = prepareTest(); @@ -189,7 +162,12 @@ public class NotNullVerifyingInstrumenterTest extends UsefulTestCase { } } - private static void verifyCallThrowsException(String expectedError, @Nullable Object instance, Member member, @Nullable Object... args) throws Exception { + public void testMalformedBytecode() throws Exception { + Class testClass = prepareTest(false); + verifyCallThrowsException("Argument 0 for @NotNull parameter of MalformedBytecode$NullTest2.handle must not be null", null, testClass.getMethod("main")); + } + + private static void verifyCallThrowsException(String expectedError, @Nullable Object instance, Member member, Object... args) throws Exception { String exceptionText = null; try { if (member instanceof Constructor) { @@ -237,8 +215,8 @@ public class NotNullVerifyingInstrumenterTest extends UsefulTestCase { final String fileName = file.getName(); byte[] content = FileUtil.loadFileBytes(file); - ClassReader reader = new ClassReader(content, 0, content.length); - ClassWriter writer = new PsiClassWriter(myFixture.getProject(), myJava6); + FailSafeClassReader reader = new FailSafeClassReader(content, 0, content.length); + ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES); modified |= NotNullVerifyingInstrumenter.processClassFile(reader, writer); byte[] instrumented = writer.toByteArray(); diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/NotNullInstrumentingBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/NotNullInstrumentingBuilder.java index f46b6a54414e..0c4f2460c4f1 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/NotNullInstrumentingBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/NotNullInstrumentingBuilder.java @@ -15,8 +15,10 @@ */ package org.jetbrains.jps.incremental.instrumentation; +import com.intellij.compiler.instrumentation.FailSafeClassReader; import com.intellij.compiler.instrumentation.InstrumentationClassFinder; import com.intellij.compiler.notNullVerification.NotNullVerifyingInstrumenter; +import com.intellij.openapi.diagnostic.Logger; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.ModuleChunk; @@ -38,6 +40,7 @@ import java.io.File; * Date: 11/21/12 */ public class NotNullInstrumentingBuilder extends BaseInstrumentingBuilder{ + private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.instrumentation.NotNullInstrumentingBuilder"); public NotNullInstrumentingBuilder() { } @@ -73,17 +76,15 @@ public class NotNullInstrumentingBuilder extends BaseInstrumentingBuilder{ ClassWriter writer, InstrumentationClassFinder finder) { try { - if (NotNullVerifyingInstrumenter.processClassFile(reader, writer)) { + if (NotNullVerifyingInstrumenter.processClassFile((FailSafeClassReader)reader, writer)) { return new BinaryContent(writer.toByteArray()); } } catch (Throwable e) { - final StringBuilder msg = new StringBuilder(); - msg.append("@NotNull instrumentation failed "); + LOG.error(e); final File sourceFile = compiledClass.getSourceFile(); - msg.append(" for ").append(sourceFile.getName()); - msg.append(": ").append(e.getMessage()); - context.processMessage(new CompilerMessage(getPresentableName(), BuildMessage.Kind.ERROR, msg.toString(), sourceFile.getPath())); + String msg = "Cannot instrument " + sourceFile.getName() + ": " + e.getMessage(); + context.processMessage(new CompilerMessage(getPresentableName(), BuildMessage.Kind.ERROR, msg, sourceFile.getPath())); } return null; }