Search in sources :

Example 1 with FailSafeClassReader

use of com.intellij.compiler.instrumentation.FailSafeClassReader in project intellij-community by JetBrains.

the class FormsInstrumenter method instrumentForms.

private Map<File, Collection<File>> instrumentForms(CompileContext context, ModuleChunk chunk, final Map<File, String> chunkSourcePath, final InstrumentationClassFinder finder, Collection<File> forms, OutputConsumer outConsumer) throws ProjectBuildException {
    final Map<File, Collection<File>> instrumented = new THashMap<>(FileUtil.FILE_HASHING_STRATEGY);
    final Map<String, File> class2form = new HashMap<>();
    final MyNestedFormLoader nestedFormsLoader = new MyNestedFormLoader(chunkSourcePath, ProjectPaths.getOutputPathsWithDependents(chunk), finder);
    for (File formFile : forms) {
        final LwRootContainer rootContainer;
        try {
            rootContainer = Utils.getRootContainer(formFile.toURI().toURL(), new CompiledClassPropertiesProvider(finder.getLoader()));
        } catch (AlienFormFileException e) {
            // ignore non-IDEA forms
            continue;
        } catch (UnexpectedFormElementException e) {
            context.processMessage(new CompilerMessage(getPresentableName(), BuildMessage.Kind.ERROR, e.getMessage(), formFile.getPath()));
            LOG.info(e);
            continue;
        } catch (UIDesignerException e) {
            context.processMessage(new CompilerMessage(getPresentableName(), BuildMessage.Kind.ERROR, e.getMessage(), formFile.getPath()));
            LOG.info(e);
            continue;
        } catch (Exception e) {
            throw new ProjectBuildException("Cannot process form file " + formFile.getAbsolutePath(), e);
        }
        final String classToBind = rootContainer.getClassToBind();
        if (classToBind == null) {
            continue;
        }
        final CompiledClass compiled = findClassFile(outConsumer, classToBind);
        if (compiled == null) {
            context.processMessage(new CompilerMessage(getPresentableName(), BuildMessage.Kind.WARNING, "Class to bind does not exist: " + classToBind, formFile.getAbsolutePath()));
            continue;
        }
        final File alreadyProcessedForm = class2form.get(classToBind);
        if (alreadyProcessedForm != null) {
            context.processMessage(new CompilerMessage(getPresentableName(), BuildMessage.Kind.WARNING, formFile.getAbsolutePath() + ": The form is bound to the class " + classToBind + ".\nAnother form " + alreadyProcessedForm.getAbsolutePath() + " is also bound to this class", formFile.getAbsolutePath()));
            continue;
        }
        class2form.put(classToBind, formFile);
        for (File file : compiled.getSourceFiles()) {
            addBinding(file, formFile, instrumented);
        }
        try {
            context.processMessage(new ProgressMessage("Instrumenting forms... [" + chunk.getPresentableShortName() + "]"));
            final BinaryContent originalContent = compiled.getContent();
            final ClassReader classReader = new FailSafeClassReader(originalContent.getBuffer(), originalContent.getOffset(), originalContent.getLength());
            final int version = ClassProcessingBuilder.getClassFileVersion(classReader);
            final InstrumenterClassWriter classWriter = new InstrumenterClassWriter(classReader, ClassProcessingBuilder.getAsmClassWriterFlags(version), finder);
            final AsmCodeGenerator codeGenerator = new AsmCodeGenerator(rootContainer, finder, nestedFormsLoader, false, classWriter);
            final byte[] patchedBytes = codeGenerator.patchClass(classReader);
            if (patchedBytes != null) {
                compiled.setContent(new BinaryContent(patchedBytes));
            }
            final FormErrorInfo[] warnings = codeGenerator.getWarnings();
            for (final FormErrorInfo warning : warnings) {
                context.processMessage(new CompilerMessage(getPresentableName(), BuildMessage.Kind.WARNING, warning.getErrorMessage(), formFile.getAbsolutePath()));
            }
            final FormErrorInfo[] errors = codeGenerator.getErrors();
            if (errors.length > 0) {
                StringBuilder message = new StringBuilder();
                for (final FormErrorInfo error : errors) {
                    if (message.length() > 0) {
                        message.append("\n");
                    }
                    message.append(formFile.getAbsolutePath()).append(": ").append(error.getErrorMessage());
                }
                context.processMessage(new CompilerMessage(getPresentableName(), BuildMessage.Kind.ERROR, message.toString()));
            }
        } catch (Exception e) {
            context.processMessage(new CompilerMessage(getPresentableName(), BuildMessage.Kind.ERROR, "Forms instrumentation failed" + e.getMessage(), formFile.getAbsolutePath()));
        }
    }
    return instrumented;
}
Also used : ProgressMessage(org.jetbrains.jps.incremental.messages.ProgressMessage) CompilerMessage(org.jetbrains.jps.incremental.messages.CompilerMessage) THashMap(gnu.trove.THashMap) LwRootContainer(com.intellij.uiDesigner.lw.LwRootContainer) THashMap(gnu.trove.THashMap) InstrumenterClassWriter(com.intellij.compiler.instrumentation.InstrumenterClassWriter) CompiledClassPropertiesProvider(com.intellij.uiDesigner.lw.CompiledClassPropertiesProvider) FailSafeClassReader(com.intellij.compiler.instrumentation.FailSafeClassReader) ClassReader(org.jetbrains.org.objectweb.asm.ClassReader) FailSafeClassReader(com.intellij.compiler.instrumentation.FailSafeClassReader)

