com.undefinedlabs.scope.coverage.utils.CoverageAnalyzerUtils Maven / Gradle / Ivy
package com.undefinedlabs.scope.coverage.utils;
import com.undefinedlabs.scope.logger.ScopeLogger;
import com.undefinedlabs.scope.logger.ScopeLoggerResolver;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.apache.bcel.Repository;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.LineNumber;
import org.apache.bcel.classfile.LineNumberTable;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.generic.ClassGen;
import org.apache.bcel.generic.MethodGen;
public enum CoverageAnalyzerUtils {
INSTANCE;
private static final ScopeLogger LOGGER = ScopeLoggerResolver.INSTANCE.get();
private static final ConcurrentMap> linesPerClassName =
new ConcurrentHashMap<>();
public List buildAllLinesPerClassName(final String className) {
final List storedLines = linesPerClassName.get(className);
if (storedLines != null) {
return storedLines;
}
try {
final JavaClass javaClass = Repository.lookupClass(className);
final List lines = new ArrayList<>();
for (final Method bcelMethod : javaClass.getMethods()) {
final MethodGen methodGen =
new MethodGen(
bcelMethod, javaClass.getClassName(), new ClassGen(javaClass).getConstantPool());
final LineNumberTable lineNumberTable =
methodGen.getLineNumberTable(methodGen.getConstantPool());
for (final LineNumber lineNumber : lineNumberTable.getLineNumberTable()) {
lines.add(lineNumber.getLineNumber());
}
Collections.sort(lines);
linesPerClassName.putIfAbsent(className, lines);
}
return lines;
} catch (final Exception e) {
LOGGER.error(
"[COVERAGE] Error calculating all source code lines for class: '"
+ className
+ "'. Exception: "
+ e);
return Collections.emptyList();
}
}
public Map> buildAllLinesPerClassName(final Set classNames) {
final Map> allLinesPerClassMap = new HashMap<>();
for (final String className : classNames) {
final List lines = buildAllLinesPerClassName(className);
if (lines.size() == 0) {
LOGGER.trace(
"--- Coverage: It could not be possible to detect executable lines for class '"
+ className
+ "'");
continue;
}
allLinesPerClassMap.put(className, lines);
}
return allLinesPerClassMap;
}
}