Search in sources :

Example 1 with InstrumenterClassWriter

use of com.intellij.compiler.instrumentation.InstrumenterClassWriter 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 InstrumenterClassWriter

use of com.intellij.compiler.instrumentation.InstrumenterClassWriter 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 InstrumenterClassWriter

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

the class Javac2 method instrumentForms.

/**
   * Instrument forms
   *
   * @param finder a classloader to use
   */
private void instrumentForms(final InstrumentationClassFinder finder) {
    // we instrument every file, because we cannot find which files should not be instrumented without dependency storage
    final ArrayList formsToInstrument = myFormFiles;
    if (formsToInstrument.size() == 0) {
        log("No forms to instrument found", Project.MSG_VERBOSE);
        return;
    }
    final HashMap class2form = new HashMap();
    for (int i = 0; i < formsToInstrument.size(); i++) {
        final File formFile = (File) formsToInstrument.get(i);
        log("compiling form " + formFile.getAbsolutePath(), Project.MSG_VERBOSE);
        final LwRootContainer rootContainer;
        try {
            rootContainer = Utils.getRootContainer(formFile.toURI().toURL(), new CompiledClassPropertiesProvider(finder.getLoader()));
        } catch (AlienFormFileException e) {
            // ignore non-IDEA forms
            continue;
        } catch (Exception e) {
            fireError("Cannot process form file " + formFile.getAbsolutePath() + ". Reason: " + e);
            continue;
        }
        final String classToBind = rootContainer.getClassToBind();
        if (classToBind == null) {
            continue;
        }
        String name = classToBind.replace('.', '/');
        File classFile = getClassFile(name);
        if (classFile == null) {
            log(formFile.getAbsolutePath() + ": Class to bind does not exist: " + classToBind, Project.MSG_WARN);
            continue;
        }
        final File alreadyProcessedForm = (File) class2form.get(classToBind);
        if (alreadyProcessedForm != null) {
            fireError(formFile.getAbsolutePath() + ": " + "The form is bound to the class " + classToBind + ".\n" + "Another form " + alreadyProcessedForm.getAbsolutePath() + " is also bound to this class.");
            continue;
        }
        class2form.put(classToBind, formFile);
        try {
            int version;
            InputStream stream = new FileInputStream(classFile);
            try {
                version = getClassFileVersion(new ClassReader(stream));
            } finally {
                stream.close();
            }
            AntNestedFormLoader formLoader = new AntNestedFormLoader(finder.getLoader(), myNestedFormPathList);
            InstrumenterClassWriter classWriter = new InstrumenterClassWriter(getAsmClassWriterFlags(version), finder);
            final AsmCodeGenerator codeGenerator = new AsmCodeGenerator(rootContainer, finder, formLoader, false, classWriter);
            codeGenerator.patchFile(classFile);
            final FormErrorInfo[] warnings = codeGenerator.getWarnings();
            for (int j = 0; j < warnings.length; j++) {
                log(formFile.getAbsolutePath() + ": " + warnings[j].getErrorMessage(), Project.MSG_WARN);
            }
            final FormErrorInfo[] errors = codeGenerator.getErrors();
            if (errors.length > 0) {
                StringBuffer message = new StringBuffer();
                for (int j = 0; j < errors.length; j++) {
                    if (message.length() > 0) {
                        message.append("\n");
                    }
                    message.append(formFile.getAbsolutePath()).append(": ").append(errors[j].getErrorMessage());
                }
                fireError(message.toString());
            }
        } catch (Exception e) {
            fireError("Forms instrumentation failed for " + formFile.getAbsolutePath() + ": " + e.toString());
        }
    }
}
Also used : CompiledClassPropertiesProvider(com.intellij.uiDesigner.lw.CompiledClassPropertiesProvider) LwRootContainer(com.intellij.uiDesigner.lw.LwRootContainer) MalformedURLException(java.net.MalformedURLException) BuildException(org.apache.tools.ant.BuildException) FailSafeClassReader(com.intellij.compiler.instrumentation.FailSafeClassReader) InstrumenterClassWriter(com.intellij.compiler.instrumentation.InstrumenterClassWriter)