Example 2 with FailSafeClassReader

use of com.intellij.compiler.instrumentation.FailSafeClassReader in project intellij-community by JetBrains.

the class Javac2 method instrumentNotNull.

/**
   * Instrument classes with NotNull annotations
   *
   * @param dir    the directory with classes to instrument (the directory is processed recursively)
   * @param finder the classloader to use
   * @return the amount of classes actually affected by instrumentation
   */
private int instrumentNotNull(File dir, final InstrumentationClassFinder finder) {
    int instrumented = 0;
    final File[] files = dir.listFiles();
    for (int i = 0; i < files.length; i++) {
        File file = files[i];
        final String name = file.getName();
        if (name.endsWith(".class")) {
            final String path = file.getPath();
            log("Adding @NotNull assertions to " + path, Project.MSG_VERBOSE);
            try {
                final FileInputStream inputStream = new FileInputStream(file);
                try {
                    FailSafeClassReader reader = new FailSafeClassReader(inputStream);
                    int version = getClassFileVersion(reader);
                    if (version >= Opcodes.V1_5 && !shouldBeSkippedByAnnotationPattern(reader)) {
                        ClassWriter writer = new InstrumenterClassWriter(reader, getAsmClassWriterFlags(version), finder);
                        if (NotNullVerifyingInstrumenter.processClassFile(reader, writer, myNotNullAnnotations.split(";"))) {
                            final FileOutputStream fileOutputStream = new FileOutputStream(path);
                            try {
                                fileOutputStream.write(writer.toByteArray());
                                instrumented++;
                            } finally {
                                fileOutputStream.close();
                            }
                        }
                    }
                } finally {
                    inputStream.close();
                }
            } catch (IOException e) {
                log("Failed to instrument @NotNull assertion for " + path + ": " + e.getMessage(), Project.MSG_WARN);
            } catch (Exception e) {
                fireError("@NotNull instrumentation failed for " + path + ": " + e.toString());
            }
        } else if (file.isDirectory()) {
            instrumented += instrumentNotNull(file, finder);
        }
    }
    return instrumented;
}
Also used : InstrumenterClassWriter(com.intellij.compiler.instrumentation.InstrumenterClassWriter) FailSafeClassReader(com.intellij.compiler.instrumentation.FailSafeClassReader) InstrumenterClassWriter(com.intellij.compiler.instrumentation.InstrumenterClassWriter) MalformedURLException(java.net.MalformedURLException) BuildException(org.apache.tools.ant.BuildException)

Example 3 with FailSafeClassReader

use of com.intellij.compiler.instrumentation.FailSafeClassReader in project intellij-community by JetBrains.

the class OutputFilesSink method save.

