Skip to content

Commit 19ed4e2

Browse files
committed
Add the concept of a higher level grouping for code.
1 parent ab6ce58 commit 19ed4e2

File tree

7 files changed

+35
-21
lines changed

7 files changed

+35
-21
lines changed

codepulse/src/main/resources/toserve/pages/traces/PackageController.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
// initialize the `stateTemplate` and `widgets` maps
3535
// based on the package nodes in `treeData`
3636
;(function setupTreeHierarchy(packageParentNode, node){
37-
if(node.kind == 'package' || node.kind == 'root'){
37+
if(node.kind == 'package' || node.kind == 'group' || node.kind == 'root'){
3838

3939
var pw = new PackageWidget()
4040
widgets[node.id] = pw
@@ -62,7 +62,7 @@
6262
pw.selectable(false)
6363
}
6464

65-
if(node.kind == 'package'){
65+
if(node.kind == 'group' || node.kind == 'package'){
6666
if(packageParentNode){
6767
widgets[packageParentNode.id].children.add(pw)
6868
} else {
@@ -75,13 +75,16 @@
7575
var parentName = packageParentNode ? packageParentNode.name : '',
7676
abbrevName = node.name.substr(parentName.length)
7777

78+
if (packageParentNode && packageParentNode.kind == 'group')
79+
abbrevName = abbrevName.substr(1)
80+
7881
pw.fullLabel(node.name).abbreviatedLabel(abbrevName)
7982
}
8083
}
8184
}
8285

8386
;(node.children || []).forEach(function(kid){
84-
var nextParent = (node.kind == 'package')? node : packageParentNode
87+
var nextParent = (node.kind == 'group' || node.kind == 'package')? node : packageParentNode
8588
setupTreeHierarchy(nextParent, kid)
8689
})
8790

codepulse/src/main/resources/toserve/pages/traces/TraceTreeData.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434

3535
treeProjector = new TreeProjector(d)
3636

37-
fullTree = treeProjector.projectFullTree(true /* generate self nodes for packages */)
37+
fullTree = treeProjector.projectFullTree(false /* generate self nodes for packages */)
3838

3939
fullTree.forEachNode(true, function(n){
4040
coverageSets[n.id] = d3.set()

codepulse/src/main/scala/com/secdec/codepulse/data/bytecode/CodeForestBuilder.scala

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -72,21 +72,21 @@ class CodeForestBuilder {
7272
this
7373
}
7474

75-
def getOrAddMethod(rawSig: String, size: Int): Option[CodeTreeNode] = {
76-
MethodSignatureParser.parseSignature(rawSig) map { getOrAddMethod(_, size) }
75+
def getOrAddMethod(group: String, rawSig: String, size: Int): Option[CodeTreeNode] = {
76+
MethodSignatureParser.parseSignature(rawSig) map { getOrAddMethod(group, _, size) }
7777
}
7878

79-
def getOrAddMethod(sig: MethodSignature, size: Int): CodeTreeNode = {
79+
def getOrAddMethod(group: String, sig: MethodSignature, size: Int): CodeTreeNode = {
8080
val treePath = CodePath.parse(sig)
81-
val startNode = addRootPackage(treePath.name)
81+
val startNode = addGroup(group)
8282

8383
def recurse(parent: CodeTreeNode, path: CodePath): CodeTreeNode = path match {
8484
case CodePath.Package(name, childPath) => recurse(addChildPackage(parent, name), childPath)
8585
case CodePath.Class(name, childPath) => recurse(addChildClass(parent, name), childPath)
8686
case CodePath.Method(name) => addChildMethod(parent, name, size)
8787
}
8888

89-
recurse(startNode, treePath.child)
89+
recurse(startNode, treePath)
9090
}
9191

9292
def getOrAddJsp(path: List[String], size: Int): CodeTreeNode = {
@@ -95,13 +95,13 @@ class CodeForestBuilder {
9595
case packageNode :: rest => recurse(addChildPackage(parent, packageNode), rest)
9696
}
9797

98-
recurse(addRootPackage("JSPs"), path)
98+
recurse(addGroup("JSPs"), path)
9999
}
100100

101-
protected def addRootPackage(name: String) = roots.find { node =>
102-
node.name == name && node.kind == CodeTreeNodeKind.Pkg
101+
protected def addGroup(name: String) = roots.find { node =>
102+
node.name == name && node.kind == CodeTreeNodeKind.Grp
103103
} getOrElse {
104-
val node = nodeFactory.createPackageNode(name)
104+
val node = nodeFactory.createGroupNode(name)
105105
roots.add(node)
106106
node
107107
}

codepulse/src/main/scala/com/secdec/codepulse/data/bytecode/CodeTree2.scala

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,20 +99,26 @@ object CodeTreeNode {
9999
}
100100

101101
def weightCriteria(node: CodeTreeNode) = node.kind match {
102-
case CodeTreeNodeKind.Pkg => 0
103-
case CodeTreeNodeKind.Cls => 1
104-
case CodeTreeNodeKind.Mth => 2
102+
case CodeTreeNodeKind.Grp => 0
103+
case CodeTreeNodeKind.Pkg => 1
104+
case CodeTreeNodeKind.Cls => 2
105+
case CodeTreeNodeKind.Mth => 3
105106
}
106107

107108
}
108109

109110
trait CodeTreeNodeFactory {
111+
def createGroupNode(name: String): CodeTreeNode
110112
def createPackageNode(name: String): CodeTreeNode
111113
def createClassNode(name: String): CodeTreeNode
112114
def createMethodNode(name: String, size: Int): CodeTreeNode
113115
}
114116

115117
object CodeTreeNodeFactory {
118+
private case class GroupNode(id: Int, name: String) extends CodeTreeNode {
119+
def kind = CodeTreeNodeKind.Grp
120+
def size = None
121+
}
116122
private case class PackageNode(id: Int, name: String) extends CodeTreeNode {
117123
def kind = CodeTreeNodeKind.Pkg
118124
def size = None
@@ -131,18 +137,21 @@ object CodeTreeNodeFactory {
131137
class DefaultImpl extends CodeTreeNodeFactory {
132138
val ids = Iterator from 0
133139

140+
def createGroupNode(name: String): CodeTreeNode = GroupNode(ids.next, name)
134141
def createPackageNode(name: String): CodeTreeNode = PackageNode(ids.next, name)
135142
def createClassNode(name: String): CodeTreeNode = ClassNode(ids.next, name)
136143
def createMethodNode(name: String, size: Int): CodeTreeNode = MethodNode(ids.next, name, size)
137144
}
138145
}
139146
sealed abstract class CodeTreeNodeKind(val label: String)
140147
object CodeTreeNodeKind {
148+
case object Grp extends CodeTreeNodeKind("group")
141149
case object Pkg extends CodeTreeNodeKind("package")
142150
case object Cls extends CodeTreeNodeKind("class")
143151
case object Mth extends CodeTreeNodeKind("method")
144152

145153
def unapply(label: String) = label match {
154+
case Grp.label => Some(Grp)
146155
case Pkg.label => Some(Pkg)
147156
case Cls.label => Some(Cls)
148157
case Mth.label => Some(Mth)

codepulse/src/main/scala/com/secdec/codepulse/data/trace/slick/TreeNodeDataDao.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ private[slick] class TreeNodeDataDao(val driver: JdbcProfile) {
3333

3434
class TreeNodeData(tag: Tag) extends Table[TreeNode](tag, "tree_node_data") {
3535
private val CodeTreeNodeKindMapping = Map[CodeTreeNodeKind, Char](
36+
CodeTreeNodeKind.Grp -> 'g',
3637
CodeTreeNodeKind.Pkg -> 'p',
3738
CodeTreeNodeKind.Cls -> 'c',
3839
CodeTreeNodeKind.Mth -> 'm')

codepulse/src/main/scala/com/secdec/codepulse/tracer/TraceUploadData.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,14 +110,15 @@ object TraceUploadData {
110110
//TODO: make this configurable somehow
111111
val jspAdapter = new JasperJspAdapter
112112

113-
ZipEntryChecker.forEachEntry(file) { (entry, contents) =>
113+
ZipEntryChecker.forEachEntry(file) { (filename, entry, contents) =>
114+
val groupName = if (filename == file.getName) "\"classes\"" else new File(filename).getName
114115
if (!entry.isDirectory) {
115116
FilenameUtils.getExtension(entry.getName) match {
116117
case "class" =>
117118
val methods = AsmVisitors.parseMethodsFromClass(contents)
118119
for {
119120
(name, size) <- methods
120-
treeNode <- builder.getOrAddMethod(name, size)
121+
treeNode <- builder.getOrAddMethod(groupName, name, size)
121122
} methodCorrelationsBuilder += (name -> treeNode.id)
122123

123124
case "jsp" =>

codepulse/src/main/scala/com/secdec/codepulse/util/ZipEntryChecker.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ trait ZipEntryChecker {
6262
case _ => false
6363
}
6464

65-
def forEachEntry(file: File)(callback: (ZipEntry, InputStream) => Unit): Unit = {
65+
def forEachEntry(file: File)(callback: (String, ZipEntry, InputStream) => Unit): Unit = {
6666
Try { new ZipFile(file) } match {
6767
// non-zip files don't work in this checker
6868
case Failure(_) =>
@@ -81,14 +81,14 @@ trait ZipEntryChecker {
8181
Stream.continually(zipStream.getNextEntry)
8282
.takeWhile(_ != null)
8383
.filterNot(ZipCleaner.shouldFilter)
84-
.foreach { innerEntry => callback(innerEntry, zipStream) }
84+
.foreach { innerEntry => callback(entry.getName, innerEntry, zipStream) }
8585

8686
} finally {
8787
zipStream.close()
8888
}
8989
} else {
9090
try {
91-
callback(entry, stream)
91+
callback(file.getName, entry, stream)
9292
} finally {
9393
stream.close
9494
}

0 commit comments

Comments
 (0)