diff --git a/java/compiler/instrumentation-util/src/com/intellij/compiler/instrumentation/InstrumentationClassFinder.java b/java/compiler/instrumentation-util/src/com/intellij/compiler/instrumentation/InstrumentationClassFinder.java index 3a5a54ae47c9..40260c34db55 100644 --- a/java/compiler/instrumentation-util/src/com/intellij/compiler/instrumentation/InstrumentationClassFinder.java +++ b/java/compiler/instrumentation-util/src/com/intellij/compiler/instrumentation/InstrumentationClassFinder.java @@ -194,11 +194,6 @@ public class InstrumentationClassFinder { return is; } - public boolean isAvaiable(String resourceName) { - return myPlatformClasspath.getResource(resourceName) != null || - myClasspath.getResource(resourceName) != null; - } - public InputStream getResourceAsStream(String resourceName) throws IOException { InputStream is = null; diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/JavaBuilderService.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/JavaBuilderService.java index 3a0254ef7d06..442a46012710 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/JavaBuilderService.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/JavaBuilderService.java @@ -23,7 +23,6 @@ import org.jetbrains.jps.builders.java.ResourcesTargetType; import org.jetbrains.jps.incremental.dependencies.DependencyResolvingBuilder; import org.jetbrains.jps.incremental.instrumentation.NotNullInstrumentingBuilder; import org.jetbrains.jps.incremental.instrumentation.RmiStubsGenerator; -import org.jetbrains.jps.incremental.instrumentation.internal.SystemIndependentInstrumentingBuilder; import org.jetbrains.jps.incremental.java.JavaBuilder; import org.jetbrains.jps.incremental.resources.ResourcesBuilder; import org.jetbrains.jps.service.SharedThreadPool; @@ -52,7 +51,6 @@ public class JavaBuilderService extends BuilderService { return Arrays.asList( new JavaBuilder(SharedThreadPool.getInstance()), new NotNullInstrumentingBuilder(), - new SystemIndependentInstrumentingBuilder(), new RmiStubsGenerator(), new DependencyResolvingBuilder(), new BackwardReferenceIndexBuilder() diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/ClassProcessingBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/ClassProcessingBuilder.java index 360403d5562a..b5c15a0ed615 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/ClassProcessingBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/ClassProcessingBuilder.java @@ -58,10 +58,6 @@ public abstract class ClassProcessingBuilder extends ModuleLevelBuilder { protected abstract boolean isEnabled(CompileContext context, ModuleChunk chunk); - protected boolean isEnabled(CompileContext context, InstrumentationClassFinder finder) throws IOException { - return true; - } - protected abstract String getProgressMessage(); @Override @@ -79,35 +75,33 @@ public abstract class ClassProcessingBuilder extends ModuleLevelBuilder { return ExitCode.NOTHING_DONE; } - InstrumentationClassFinder finder = CLASS_FINDER.get(context); // try using shared finder - if (finder == null) { - final Collection platformCp = ProjectPaths.getPlatformCompilationClasspath(chunk, false); - final Collection classpath = new ArrayList<>(); - classpath.addAll(ProjectPaths.getCompilationClasspath(chunk, false)); - classpath.addAll(ProjectPaths.getSourceRootsWithDependents(chunk).keySet()); - final JpsSdk sdk = chunk.representativeTarget().getModule().getSdk(JpsJavaSdkType.INSTANCE); - finder = createInstrumentationClassFinder(sdk, platformCp, classpath, outputConsumer); - CLASS_FINDER.set(context, finder); - } - - if (!isEnabled(context, finder)) { - return ExitCode.NOTHING_DONE; - } - final String progress = getProgressMessage(); final boolean shouldShowProgress = !StringUtil.isEmptyOrSpaces(progress); if (shouldShowProgress) { context.processMessage(new ProgressMessage(progress + " [" + chunk.getPresentableShortName() + "]")); } + ExitCode exitCode = ExitCode.NOTHING_DONE; try { - return performBuild(context, chunk, finder, outputConsumer); + InstrumentationClassFinder finder = CLASS_FINDER.get(context); // try using shared finder + if (finder == null) { + final Collection platformCp = ProjectPaths.getPlatformCompilationClasspath(chunk, false); + final Collection classpath = new ArrayList<>(); + classpath.addAll(ProjectPaths.getCompilationClasspath(chunk, false)); + classpath.addAll(ProjectPaths.getSourceRootsWithDependents(chunk).keySet()); + final JpsSdk sdk = chunk.representativeTarget().getModule().getSdk(JpsJavaSdkType.INSTANCE); + finder = createInstrumentationClassFinder(sdk, platformCp, classpath, outputConsumer); + CLASS_FINDER.set(context, finder); + } + + exitCode = performBuild(context, chunk, finder, outputConsumer); } finally { if (shouldShowProgress) { context.processMessage(new ProgressMessage("")); // cleanup progress } } + return exitCode; } @Override 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 a753693a58aa..08dbb9aa3f4c 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 @@ -63,10 +63,6 @@ public class NotNullInstrumentingBuilder extends BaseInstrumentingBuilder{ @Override protected boolean isEnabled(CompileContext context, ModuleChunk chunk) { - return isEnabledIn(context); - } - - public static boolean isEnabledIn(CompileContext context) { final ProjectDescriptor pd = context.getProjectDescriptor(); return JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(pd.getProject()).isAddNotNullAssertions(); } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/internal/AssertionMethodImpl.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/internal/AssertionMethodImpl.java deleted file mode 100644 index c3e39f8c2106..000000000000 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/internal/AssertionMethodImpl.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2000-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.jps.incremental.instrumentation.internal; - -import com.intellij.openapi.diagnostic.Logger; - -/* - A template for the synthetic method embedded by the bytecode instrumentation. - */ -class AssertionMethodImpl { - private static void assertArgumentIsSystemIndependent(String className, String methodName, String parameterName, String argument) { - if (argument != null && argument.indexOf('\\') > -1) { - String message = String.format("Argument for @SystemIndependent parameter '%s' of %s.%s must be system-independent: %s", - parameterName, className, methodName, argument); - - IllegalArgumentException exception = new IllegalArgumentException(message); - - StackTraceElement[] stackTrace = new StackTraceElement[exception.getStackTrace().length - 1]; - System.arraycopy(exception.getStackTrace(), 1, stackTrace, 0, stackTrace.length); - exception.setStackTrace(stackTrace); - - Logger.getInstance("#org.jetbrains.jps.incremental.instrumentation.AssertionMethodImpl").error(exception); - } - } -} diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/internal/MethodTemplate.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/internal/MethodTemplate.java deleted file mode 100644 index 03095100972c..000000000000 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/internal/MethodTemplate.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2000-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.jps.incremental.instrumentation.internal; - -import com.intellij.openapi.util.io.FileUtil; -import org.jetbrains.org.objectweb.asm.ClassReader; -import org.jetbrains.org.objectweb.asm.ClassVisitor; -import org.jetbrains.org.objectweb.asm.MethodVisitor; -import org.jetbrains.org.objectweb.asm.Opcodes; - -import java.io.IOException; -import java.io.InputStream; - -class MethodTemplate { - private final byte[] myBytecode; - - MethodTemplate(Class aClass) { - try { - myBytecode = readBytecodeOf(aClass); - } - catch (IOException e) { - throw new RuntimeException(e); - } - } - - private static byte[] readBytecodeOf(Class aClass) throws IOException { - InputStream stream = aClass.getResourceAsStream(aClass.getSimpleName() + ".class"); - if (stream == null) { - throw new IllegalArgumentException("Cannot read class bytecode: " + aClass); - } - try { - return FileUtil.loadBytes(stream); - } - finally { - stream.close(); - } - } - - public void write(ClassVisitor writer, int accessModifier, String methodName) { - ClassReader reader = new ClassReader(myBytecode); - - reader.accept(new ClassVisitor(Opcodes.API_VERSION) { - @Override - public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { - return "".equals(name) ? null : writer.visitMethod(access | accessModifier, methodName, desc, signature, exceptions); - } - }, 0); - } -} diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/internal/SystemIndependentInstrumenter.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/internal/SystemIndependentInstrumenter.java deleted file mode 100644 index 9d688ea01065..000000000000 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/internal/SystemIndependentInstrumenter.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2000-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.jps.incremental.instrumentation.internal; - -import org.jetbrains.org.objectweb.asm.*; -import sun.management.counter.perf.InstrumentationException; - -class SystemIndependentInstrumenter extends ClassVisitor { - static final String ANNOTATION = "@SystemIndependent"; - static final String ANNOTATION_CLASS = "org/jetbrains/annotations/SystemIndependent"; - static final String ASSERTION_SIGNATURE = "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"; - - private final String myAssertionMethodName; - - private String myClassName; - private boolean myAssertionAdded; - - SystemIndependentInstrumenter(ClassWriter writer, String assertionMethodName) { - super(Opcodes.API_VERSION, writer); - myAssertionMethodName = assertionMethodName; - } - - public boolean isAssertionAdded() { - return myAssertionAdded; - } - - @Override - public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { - myClassName = name; - super.visit(version, access, name, signature, superName, interfaces); - } - - @Override - public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { - Type[] argumentTypes = Type.getArgumentTypes(desc); - - Parameter[] parameters = new Parameter[argumentTypes.length]; - - int slot = (access & Opcodes.ACC_STATIC) != 0 ? 0 : 1; - for (int i = 0; i < argumentTypes.length; i++) { - Type argumentType = argumentTypes[i]; - - Parameter parameter = new Parameter(); - parameter.name = Integer.toString(i); - parameter.slot = slot; - parameter.isString = argumentType.getSort() == Type.OBJECT && "java.lang.String".equals(argumentType.getClassName()); - - parameters[i] = parameter; - - slot += argumentType.getSize(); - } - - return new MethodVisitor(api, super.visitMethod(access, name, desc, signature, exceptions)) { - private int myParameterIndex = 0; - - @Override - public void visitParameter(String name, int access) { - parameters[myParameterIndex].name = name; - myParameterIndex++; - super.visitParameter(name, access); - } - - @Override - public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) { - if (typePath == null) { - TypeReference ref = new TypeReference(typeRef); - if (ref.getSort() == TypeReference.METHOD_FORMAL_PARAMETER && ("L" + ANNOTATION_CLASS + ";").equals(desc)) { - parameters[ref.getFormalParameterIndex()].isSystemIndependent = true; - } - } - return super.visitTypeAnnotation(typeRef, typePath, desc, visible); - } - - @Override - public void visitCode() { - super.visitCode(); - - for (Parameter parameter : parameters) { - if (parameter.isSystemIndependent) { - if (!parameter.isString) { - throw new InstrumentationException("Only String can be annotated as " + ANNOTATION); - } - addAssertionFor(parameter.name, parameter.slot); - myAssertionAdded = true; - } - } - } - - private void addAssertionFor(String parameterName, int parameterSlot) { - visitLdcInsn(myClassName); - visitLdcInsn(name); - visitLdcInsn(parameterName); - visitVarInsn(Opcodes.ALOAD, parameterSlot); - visitMethodInsn(Opcodes.INVOKESTATIC, myClassName, myAssertionMethodName, ASSERTION_SIGNATURE, false); - } - }; - } - - private static class Parameter { - String name; - int slot; - boolean isString; - boolean isSystemIndependent; - } -} diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/internal/SystemIndependentInstrumentingBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/internal/SystemIndependentInstrumentingBuilder.java deleted file mode 100644 index f2efc93dce7c..000000000000 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/internal/SystemIndependentInstrumentingBuilder.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2000-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.jps.incremental.instrumentation.internal; - -import com.intellij.compiler.instrumentation.InstrumentationClassFinder; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jps.ModuleChunk; -import org.jetbrains.jps.incremental.BinaryContent; -import org.jetbrains.jps.incremental.CompileContext; -import org.jetbrains.jps.incremental.CompiledClass; -import org.jetbrains.jps.incremental.instrumentation.BaseInstrumentingBuilder; -import org.jetbrains.jps.incremental.instrumentation.NotNullInstrumentingBuilder; -import org.jetbrains.jps.incremental.messages.BuildMessage; -import org.jetbrains.jps.incremental.messages.CompilerMessage; -import org.jetbrains.org.objectweb.asm.*; -import sun.management.counter.perf.InstrumentationException; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import static org.jetbrains.org.objectweb.asm.Opcodes.ACC_SYNTHETIC; - -/** - * Adds assertions for method / constructor parameters that are annotated as @SystemDependent. - *

- * TODO Add other kind of checks (method return, etc). - */ -public class SystemIndependentInstrumentingBuilder extends BaseInstrumentingBuilder { - private MethodTemplate myAssertionMethodTemplate = new MethodTemplate(AssertionMethodImpl.class); - - @NotNull - @Override - public String getPresentableName() { - return "Path type instrumentation"; - } - - @Override - protected String getProgressMessage() { - return "Adding path type assertions..."; - } - - @Override - protected boolean isEnabled(CompileContext context, ModuleChunk chunk) { - return NotNullInstrumentingBuilder.isEnabledIn(context); - } - - @Override - protected boolean isEnabled(CompileContext context, InstrumentationClassFinder finder) throws IOException { - return finder.isAvaiable(SystemIndependentInstrumenter.ANNOTATION_CLASS + ".class"); - } - - @Override - protected boolean canInstrument(CompiledClass compiledClass, int classFileVersion) { - return !"module-info".equals(compiledClass.getClassName()); - } - - @Nullable - @Override - protected BinaryContent instrument(CompileContext context, - CompiledClass compiled, - ClassReader reader, - ClassWriter writer, - InstrumentationClassFinder finder) { - String assertionMethodName = unique("$$$assertArgumentIsSystemIndependent$$$", methodNamesFrom(reader)); - try { - SystemIndependentInstrumenter instrumenter = new SystemIndependentInstrumenter(writer, assertionMethodName); - reader.accept(instrumenter, 0); - if (instrumenter.isAssertionAdded()) { - myAssertionMethodTemplate.write(writer, ACC_SYNTHETIC, assertionMethodName); - return new BinaryContent(writer.toByteArray()); - } - } - catch (InstrumentationException e) { - context.processMessage(new CompilerMessage(getPresentableName(), BuildMessage.Kind.ERROR, e.getMessage())); - } - return null; - } - - private static List methodNamesFrom(ClassReader reader) { - List myNames = new ArrayList<>(); - - reader.accept(new ClassVisitor(Opcodes.API_VERSION) { - @Override - public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { - myNames.add(name); - return null; - } - }, 0); - - return myNames; - } - - private static String unique(String string, List strings) { - for (int i = 0; i < Integer.MAX_VALUE; i++) { - String name = i == 0 ? string : string + i; - if (!strings.contains(name)) { - return name; - } - } - throw new RuntimeException("Cannot make unique: " + string); - } -}