public void save(@NotNull final OutputFileObject fileObject) {
    final BinaryContent content = fileObject.getContent();
    final File srcFile = fileObject.getSourceFile();
    boolean isTemp = false;
    final JavaFileObject.Kind outKind = fileObject.getKind();
    if (srcFile != null && content != null) {
        final String sourcePath = FileUtil.toSystemIndependentName(srcFile.getPath());
        final JavaSourceRootDescriptor rootDescriptor = myContext.getProjectDescriptor().getBuildRootIndex().findJavaRootDescriptor(myContext, srcFile);
        try {
            if (rootDescriptor != null) {
                isTemp = rootDescriptor.isTemp;
                if (!isTemp) {
                    // first, handle [src->output] mapping and register paths for files_generated event
                    if (outKind == JavaFileObject.Kind.CLASS) {
                        // todo: avoid array copying?
                        myOutputConsumer.registerCompiledClass(rootDescriptor.target, new CompiledClass(fileObject.getFile(), srcFile, fileObject.getClassName(), content));
                    } else {
                        myOutputConsumer.registerOutputFile(rootDescriptor.target, fileObject.getFile(), Collections.<String>singleton(sourcePath));
                    }
                }
            } else {
                // was not able to determine the source root descriptor or the source root is excluded from compilation (e.g. for annotation processors)
                if (outKind == JavaFileObject.Kind.CLASS) {
                    myOutputConsumer.registerCompiledClass(null, new CompiledClass(fileObject.getFile(), srcFile, fileObject.getClassName(), content));
                }
            }
        } catch (IOException e) {
            myContext.processMessage(new CompilerMessage(JavaBuilder.BUILDER_NAME, e));
        }
        if (!isTemp && outKind == JavaFileObject.Kind.CLASS) {
            // register in mappings any non-temp class file
            try {
                final ClassReader reader = new FailSafeClassReader(content.getBuffer(), content.getOffset(), content.getLength());
                myMappingsCallback.associate(FileUtil.toSystemIndependentName(fileObject.getFile().getPath()), sourcePath, reader);
            } catch (Throwable e) {
                // need this to make sure that unexpected errors in, for example, ASM will not ruin the compilation  
                final String message = "Class dependency information may be incomplete! Error parsing generated class " + fileObject.getFile().getPath();
                LOG.info(message, e);
                myContext.processMessage(new CompilerMessage(JavaBuilder.BUILDER_NAME, BuildMessage.Kind.WARNING, message + "\n" + CompilerMessage.getTextFromThrowable(e), sourcePath));
            }
        }
    }
    if (outKind == JavaFileObject.Kind.CLASS) {
        myContext.processMessage(new ProgressMessage("Writing classes... " + myChunkName));
        if (!isTemp && srcFile != null) {
            mySuccessfullyCompiled.add(srcFile);
        }
    }
}
Also used : ProgressMessage(org.jetbrains.jps.incremental.messages.ProgressMessage) CompilerMessage(org.jetbrains.jps.incremental.messages.CompilerMessage) CompiledClass(org.jetbrains.jps.incremental.CompiledClass) IOException(java.io.IOException) BinaryContent(org.jetbrains.jps.incremental.BinaryContent) FailSafeClassReader(com.intellij.compiler.instrumentation.FailSafeClassReader) ClassReader(org.jetbrains.org.objectweb.asm.ClassReader) JavaSourceRootDescriptor(org.jetbrains.jps.builders.java.JavaSourceRootDescriptor) File(java.io.File) FailSafeClassReader(com.intellij.compiler.instrumentation.FailSafeClassReader)

Example 4 with FailSafeClassReader

use of com.intellij.compiler.instrumentation.FailSafeClassReader in project intellij-community by JetBrains.

the class JpsGroovycRunner method updateDependencies.

void updateDependencies(CompileContext context, List<File> toCompile, MultiMap<T, GroovycOutputParser.OutputItem> successfullyCompiled, final GroovyOutputConsumer outputConsumer, Builder builder) throws IOException {
    JavaBuilderUtil.registerFilesToCompile(context, toCompile);
    if (!successfullyCompiled.isEmpty()) {
        final Callbacks.Backend callback = JavaBuilderUtil.getDependenciesRegistrar(context);
        for (Map.Entry<T, Collection<GroovycOutputParser.OutputItem>> entry : successfullyCompiled.entrySet()) {
            final T target = entry.getKey();
            final Collection<GroovycOutputParser.OutputItem> compiled = entry.getValue();
            for (GroovycOutputParser.OutputItem item : compiled) {
                final String sourcePath = FileUtil.toSystemIndependentName(item.sourcePath);
                final String outputPath = FileUtil.toSystemIndependentName(item.outputPath);
                final File outputFile = new File(outputPath);
                final File srcFile = new File(sourcePath);
                try {
                    final byte[] bytes = FileUtil.loadFileBytes(outputFile);
                    if (Utils.IS_TEST_MODE || LOG.isDebugEnabled()) {
                        LOG.info("registerCompiledClass " + outputFile + " from " + srcFile);
                    }
                    outputConsumer.registerCompiledClass(target, srcFile, outputFile, bytes);
                    callback.associate(outputPath, sourcePath, new FailSafeClassReader(bytes));
                } catch (Throwable e) {
                    // need this to make sure that unexpected errors in, for example, ASM will not ruin the compilation
                    final String message = "Class dependency information may be incomplete! Error parsing generated class " + item.outputPath;
                    LOG.info(message, e);
                    context.processMessage(new CompilerMessage(builder.getPresentableName(), BuildMessage.Kind.WARNING, message + "\n" + CompilerMessage.getTextFromThrowable(e), sourcePath));
                }
                JavaBuilderUtil.registerSuccessfullyCompiled(context, srcFile);
            }
        }
    }
}
Also used : CompilerMessage(org.jetbrains.jps.incremental.messages.CompilerMessage) Callbacks(org.jetbrains.jps.builders.java.dependencyView.Callbacks) MultiMap(com.intellij.util.containers.MultiMap) File(java.io.File) FailSafeClassReader(com.intellij.compiler.instrumentation.FailSafeClassReader)

