diff --git a/java/ql/src/Telemetry/APIUsage.qll b/java/ql/src/Telemetry/APIUsage.qll index cde33411b63..816a18a0852 100644 --- a/java/ql/src/Telemetry/APIUsage.qll +++ b/java/ql/src/Telemetry/APIUsage.qll @@ -2,7 +2,7 @@ import java private import semmle.code.java.dataflow.FlowSteps private import semmle.code.java.dataflow.ExternalFlow -private string jarName(CompilationUnit cu) { +string jarName(CompilationUnit cu) { result = cu.getParentContainer().toString().regexpCapture(".*/(.*\\.jar)/?.*", 1) } diff --git a/java/ql/src/Telemetry/ExternalAPI.qll b/java/ql/src/Telemetry/ExternalAPI.qll new file mode 100644 index 00000000000..db83ea6f8e4 --- /dev/null +++ b/java/ql/src/Telemetry/ExternalAPI.qll @@ -0,0 +1,40 @@ +import java +import APIUsage +private import experimental.semmle.code.java.Logging + +class ExternalAPI extends Callable { + ExternalAPI() { + not this.fromSource() and + not this.getDeclaringType().getPackage().getName().matches("java.%") and + not isJavaRuntime(this) + } + + string jarName() { result = jarName(this.getCompilationUnit()) } + + string simpleName() { + result = getDeclaringType().getSourceDeclaration() + "#" + this.getStringSignature() + } +} + +// TODO [bm]: Shall we move this into LoggingCall or a LoggingSetup predicate? +predicate loggingRelated(Call call) { + call instanceof LoggingCall or + call.getCallee().getName() = "getLogger" or // getLogger is not a LoggingCall + call.getCallee().getName() = "isDebugEnabled" // org.slf4j.Logger#isDebugEnabled is not a LoggingCall +} + +class TestLibrary extends RefType { + TestLibrary() { + getPackage() + .getName() + .matches([ + "org.junit%", "junit.%", "org.mockito%", "org.assertj%", + "com.github.tomakehurst.wiremock%", "org.hamcrest%", "org.springframework.test.%", + "org.springframework.mock.%", "org.springframework.boot.test.%", "reactor.test%", + "org.xmlunit%", "org.testcontainers.%", "org.opentest4j%", "org.mockserver%", + "org.powermock%", "org.skyscreamer.jsonassert%", "org.rnorth.visibleassertions", + "org.openqa.selenium%", "com.gargoylesoftware.htmlunit%", + "org.jboss.arquillian.testng%", "org.testng%" + ]) + } +} diff --git a/java/ql/src/Telemetry/ExternalLibraryUsage.ql b/java/ql/src/Telemetry/ExternalLibraryUsage.ql new file mode 100644 index 00000000000..b47091462a8 --- /dev/null +++ b/java/ql/src/Telemetry/ExternalLibraryUsage.ql @@ -0,0 +1,16 @@ +/** + * @name External libraries + * @description A list of external libraries used in the code + * @id java/telemetry/external-libs + */ + +import java +import ExternalAPI + +from ExternalAPI api +where not api.getDeclaringType() instanceof TestLibrary +// TODO [bm]: the count is not aggregated and we have the same jar with multiple usages, e.g. +// 1 protobuf-java-3.17.3.jar 373 +// 2 protobuf-java-3.17.3.jar 48 +select api.jarName() as jarname, count(Call c | c.getCallee() = api) as Usages +order by Usages desc \ No newline at end of file