mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
generalized instrumentation
This commit is contained in:
@@ -772,6 +772,12 @@ public class IncProjectBuilder {
|
||||
|
||||
// return true if changed something, false otherwise
|
||||
private boolean runModuleLevelBuilders(final CompileContext context, final ModuleChunk chunk) throws ProjectBuildException, IOException {
|
||||
for (BuilderCategory category : BuilderCategory.values()) {
|
||||
for (ModuleLevelBuilder builder : myBuilderRegistry.getBuilders(category)) {
|
||||
builder.chunkBuildStarted(context, chunk);
|
||||
}
|
||||
}
|
||||
|
||||
boolean doneSomething = false;
|
||||
boolean rebuildFromScratchRequested = false;
|
||||
float stageCount = myTotalModuleLevelBuilderCount;
|
||||
@@ -878,7 +884,7 @@ public class IncProjectBuilder {
|
||||
outputConsumer.clear();
|
||||
for (BuilderCategory category : BuilderCategory.values()) {
|
||||
for (ModuleLevelBuilder builder : myBuilderRegistry.getBuilders(category)) {
|
||||
builder.cleanupChunkResources(context);
|
||||
builder.chunkBuildFinished(context, chunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jps.builders.BuildTargetType;
|
||||
import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType;
|
||||
import org.jetbrains.jps.builders.java.ResourcesTargetType;
|
||||
import org.jetbrains.jps.incremental.instrumentation.NotNullInstrumentingBuilder;
|
||||
import org.jetbrains.jps.incremental.java.JavaBuilder;
|
||||
import org.jetbrains.jps.incremental.java.NotNullInstrumentingBuilder;
|
||||
import org.jetbrains.jps.incremental.resources.ResourcesBuilder;
|
||||
import org.jetbrains.jps.service.SharedThreadPool;
|
||||
|
||||
|
||||
@@ -57,6 +57,9 @@ public abstract class ModuleLevelBuilder extends Builder {
|
||||
return myCategory;
|
||||
}
|
||||
|
||||
public void cleanupChunkResources(CompileContext context) {
|
||||
public void chunkBuildStarted(CompileContext context, ModuleChunk chunk) {
|
||||
}
|
||||
|
||||
public void chunkBuildFinished(CompileContext context, ModuleChunk chunk) {
|
||||
}
|
||||
}
|
||||
|
||||
+160
@@ -0,0 +1,160 @@
|
||||
package org.jetbrains.jps.incremental.instrumentation;
|
||||
|
||||
import com.intellij.compiler.instrumentation.InstrumentationClassFinder;
|
||||
import com.intellij.compiler.instrumentation.InstrumenterClassWriter;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.asm4.ClassReader;
|
||||
import org.jetbrains.asm4.ClassVisitor;
|
||||
import org.jetbrains.asm4.ClassWriter;
|
||||
import org.jetbrains.asm4.Opcodes;
|
||||
import org.jetbrains.jps.ModuleChunk;
|
||||
import org.jetbrains.jps.ProjectPaths;
|
||||
import org.jetbrains.jps.builders.DirtyFilesHolder;
|
||||
import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor;
|
||||
import org.jetbrains.jps.incremental.*;
|
||||
import org.jetbrains.jps.incremental.messages.ProgressMessage;
|
||||
import org.jetbrains.jps.javac.BinaryContent;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 11/25/12
|
||||
*/
|
||||
public abstract class BaseInstrumentingBuilder extends ModuleLevelBuilder{
|
||||
private static final Key<InstrumentationClassFinder> CLASS_FINDER = Key.create("_cached_instrumentation_class_finder_");
|
||||
|
||||
public BaseInstrumentingBuilder() {
|
||||
super(BuilderCategory.CLASS_INSTRUMENTER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void chunkBuildStarted(CompileContext context, ModuleChunk chunk) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void chunkBuildFinished(CompileContext context, ModuleChunk chunk) {
|
||||
final InstrumentationClassFinder finder = CLASS_FINDER.get(context);
|
||||
CLASS_FINDER.set(context, null);
|
||||
if (finder != null) {
|
||||
finder.releaseResources();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ExitCode build(CompileContext context, ModuleChunk chunk, DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget> dirtyFilesHolder, OutputConsumer outputConsumer) throws ProjectBuildException, IOException {
|
||||
ExitCode exitCode = ExitCode.NOTHING_DONE;
|
||||
if (outputConsumer.getCompiledClasses().isEmpty() || !isEnabled(context, chunk)) {
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
InstrumentationClassFinder finder = null;
|
||||
final String progress = getProgressMessage();
|
||||
final boolean shouldShowProgress = !StringUtil.isEmptyOrSpaces(progress);
|
||||
if (shouldShowProgress) {
|
||||
context.processMessage(new ProgressMessage(progress + " [" + chunk.getName() + "]"));
|
||||
}
|
||||
|
||||
try {
|
||||
for (CompiledClass compiledClass : outputConsumer.getCompiledClasses().values()) {
|
||||
final BinaryContent originalContent = compiledClass.getContent();
|
||||
final ClassReader reader = new ClassReader(originalContent.getBuffer(), originalContent.getOffset(), originalContent.getLength());
|
||||
final int version = getClassFileVersion(reader);
|
||||
if (!canInstrument(compiledClass, version)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (finder == null) { // lazy init for this particular builder
|
||||
finder = CLASS_FINDER.get(context); // try using shared finder
|
||||
if (finder == null) {
|
||||
final ProjectPaths paths = context.getProjectPaths();
|
||||
final Collection<File> platformCp = paths.getPlatformCompilationClasspath(chunk, false);
|
||||
|
||||
final Collection<File> classpath = new ArrayList<File>();
|
||||
classpath.addAll(paths.getCompilationClasspath(chunk, false));
|
||||
classpath.addAll(ProjectPaths.getSourceRootsWithDependents(chunk).keySet());
|
||||
|
||||
finder = createInstrumentationClassFinder(platformCp, classpath, outputConsumer);
|
||||
CLASS_FINDER.set(context, finder);
|
||||
}
|
||||
}
|
||||
|
||||
final ClassWriter writer = new InstrumenterClassWriter(getAsmClassWriterFlags(version), finder);
|
||||
final BinaryContent instrumented = instrument(context, compiledClass, reader, writer, finder);
|
||||
if (instrumented != null) {
|
||||
compiledClass.setContent(instrumented);
|
||||
exitCode = ExitCode.OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (shouldShowProgress) {
|
||||
context.processMessage(new ProgressMessage("")); // cleanup progress
|
||||
}
|
||||
}
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
protected abstract boolean isEnabled(CompileContext context, ModuleChunk chunk);
|
||||
|
||||
protected abstract boolean canInstrument(CompiledClass compiledClass, int classFileVersion);
|
||||
|
||||
@Nullable
|
||||
protected abstract BinaryContent instrument(CompileContext context,
|
||||
CompiledClass compiled,
|
||||
ClassReader reader,
|
||||
ClassWriter writer,
|
||||
InstrumentationClassFinder finder);
|
||||
|
||||
protected abstract String getProgressMessage();
|
||||
// utility methods
|
||||
|
||||
public static InstrumentationClassFinder createInstrumentationClassFinder(Collection<File> platformCp, Collection<File> cp, final OutputConsumer outputConsumer) throws MalformedURLException {
|
||||
final URL[] platformUrls = new URL[platformCp.size()];
|
||||
int index = 0;
|
||||
for (File file : platformCp) {
|
||||
platformUrls[index++] = file.toURI().toURL();
|
||||
}
|
||||
|
||||
final URL[] urls = new URL[cp.size()];
|
||||
index = 0;
|
||||
for (File file : cp) {
|
||||
urls[index++] = file.toURI().toURL();
|
||||
}
|
||||
|
||||
return new InstrumentationClassFinder(platformUrls, urls) {
|
||||
protected InputStream lookupClassBeforeClasspath(String internalClassName) {
|
||||
final BinaryContent content = outputConsumer.lookupClassBytes(internalClassName.replace("/", "."));
|
||||
if (content != null) {
|
||||
return new ByteArrayInputStream(content.getBuffer(), content.getOffset(), content.getLength());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static int getAsmClassWriterFlags(int version) {
|
||||
return version >= Opcodes.V1_6 && version != Opcodes.V1_1 ? ClassWriter.COMPUTE_FRAMES : ClassWriter.COMPUTE_MAXS;
|
||||
}
|
||||
|
||||
public static int getClassFileVersion(ClassReader reader) {
|
||||
final Ref<Integer> result = new Ref<Integer>(0);
|
||||
reader.accept(new ClassVisitor(Opcodes.ASM4) {
|
||||
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
|
||||
result.set(version);
|
||||
}
|
||||
}, 0);
|
||||
return result.get();
|
||||
}
|
||||
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
package org.jetbrains.jps.incremental.instrumentation;
|
||||
|
||||
import com.intellij.compiler.instrumentation.InstrumentationClassFinder;
|
||||
import com.intellij.compiler.notNullVerification.NotNullVerifyingInstrumenter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.asm4.ClassReader;
|
||||
import org.jetbrains.asm4.ClassWriter;
|
||||
import org.jetbrains.asm4.Opcodes;
|
||||
import org.jetbrains.jps.ModuleChunk;
|
||||
import org.jetbrains.jps.cmdline.ProjectDescriptor;
|
||||
import org.jetbrains.jps.incremental.CompileContext;
|
||||
import org.jetbrains.jps.incremental.CompiledClass;
|
||||
import org.jetbrains.jps.incremental.messages.BuildMessage;
|
||||
import org.jetbrains.jps.incremental.messages.CompilerMessage;
|
||||
import org.jetbrains.jps.javac.BinaryContent;
|
||||
import org.jetbrains.jps.model.java.JpsJavaExtensionService;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 11/21/12
|
||||
*/
|
||||
public class NotNullInstrumentingBuilder extends BaseInstrumentingBuilder{
|
||||
|
||||
public NotNullInstrumentingBuilder() {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getPresentableName() {
|
||||
return "NotNull instrumentation";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getProgressMessage() {
|
||||
return "Adding @NotNull assertions...";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnabled(CompileContext context, ModuleChunk chunk) {
|
||||
final ProjectDescriptor pd = context.getProjectDescriptor();
|
||||
return JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(pd.getProject()).isAddNotNullAssertions();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canInstrument(CompiledClass compiledClass, int classFileVersion) {
|
||||
return classFileVersion >= Opcodes.V1_5;
|
||||
}
|
||||
|
||||
// todo: probably instrument other NotNull-like annotations defined in project settings?
|
||||
@Override
|
||||
@Nullable
|
||||
protected BinaryContent instrument(CompileContext context,
|
||||
CompiledClass compiledClass,
|
||||
ClassReader reader,
|
||||
ClassWriter writer,
|
||||
InstrumentationClassFinder finder) {
|
||||
try {
|
||||
final NotNullVerifyingInstrumenter instrumenter = new NotNullVerifyingInstrumenter(writer);
|
||||
reader.accept(instrumenter, 0);
|
||||
if (instrumenter.isModification()) {
|
||||
return new BinaryContent(writer.toByteArray());
|
||||
}
|
||||
}
|
||||
catch (Throwable e) {
|
||||
final StringBuilder msg = new StringBuilder();
|
||||
msg.append("@NotNull instrumentation failed ");
|
||||
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()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -681,7 +681,7 @@ public class JavaBuilder extends ModuleLevelBuilder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanupChunkResources(CompileContext context) {
|
||||
public void chunkBuildFinished(CompileContext context, ModuleChunk chunk) {
|
||||
JavaBuilderUtil.cleanupChunkResources(context);
|
||||
}
|
||||
|
||||
|
||||
-147
@@ -1,147 +0,0 @@
|
||||
package org.jetbrains.jps.incremental.java;
|
||||
|
||||
import com.intellij.compiler.instrumentation.InstrumentationClassFinder;
|
||||
import com.intellij.compiler.instrumentation.InstrumenterClassWriter;
|
||||
import com.intellij.compiler.notNullVerification.NotNullVerifyingInstrumenter;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.asm4.ClassReader;
|
||||
import org.jetbrains.asm4.ClassVisitor;
|
||||
import org.jetbrains.asm4.ClassWriter;
|
||||
import org.jetbrains.asm4.Opcodes;
|
||||
import org.jetbrains.jps.ModuleChunk;
|
||||
import org.jetbrains.jps.ProjectPaths;
|
||||
import org.jetbrains.jps.builders.DirtyFilesHolder;
|
||||
import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor;
|
||||
import org.jetbrains.jps.cmdline.ProjectDescriptor;
|
||||
import org.jetbrains.jps.incremental.*;
|
||||
import org.jetbrains.jps.incremental.messages.BuildMessage;
|
||||
import org.jetbrains.jps.incremental.messages.CompilerMessage;
|
||||
import org.jetbrains.jps.incremental.messages.ProgressMessage;
|
||||
import org.jetbrains.jps.javac.BinaryContent;
|
||||
import org.jetbrains.jps.model.java.JpsJavaExtensionService;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 11/21/12
|
||||
*/
|
||||
public class NotNullInstrumentingBuilder extends ModuleLevelBuilder{
|
||||
|
||||
public NotNullInstrumentingBuilder() {
|
||||
super(BuilderCategory.CLASS_INSTRUMENTER);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getPresentableName() {
|
||||
return "NotNull instrumentation";
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExitCode build(CompileContext context,
|
||||
ModuleChunk chunk,
|
||||
DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget> dirtyFilesHolder,
|
||||
OutputConsumer outputConsumer) throws ProjectBuildException, IOException {
|
||||
ExitCode exitCode = ExitCode.NOTHING_DONE;
|
||||
|
||||
final ProjectDescriptor pd = context.getProjectDescriptor();
|
||||
final boolean addNotNullAssertions = JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(pd.getProject()).isAddNotNullAssertions();
|
||||
if (addNotNullAssertions && !outputConsumer.getCompiledClasses().isEmpty()) {
|
||||
final ProjectPaths paths = context.getProjectPaths();
|
||||
final Collection<File> classpath = paths.getCompilationClasspath(chunk, false);
|
||||
final Collection<File> platformCp = paths.getPlatformCompilationClasspath(chunk, false);
|
||||
final InstrumentationClassFinder finder = createInstrumentationClassFinder(platformCp, classpath, outputConsumer);
|
||||
try {
|
||||
try {
|
||||
context.processMessage(new ProgressMessage("Adding @NotNull assertions... [" + chunk.getName() + "]"));
|
||||
exitCode = instrumentNotNull(context, outputConsumer, finder);
|
||||
}
|
||||
finally {
|
||||
context.processMessage(new ProgressMessage("Finished adding @NotNull assertions [" + chunk.getName() + "]"));
|
||||
}
|
||||
}
|
||||
finally {
|
||||
finder.releaseResources();
|
||||
}
|
||||
}
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
// todo: probably instrument other NotNull-like annotations defined in project settings?
|
||||
private ExitCode instrumentNotNull(CompileContext context, OutputConsumer outputConsumer, final InstrumentationClassFinder finder) {
|
||||
boolean doneSomething = false;
|
||||
for (final CompiledClass compiledClass : outputConsumer.getCompiledClasses().values()) {
|
||||
final BinaryContent originalContent = compiledClass.getContent();
|
||||
final ClassReader reader = new ClassReader(originalContent.getBuffer(), originalContent.getOffset(), originalContent.getLength());
|
||||
final int version = getClassFileVersion(reader);
|
||||
if (version >= Opcodes.V1_5) {
|
||||
final ClassWriter writer = new InstrumenterClassWriter(getAsmClassWriterFlags(version), finder);
|
||||
try {
|
||||
final NotNullVerifyingInstrumenter instrumenter = new NotNullVerifyingInstrumenter(writer);
|
||||
reader.accept(instrumenter, 0);
|
||||
if (instrumenter.isModification()) {
|
||||
compiledClass.setContent(new BinaryContent(writer.toByteArray()));
|
||||
doneSomething = true;
|
||||
}
|
||||
}
|
||||
catch (Throwable e) {
|
||||
doneSomething = true;
|
||||
final StringBuilder msg = new StringBuilder();
|
||||
msg.append("@NotNull instrumentation failed ");
|
||||
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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return doneSomething? ExitCode.OK : ExitCode.NOTHING_DONE;
|
||||
}
|
||||
|
||||
private static InstrumentationClassFinder createInstrumentationClassFinder(Collection<File> platformCp, Collection<File> classpath, final OutputConsumer outputConsumer) throws MalformedURLException {
|
||||
final URL[] platformUrls = new URL[platformCp.size()];
|
||||
int index = 0;
|
||||
for (File file : platformCp) {
|
||||
platformUrls[index++] = file.toURI().toURL();
|
||||
}
|
||||
|
||||
final List<URL> urls = new ArrayList<URL>(classpath.size());
|
||||
for (File file : classpath) {
|
||||
urls.add(file.toURI().toURL());
|
||||
}
|
||||
|
||||
return new InstrumentationClassFinder(platformUrls, urls.toArray(new URL[urls.size()])) {
|
||||
protected InputStream lookupClassBeforeClasspath(String internalClassName) {
|
||||
final BinaryContent content = outputConsumer.lookupClassBytes(internalClassName.replace("/", "."));
|
||||
if (content != null) {
|
||||
return new ByteArrayInputStream(content.getBuffer(), content.getOffset(), content.getLength());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static int getClassFileVersion(ClassReader reader) {
|
||||
final Ref<Integer> result = new Ref<Integer>(0);
|
||||
reader.accept(new ClassVisitor(Opcodes.ASM4) {
|
||||
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
|
||||
result.set(version);
|
||||
}
|
||||
}, 0);
|
||||
return result.get();
|
||||
}
|
||||
|
||||
private static int getAsmClassWriterFlags(int version) {
|
||||
return version >= Opcodes.V1_6 && version != Opcodes.V1_1 ? ClassWriter.COMPUTE_FRAMES : ClassWriter.COMPUTE_MAXS;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -252,7 +252,7 @@ public class GroovyBuilder extends ModuleLevelBuilder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanupChunkResources(CompileContext context) {
|
||||
public void chunkBuildFinished(CompileContext context, ModuleChunk chunk) {
|
||||
JavaBuilderUtil.cleanupChunkResources(context);
|
||||
STUB_TO_SRC.set(context, null);
|
||||
}
|
||||
|
||||
+11
-55
@@ -18,7 +18,6 @@ package org.jetbrains.jps.uiDesigner.compiler;
|
||||
import com.intellij.compiler.instrumentation.InstrumentationClassFinder;
|
||||
import com.intellij.compiler.instrumentation.InstrumenterClassWriter;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.uiDesigner.compiler.*;
|
||||
import com.intellij.uiDesigner.compiler.Utils;
|
||||
@@ -28,9 +27,6 @@ import com.intellij.uiDesigner.lw.LwRootContainer;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.asm4.ClassReader;
|
||||
import org.jetbrains.asm4.ClassVisitor;
|
||||
import org.jetbrains.asm4.ClassWriter;
|
||||
import org.jetbrains.asm4.Opcodes;
|
||||
import org.jetbrains.jps.ModuleChunk;
|
||||
import org.jetbrains.jps.ProjectPaths;
|
||||
import org.jetbrains.jps.builders.DirtyFilesHolder;
|
||||
@@ -38,6 +34,7 @@ import org.jetbrains.jps.builders.FileProcessor;
|
||||
import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor;
|
||||
import org.jetbrains.jps.builders.logging.ProjectBuilderLogger;
|
||||
import org.jetbrains.jps.incremental.*;
|
||||
import org.jetbrains.jps.incremental.instrumentation.BaseInstrumentingBuilder;
|
||||
import org.jetbrains.jps.incremental.messages.BuildMessage;
|
||||
import org.jetbrains.jps.incremental.messages.CompilerMessage;
|
||||
import org.jetbrains.jps.incremental.messages.ProgressMessage;
|
||||
@@ -48,8 +45,6 @@ import org.jetbrains.jps.uiDesigner.model.JpsUiDesignerConfiguration;
|
||||
import org.jetbrains.jps.uiDesigner.model.JpsUiDesignerExtensionService;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
@@ -93,10 +88,16 @@ public class FormsInstrumenter extends FormsBuilder {
|
||||
|
||||
try {
|
||||
final ProjectPaths paths = context.getProjectPaths();
|
||||
final Collection<File> classpath = paths.getCompilationClasspath(chunk, false);
|
||||
final Collection<File> platformCp = paths.getPlatformCompilationClasspath(chunk, false);
|
||||
|
||||
final List<File> classpath = new ArrayList<File>();
|
||||
classpath.addAll(paths.getCompilationClasspath(chunk, false));
|
||||
classpath.add(getResourcePath(GridConstraints.class)); // forms_rt.jar
|
||||
final Map<File, String> chunkSourcePath = ProjectPaths.getSourceRootsWithDependents(chunk);
|
||||
final InstrumentationClassFinder finder = createInstrumentationClassFinder(platformCp, classpath, chunkSourcePath, outputConsumer);
|
||||
classpath.addAll(chunkSourcePath.keySet()); // sourcepath for loading forms resources
|
||||
|
||||
final InstrumentationClassFinder finder =
|
||||
BaseInstrumentingBuilder.createInstrumentationClassFinder(platformCp, classpath, outputConsumer);
|
||||
|
||||
try {
|
||||
instrumentForms(context, chunk, chunkSourcePath, finder, forms, outputConsumer);
|
||||
@@ -181,8 +182,8 @@ public class FormsInstrumenter extends FormsBuilder {
|
||||
final ClassReader classReader =
|
||||
new ClassReader(originalContent.getBuffer(), originalContent.getOffset(), originalContent.getLength());
|
||||
|
||||
final int version = getClassFileVersion(classReader);
|
||||
final InstrumenterClassWriter classWriter = new InstrumenterClassWriter(getAsmClassWriterFlags(version), finder);
|
||||
final int version = BaseInstrumentingBuilder.getClassFileVersion(classReader);
|
||||
final InstrumenterClassWriter classWriter = new InstrumenterClassWriter(BaseInstrumentingBuilder.getAsmClassWriterFlags(version), finder);
|
||||
final AsmCodeGenerator codeGenerator = new AsmCodeGenerator(rootContainer, finder, nestedFormsLoader, false, classWriter);
|
||||
final byte[] patchedBytes = codeGenerator.patchClass(classReader);
|
||||
if (patchedBytes != null) {
|
||||
@@ -241,51 +242,6 @@ public class FormsInstrumenter extends FormsBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
private static int getClassFileVersion(ClassReader reader) {
|
||||
final Ref<Integer> result = new Ref<Integer>(0);
|
||||
reader.accept(new ClassVisitor(Opcodes.ASM4) {
|
||||
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
|
||||
result.set(version);
|
||||
}
|
||||
}, 0);
|
||||
return result.get();
|
||||
}
|
||||
|
||||
private static int getAsmClassWriterFlags(int version) {
|
||||
return version >= Opcodes.V1_6 && version != Opcodes.V1_1 ? ClassWriter.COMPUTE_FRAMES : ClassWriter.COMPUTE_MAXS;
|
||||
}
|
||||
|
||||
private static InstrumentationClassFinder createInstrumentationClassFinder(
|
||||
Collection<File> platformCp, Collection<File> cp, Map<File, String> sourcePath, final OutputConsumer outputConsumer
|
||||
) throws MalformedURLException {
|
||||
|
||||
final URL[] platformUrls = new URL[platformCp.size()];
|
||||
int index = 0;
|
||||
for (File file : platformCp) {
|
||||
platformUrls[index++] = file.toURI().toURL();
|
||||
}
|
||||
|
||||
final List<URL> urls = new ArrayList<URL>(cp.size() + sourcePath.size() + 1);
|
||||
for (File file : cp) {
|
||||
urls.add(file.toURI().toURL());
|
||||
}
|
||||
urls.add(getResourcePath(GridConstraints.class).toURI().toURL()); // forms_rt.jar
|
||||
|
||||
for (File file : sourcePath.keySet()) { // sourcepath for loading forms resources
|
||||
urls.add(file.toURI().toURL());
|
||||
}
|
||||
|
||||
return new InstrumentationClassFinder(platformUrls, urls.toArray(new URL[urls.size()])) {
|
||||
protected InputStream lookupClassBeforeClasspath(String internalClassName) {
|
||||
final BinaryContent content = outputConsumer.lookupClassBytes(internalClassName.replace("/", "."));
|
||||
if (content != null) {
|
||||
return new ByteArrayInputStream(content.getBuffer(), content.getOffset(), content.getLength());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static File getResourcePath(Class aClass) {
|
||||
return new File(PathManager.getResourceRoot(aClass, "/" + aClass.getName().replace('.', '/') + ".class"));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user