Example 5 with FailSafeClassReader

use of com.intellij.compiler.instrumentation.FailSafeClassReader in project intellij-community by JetBrains.

the class NotNullVerifyingInstrumenterTest method prepareTest.

private Class prepareTest(boolean withDebugInfo, String... notNullAnnos) throws IOException {
    String base = JavaTestUtil.getJavaTestDataPath() + "/compiler/notNullVerification/";
    final String baseClassName = getTestName(false);
    String path = base + baseClassName;
    String javaPath = path + ".java";
    File classesDir = FileUtil.createTempDirectory(baseClassName, "output");
    try {
        List<String> cmdLine = ContainerUtil.newArrayList("-classpath", base + "annotations.jar", "-d", classesDir.getAbsolutePath());
        if (withDebugInfo) {
            cmdLine.add("-g");
        }
        cmdLine.add(javaPath);
        com.sun.tools.javac.Main.compile(ArrayUtil.toStringArray(cmdLine));
        Class mainClass = null;
        final File[] files = classesDir.listFiles();
        assertNotNull(files);
        Arrays.sort(files, (o1, o2) -> o1.getName().compareToIgnoreCase(o2.getName()));
        boolean modified = false;
        MyClassLoader classLoader = new MyClassLoader(getClass().getClassLoader());
        for (File file : files) {
            final String fileName = file.getName();
            byte[] content = FileUtil.loadFileBytes(file);
            FailSafeClassReader reader = new FailSafeClassReader(content, 0, content.length);
            ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_FRAMES);
            modified |= NotNullVerifyingInstrumenter.processClassFile(reader, writer, notNullAnnos);
            byte[] instrumented = writer.toByteArray();
            final String className = FileUtil.getNameWithoutExtension(fileName);
            final Class aClass = classLoader.doDefineClass(className, instrumented);
            if (className.equals(baseClassName)) {
                mainClass = aClass;
            }
        }
        assertTrue(modified);
        assertNotNull("Class " + baseClassName + " not found!", mainClass);
        return mainClass;
    } finally {
        FileUtil.delete(classesDir);
    }
}
Also used : File(java.io.File) FailSafeClassReader(com.intellij.compiler.instrumentation.FailSafeClassReader) ClassWriter(org.jetbrains.org.objectweb.asm.ClassWriter)

Aggregations

FailSafeClassReader (com.intellij.compiler.instrumentation.FailSafeClassReader)6 CompilerMessage (org.jetbrains.jps.incremental.messages.CompilerMessage)4 InstrumenterClassWriter (com.intellij.compiler.instrumentation.InstrumenterClassWriter)3 File (java.io.File)3 ClassReader (org.jetbrains.org.objectweb.asm.ClassReader)3 ProgressMessage (org.jetbrains.jps.incremental.messages.ProgressMessage)2 ClassWriter (org.jetbrains.org.objectweb.asm.ClassWriter)2 CompiledClassPropertiesProvider (com.intellij.uiDesigner.lw.CompiledClassPropertiesProvider)1 LwRootContainer (com.intellij.uiDesigner.lw.LwRootContainer)1 MultiMap (com.intellij.util.containers.MultiMap)1 THashMap (gnu.trove.THashMap)1 IOException (java.io.IOException)1 MalformedURLException (java.net.MalformedURLException)1 BuildException (org.apache.tools.ant.BuildException)1 JavaSourceRootDescriptor (org.jetbrains.jps.builders.java.JavaSourceRootDescriptor)1 Callbacks (org.jetbrains.jps.builders.java.dependencyView.Callbacks)1 BinaryContent (org.jetbrains.jps.incremental.BinaryContent)1 CompiledClass (org.jetbrains.jps.incremental.CompiledClass)1