Skip to content

Commit

Permalink
[WIP] seeing lots of strange results
Browse files Browse the repository at this point in the history
  • Loading branch information
avantgardnerio committed Oct 31, 2018
1 parent 358a6e3 commit 046958f
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 12 deletions.
45 changes: 43 additions & 2 deletions src/main/kotlin/net/squarelabs/depends/Reporter.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package net.squarelabs.depends

import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.SerializationFeature
import net.squarelabs.depends.models.Artifact
import java.io.File

fun fqmns(a: Artifact): HashSet<String> = HashSet(a.classes.values.flatMap { c -> c.methods.values.map { m -> "${c.name}:${m.name}${m.descriptor}" } })

Expand All @@ -27,14 +30,52 @@ fun removedMethods(artifacts: Collection<Artifact>): Set<String> {
return accumulator
}

fun apiMethods(state: State): Set<String> {
val methods = mutableSetOf<String>()
val missing = mutableSetOf<String>()
state.artifactsByGa.values.forEach { artifacts ->
artifacts.values.forEach { artifact ->
println("finding api methods for artifact: ${artifact.coordinate}")
val callerGa = "${artifact.coordinate.split(":")[0]}:${artifact.coordinate.split(":")[1]}"
artifact.classes.values.forEach { clazz ->
clazz.methods.values.forEach { method ->
method.invocations.forEach { call ->
val callee = "${call.fqcn.replace("/", ".")}.${call.methodName}${call.descriptor}"
//println("${state.artifactsByMethod.size} callee: $callee example: ${state.artifactsByMethod.keys.first()}")
val providers:MutableSet<String>? = state.artifactsByMethod.get(callee)
if(providers != null) {
val exporters = providers.filter { art ->
val providerGa = "${art.split(":")[0]}:${art.split(":")[1]}"
providerGa != callerGa
}
if(exporters.isNotEmpty()) methods.add(callee)
} else {
if(!callee.startsWith("java")) {
missing.add(callee)
}
}
}
}
}
}
}
File("missing.json").printWriter().use { writer ->
val mapper = ObjectMapper()
mapper.enable(SerializationFeature.INDENT_OUTPUT)
mapper.writeValue(writer, missing)
}

return methods
}

fun populateIndices(state: State) {
state.artifactsByGa.values.forEach { artifacts ->
artifacts.values.forEach { artifact ->
println("indexing artifact: ${artifact.coordinate}")
artifact.classes.values.forEach { c ->
c.methods.keys.forEach { m ->
val fqmn = "${c.name}:$m"
val methodProviders = state.artifactsByMethod.computeIfAbsent(fqmn) { mutableSetOf() }
val fqmn = "${c.name}.$m"
val methodProviders = state.artifactsByMethod.computeIfAbsent(fqmn) { HashSet() }
methodProviders.add(artifact.coordinate)
}
}
Expand Down
14 changes: 7 additions & 7 deletions src/main/kotlin/net/squarelabs/depends/Resolver.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ var invocationCount = 0

fun resolve(coordinate: String, state: State): Artifact {
val terms = coordinate.split(":")
val ga = state.artifactsByGa.computeIfAbsent("${terms[0]}:${terms[1]}") { mutableMapOf() }
val ga = state.artifactsByGa.computeIfAbsent("${terms[0]}:${terms[1]}") { HashMap() }
val version = terms[terms.size - 1]
return ga.computeIfAbsent(version) { version ->
val artifacts = Maven.resolver()
Expand Down Expand Up @@ -56,21 +56,21 @@ fun methodsFromClass(clazz: ClassPath.ClassInfo, loader: URLClassLoader): Map<St
val cl = object : ClassVisitor(Opcodes.ASM7) {
override fun visitMethod(access: Int, methodName: String,
desc: String, signature: String?, exceptions: Array<String>?): MethodVisitor? {
val invocations = mutableListOf<Invocation>()
val method = Method(methodName, desc)
val methodId = "$methodName$desc"
assert(methods[methodId] == null)
methods[methodId] = method

val oriMv: MethodVisitor = object : MethodVisitor(Opcodes.ASM7) {}
val instMv = object : InstructionAdapter(Opcodes.ASM7, oriMv) {
override fun visitMethodInsn(opcode: Int, owner: String, name: String, descriptor: String, isInterface: Boolean) {
invocationCount++
//invocations.add(Invocation(owner, name, descriptor))
method.invocations.add(Invocation(owner, name, descriptor))
//println("invoke $owner.$name from ${clazz.name}.$methodName()")
super.visitMethodInsn(opcode, owner, name, descriptor, isInterface)
}
}
methodCount++
val method = Method(methodName, desc, invocations.toList())
val methodId = "$methodName$desc"
assert(methods[methodId] == null)
methods[methodId] = method
return instMv
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/main/kotlin/net/squarelabs/depends/State.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ package net.squarelabs.depends
import net.squarelabs.depends.models.Artifact

data class State(
val artifactsByGa: MutableMap<String, MutableMap<String, Artifact>> = mutableMapOf(),
val artifactsByMethod: MutableMap<String, MutableSet<String>> = mutableMapOf()
val artifactsByGa: HashMap<String, HashMap<String, Artifact>> = HashMap(),
val artifactsByMethod: HashMap<String, HashSet<String>> = HashMap()
)
2 changes: 1 addition & 1 deletion src/main/kotlin/net/squarelabs/depends/models/Method.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ package net.squarelabs.depends.models
data class Method(
val name: String,
val descriptor: String,
val invocations: List<Invocation>
val invocations: MutableSet<Invocation> = mutableSetOf()
)
17 changes: 17 additions & 0 deletions src/test/kotlin/net/squarelabs/depends/ResolverTest.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package net.squarelabs.depends

import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.SerializationFeature
import net.squarelabs.depends.models.Artifact
import org.junit.Test
import java.io.File
import java.text.DecimalFormat

class ResolverTest {
Expand All @@ -12,6 +15,12 @@ class ResolverTest {
val state = State()
val root: Artifact = resolve("io.dropwizard:dropwizard-core:1.3.7", state)
populateIndices(state)
File("artifactsByMethod.json").printWriter().use { writer ->
val mapper = ObjectMapper()
mapper.enable(SerializationFeature.INDENT_OUTPUT)
mapper.writeValue(writer, state.artifactsByMethod)
}

val conflicts = state.artifactsByGa.keys
.filter { key -> state.artifactsByGa[key]!!.size > 1 }
.map { key -> key + ": " + state.artifactsByGa[key]!!.keys.joinToString() }
Expand All @@ -26,6 +35,14 @@ class ResolverTest {
.flatMap { artifacts -> removedMethods(artifacts) }
println("methods removed: ${removedMethods.size}")

// find apis
val apis = apiMethods(state)
println("api methods: ${apis.size}")

// find removed apis
val brokenApis = apis.intersect(removedMethods)
println("broken apis: ${brokenApis.size}")

// print memory
Runtime.getRuntime().gc()
println("Used mem: ${DecimalFormat("#,##0").format(runtime.totalMemory() - runtime.freeMemory())}")
Expand Down

0 comments on commit 046958f

Please sign in to comment.