BytecodeAnalysis refactoring: hashing in single place; cosmetics

This commit is contained in:
Tagir Valeev
2017-05-30 13:47:05 +07:00
parent 97eaee737b
commit c8633ffc7c
5 changed files with 34 additions and 58 deletions

View File

@@ -18,7 +18,6 @@ package com.intellij.codeInspection.bytecodeAnalysis;
import com.intellij.codeInspection.dataFlow.MethodContract.ValueConstraint;
import com.intellij.codeInspection.dataFlow.StandardMethodContract;
import com.intellij.openapi.util.ThreadLocalCachedValue;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.TypeConversionUtil;
@@ -38,12 +37,6 @@ import static com.intellij.codeInspection.bytecodeAnalysis.ProjectBytecodeAnalys
*/
public class BytecodeAnalysisConverter {
// how many bytes are taken from class fqn digest
public static final int CLASS_HASH_SIZE = 10;
// how many bytes are taken from signature digest
public static final int SIGNATURE_HASH_SIZE = 4;
public static final int HASH_SIZE = CLASS_HASH_SIZE + SIGNATURE_HASH_SIZE;
private static final ThreadLocalCachedValue<MessageDigest> HASHER_CACHE = new ThreadLocalCachedValue<MessageDigest>() {
@Override
public MessageDigest create() {
@@ -65,49 +58,26 @@ public class BytecodeAnalysisConverter {
}
/**
* Converts a Psi method to a small hash key (Key).
* Converts a Psi method to a hashed EKey.
* Returns null if conversion is impossible (something is not resolvable).
*/
@Nullable
public static EKey psiKey(@NotNull PsiMethod psiMethod, @NotNull Direction direction, @NotNull MessageDigest md) {
final PsiClass psiClass = PsiTreeUtil.getParentOfType(psiMethod, PsiClass.class, false);
final PsiClass psiClass = psiMethod.getContainingClass();
if (psiClass == null) {
return null;
}
byte[] classDigest = psiClassDigest(psiClass, md);
if (classDigest == null) {
String className = descriptor(psiClass, 0, false);
String methodSig = methodSignature(psiMethod);
if (className == null || methodSig == null) {
return null;
}
byte[] sigDigest = methodDigest(psiMethod, md);
if (sigDigest == null) {
return null;
}
byte[] digest = new byte[HASH_SIZE];
System.arraycopy(classDigest, 0, digest, 0, CLASS_HASH_SIZE);
System.arraycopy(sigDigest, 0, digest, CLASS_HASH_SIZE, SIGNATURE_HASH_SIZE);
return new EKey(new HMethod(digest), direction, true, false);
String methodName = psiMethod.getReturnType() == null ? "<init>" : psiMethod.getName();
return new EKey(new Method(className, methodName, methodSig).hashed(md), direction, true, false);
}
@Nullable
private static byte[] psiClassDigest(@NotNull PsiClass psiClass, @NotNull MessageDigest md) {
String descriptor = descriptor(psiClass, 0, false);
if (descriptor == null) {
return null;
}
return md.digest(descriptor.getBytes(CharsetToolkit.UTF8_CHARSET));
}
@Nullable
private static byte[] methodDigest(@NotNull PsiMethod psiMethod, @NotNull MessageDigest md) {
String descriptor = descriptor(psiMethod);
if (descriptor == null) {
return null;
}
return md.digest(descriptor.getBytes(CharsetToolkit.UTF8_CHARSET));
}
@Nullable
private static String descriptor(@NotNull PsiMethod psiMethod) {
private static String methodSignature(@NotNull PsiMethod psiMethod) {
StringBuilder sb = new StringBuilder();
final PsiClass psiClass = PsiTreeUtil.getParentOfType(psiMethod, PsiClass.class, false);
if (psiClass == null) {
@@ -118,7 +88,6 @@ public class BytecodeAnalysisConverter {
PsiParameter[] parameters = psiMethod.getParameterList().getParameters();
PsiType returnType = psiMethod.getReturnType();
sb.append(returnType == null ? "<init>" : psiMethod.getName());
sb.append('(');
String desc;

View File

@@ -141,7 +141,7 @@ public class BytecodeAnalysisIndex extends ScalarIndexExtension<HMethod> {
@Override
public HMethod read(@NotNull DataInput in) throws IOException {
byte[] bytes = new byte[BytecodeAnalysisConverter.HASH_SIZE];
byte[] bytes = new byte[HMethod.HASH_SIZE];
in.readFully(bytes);
return new HMethod(bytes);
}
@@ -270,7 +270,7 @@ public class BytecodeAnalysisIndex extends ScalarIndexExtension<HMethod> {
effects.add(EffectQuantum.ThisChangeQuantum);
}
else if (effectMask == -3){
byte[] bytes = new byte[BytecodeAnalysisConverter.HASH_SIZE];
byte[] bytes = new byte[HMethod.HASH_SIZE];
in.readFully(bytes);
int rawDirKey = DataInputOutputUtil.readINT(in);
boolean isStable = in.readBoolean();
@@ -324,7 +324,7 @@ public class BytecodeAnalysisIndex extends ScalarIndexExtension<HMethod> {
int componentSize = DataInputOutputUtil.readINT(in);
EKey[] ids = new EKey[componentSize];
for (int j = 0; j < componentSize; j++) {
byte[] bytes = new byte[BytecodeAnalysisConverter.HASH_SIZE];
byte[] bytes = new byte[HMethod.HASH_SIZE];
in.readFully(bytes);
int rawDirKey = DataInputOutputUtil.readINT(in);
ids[j] = new EKey(new HMethod(bytes), Direction.fromInt(Math.abs(rawDirKey)), in.readBoolean(), rawDirKey < 0);

View File

@@ -15,7 +15,6 @@
*/
package com.intellij.codeInspection.bytecodeAnalysis;
import com.intellij.util.ArrayFactory;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
@@ -28,7 +27,6 @@ import java.util.Set;
*/
final class Component {
static final Component[] EMPTY_ARRAY = new Component[0];
static final ArrayFactory<Component> ARRAY_FACTORY = count -> count == 0 ? EMPTY_ARRAY : new Component[count];
@NotNull Value value;
@NotNull final EKey[] ids;

View File

@@ -15,19 +15,41 @@
*/
package com.intellij.codeInspection.bytecodeAnalysis;
import com.intellij.openapi.vfs.CharsetToolkit;
import one.util.streamex.IntStreamEx;
import org.jetbrains.annotations.NotNull;
import java.security.MessageDigest;
import java.util.Arrays;
import static com.intellij.codeInspection.bytecodeAnalysis.BytecodeAnalysisConverter.getMessageDigest;
/**
* Hashed representation of method.
*/
public final class HMethod implements MethodDescriptor {
// how many bytes are taken from class fqn digest
private static final int CLASS_HASH_SIZE = 10;
// how many bytes are taken from signature digest
private static final int SIGNATURE_HASH_SIZE = 4;
static final int HASH_SIZE = CLASS_HASH_SIZE + SIGNATURE_HASH_SIZE;
@NotNull
final byte[] myBytes;
HMethod(Method method, MessageDigest md) {
if (md == null) {
md = getMessageDigest();
}
byte[] classDigest = md.digest(method.internalClassName.getBytes(CharsetToolkit.UTF8_CHARSET));
md.update(method.methodName.getBytes(CharsetToolkit.UTF8_CHARSET));
md.update(method.methodDesc.getBytes(CharsetToolkit.UTF8_CHARSET));
byte[] sigDigest = md.digest();
myBytes = new byte[HASH_SIZE];
System.arraycopy(classDigest, 0, myBytes, 0, CLASS_HASH_SIZE);
System.arraycopy(sigDigest, 0, myBytes, CLASS_HASH_SIZE, SIGNATURE_HASH_SIZE);
}
public HMethod(@NotNull byte[] bytes) {
myBytes = bytes;
}

View File

@@ -15,15 +15,12 @@
*/
package com.intellij.codeInspection.bytecodeAnalysis;
import com.intellij.openapi.vfs.CharsetToolkit;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode;
import java.security.MessageDigest;
import static com.intellij.codeInspection.bytecodeAnalysis.BytecodeAnalysisConverter.*;
public final class Method implements MethodDescriptor {
final String internalClassName;
final String methodName;
@@ -72,17 +69,7 @@ public final class Method implements MethodDescriptor {
@NotNull
@Override
public HMethod hashed(@Nullable MessageDigest md) {
if (md == null) {
md = getMessageDigest();
}
byte[] classDigest = md.digest(internalClassName.getBytes(CharsetToolkit.UTF8_CHARSET));
md.update(methodName.getBytes(CharsetToolkit.UTF8_CHARSET));
md.update(methodDesc.getBytes(CharsetToolkit.UTF8_CHARSET));
byte[] sigDigest = md.digest();
byte[] digest = new byte[HASH_SIZE];
System.arraycopy(classDigest, 0, digest, 0, CLASS_HASH_SIZE);
System.arraycopy(sigDigest, 0, digest, CLASS_HASH_SIZE, SIGNATURE_HASH_SIZE);
return new HMethod(digest);
return new HMethod(this, md);
}
@Override