mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
@SystemIndependent instrumentation removed (will be in a separate plugin)
This commit is contained in:
-5
@@ -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;
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
+14
-20
@@ -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<File> platformCp = ProjectPaths.getPlatformCompilationClasspath(chunk, false);
|
||||
final Collection<File> classpath = new ArrayList<>();
|
||||
classpath.addAll(ProjectPaths.getCompilationClasspath(chunk, false));
|
||||
classpath.addAll(ProjectPaths.getSourceRootsWithDependents(chunk).keySet());
|
||||
final JpsSdk<JpsDummyElement> 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<File> platformCp = ProjectPaths.getPlatformCompilationClasspath(chunk, false);
|
||||
final Collection<File> classpath = new ArrayList<>();
|
||||
classpath.addAll(ProjectPaths.getCompilationClasspath(chunk, false));
|
||||
classpath.addAll(ProjectPaths.getSourceRootsWithDependents(chunk).keySet());
|
||||
final JpsSdk<JpsDummyElement> 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
|
||||
|
||||
-4
@@ -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();
|
||||
}
|
||||
|
||||
-38
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
-62
@@ -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 "<init>".equals(name) ? null : writer.visitMethod(access | accessModifier, methodName, desc, signature, exceptions);
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
-118
@@ -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;
|
||||
}
|
||||
}
|
||||
-117
@@ -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 <code>@SystemDependent</code>.
|
||||
* <p>
|
||||
* 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<String> methodNamesFrom(ClassReader reader) {
|
||||
List<String> 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<String> 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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user