Example 4 with InstrumenterClassWriter

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

the class BaseInstrumentingBuilder method performBuild.

@Override
protected final ExitCode performBuild(CompileContext context, ModuleChunk chunk, InstrumentationClassFinder finder, OutputConsumer outputConsumer) {
    ExitCode exitCode = ExitCode.NOTHING_DONE;
    for (CompiledClass compiledClass : outputConsumer.getCompiledClasses().values()) {
        if (Utils.IS_TEST_MODE || LOG.isDebugEnabled()) {
            LOG.info("checking " + compiledClass + " by " + getClass());
        }
        final BinaryContent originalContent = compiledClass.getContent();
        final ClassReader reader = new FailSafeClassReader(originalContent.getBuffer(), originalContent.getOffset(), originalContent.getLength());
        final int version = getClassFileVersion(reader);
        if (IS_INSTRUMENTED_KEY.get(compiledClass, Boolean.FALSE) || !canInstrument(compiledClass, version)) {
            // do not instrument the same content twice
            continue;
        }
        final ClassWriter writer = new InstrumenterClassWriter(reader, getAsmClassWriterFlags(version), finder);
        try {
            if (Utils.IS_TEST_MODE || LOG.isDebugEnabled()) {
                LOG.info("instrumenting " + compiledClass + " by " + getClass());
            }
            final BinaryContent instrumented = instrument(context, compiledClass, reader, writer, finder);
            if (instrumented != null) {
                compiledClass.setContent(instrumented);
                finder.cleanCachedData(compiledClass.getClassName());
                IS_INSTRUMENTED_KEY.set(compiledClass, Boolean.TRUE);
                exitCode = ExitCode.OK;
            }
        } catch (Throwable e) {
            LOG.info(e);
            final String message = e.getMessage();
            if (message != null) {
                context.processMessage(new CompilerMessage(getPresentableName(), BuildMessage.Kind.ERROR, message, ContainerUtil.getFirstItem(compiledClass.getSourceFilesPaths())));
            } else {
                context.processMessage(new CompilerMessage(getPresentableName(), e));
            }
        }
    }
    return exitCode;
}
Also used : CompilerMessage(org.jetbrains.jps.incremental.messages.CompilerMessage) FailSafeClassReader(com.intellij.compiler.instrumentation.FailSafeClassReader) ClassReader(org.jetbrains.org.objectweb.asm.ClassReader) InstrumenterClassWriter(com.intellij.compiler.instrumentation.InstrumenterClassWriter) FailSafeClassReader(com.intellij.compiler.instrumentation.FailSafeClassReader) ClassWriter(org.jetbrains.org.objectweb.asm.ClassWriter) InstrumenterClassWriter(com.intellij.compiler.instrumentation.InstrumenterClassWriter)

Aggregations

FailSafeClassReader (com.intellij.compiler.instrumentation.FailSafeClassReader)4 InstrumenterClassWriter (com.intellij.compiler.instrumentation.InstrumenterClassWriter)4 CompiledClassPropertiesProvider (com.intellij.uiDesigner.lw.CompiledClassPropertiesProvider)2 LwRootContainer (com.intellij.uiDesigner.lw.LwRootContainer)2 MalformedURLException (java.net.MalformedURLException)2 BuildException (org.apache.tools.ant.BuildException)2 CompilerMessage (org.jetbrains.jps.incremental.messages.CompilerMessage)2 ClassReader (org.jetbrains.org.objectweb.asm.ClassReader)2 THashMap (gnu.trove.THashMap)1 ProgressMessage (org.jetbrains.jps.incremental.messages.ProgressMessage)1 ClassWriter (org.jetbrains.org.objectweb.asm.ClassWriter)1