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;
}
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;
}
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());
}
}
}
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;
}
Aggregations