Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restoring Comment Matcher Functionality #1388

Merged
merged 19 commits into from
Jan 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
b4c21a8
fix out of bounds
maximiliankaul Nov 30, 2023
9ccacd0
improved codeOf
maximiliankaul Dec 1, 2023
ff25972
comment matching first draft
maximiliankaul Dec 1, 2023
60517d2
fix index
maximiliankaul Dec 1, 2023
e014325
Merge branch 'main' into mk/pythonCommentMatcher
maximiliankaul Dec 4, 2023
14ce023
Merge branch 'main' into mk/pythonCommentMatcher
konradweiss Jan 2, 2024
bbdd21b
Allow usage of older python version 3.8 and adapt ast element matchin…
konradweiss Jan 4, 2024
cc65468
Using the right number encoded token to identify a comment and additi…
konradweiss Jan 4, 2024
cb40d3e
Merge branch 'mk/pythonCommentMatcher' of github.com:Fraunhofer-AISEC…
konradweiss Jan 4, 2024
a37310e
ASTarg also has location information
oxisto Jan 8, 2024
5df28d6
Give the body a location, in this case the location of the parent, fu…
konradweiss Jan 8, 2024
e76d7b8
Improve comment matching, remove rawNode for key value expression as …
konradweiss Jan 9, 2024
a324849
Merge branch 'main' into mk/pythonCommentMatcher
konradweiss Jan 16, 2024
567f099
Set code and location of certain nodes based on parent and Children
konradweiss Jan 16, 2024
ce228e0
Merge branch 'main' into mk/pythonCommentMatcher
konradweiss Jan 16, 2024
e7d5e1e
Fixing region column computation and test, not removing whitespaces i…
konradweiss Jan 16, 2024
a936e1a
Fixing region test to sarif region
konradweiss Jan 16, 2024
7bc05f0
Merge branch 'main' into mk/pythonCommentMatcher
oxisto Jan 19, 2024
c0c8c37
Merge branch 'main' into mk/pythonCommentMatcher
oxisto Jan 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ class CommentMatcher {
.filter {
artifactLocation == null || artifactLocation == it.location?.artifactLocation
}
.toMutableList()
.toMutableSet()

// Because we sometimes wrap all elements into a NamespaceDeclaration we have to extract the
// children with a location
Expand All @@ -109,6 +109,19 @@ class CommentMatcher {
}
)

// When a child has no location we can not properly consider it for comment matching,
// however, it might have
// a child with a location that we want to consider, this can overlap with namespaces but
// nodes are considered
// only once in the set
children.addAll(
children
.filter { node -> node.location == null || node.location?.region == Region() }
.flatMap { locationLess ->
SubgraphWalker.getAstChildren(locationLess).filter { it !in children }
}
)

// Searching for the closest successor to our comment amongst the children of the smallest
// enclosing nodes
val successors =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,13 @@ class ExpressionHandler(frontend: PythonLanguageFrontend) :
private fun handleDict(node: Python.ASTDict): Expression {
val lst = mutableListOf<Expression>()
for (i in node.values.indices) { // TODO: keys longer than values possible?
// Here we can not use node as raw node as it spans all keys and values
lst +=
newKeyValueExpression(
key = node.keys[i]?.let { handle(it) },
value = handle(node.values[i]),
rawNode = node
)
key = node.keys[i]?.let { handle(it) },
value = handle(node.values[i]),
)
.codeAndLocationFromChildren(node)
}
val ile = newInitializerListExpression(rawNode = node)
ile.initializers = lst.toList()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ object JepSingleton {
val virtualEnvName = System.getenv("CPG_PYTHON_VIRTUALENV") ?: "cpg"
val virtualEnvPath =
Paths.get(System.getProperty("user.home"), ".virtualenvs", virtualEnvName)
val pythonVersions = listOf("3.9", "3.10", "3.11", "3.12", "3.13")
val pythonVersions = listOf("3.8", "3.9", "3.10", "3.11", "3.12", "3.13")
val wellKnownPaths = mutableListOf<Path>()
pythonVersions.forEach { version ->
// Linux
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1197,7 +1197,7 @@ interface Python {
* | arg(identifier arg, expr? annotation, string? type_comment)
* ```
*/
class ASTarg(pyObject: PyObject) : AST(pyObject) {
class ASTarg(pyObject: PyObject) : AST(pyObject), WithPythonLocation {
val arg: String by lazy { "arg" of pyObject }
val annotation: ASTBASEexpr? by lazy { "annotation" of pyObject }
val type_comment: String? by lazy { "type_comment" of pyObject }
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ class StatementHandler(frontend: PythonLanguageFrontend) :
private fun handleWhile(node: Python.ASTWhile): Statement {
val ret = newWhileStatement(rawNode = node)
ret.condition = frontend.expressionHandler.handle(node.test)
ret.statement = makeBlock(node.body)
ret.statement = makeBlock(node.body).codeAndLocationFromChildren(node)
node.orelse.firstOrNull()?.let { TODO("Not supported") }
return ret
}
Expand All @@ -86,7 +86,7 @@ class StatementHandler(frontend: PythonLanguageFrontend) :
val ret = newForEachStatement(rawNode = node)
ret.iterable = frontend.expressionHandler.handle(node.iter)
ret.variable = frontend.expressionHandler.handle(node.target)
ret.statement = makeBlock(node.body)
ret.statement = makeBlock(node.body).codeAndLocationFromChildren(node)
node.orelse.firstOrNull()?.let { TODO("Not supported") }
return ret
}
Expand Down Expand Up @@ -114,13 +114,13 @@ class StatementHandler(frontend: PythonLanguageFrontend) :
ret.condition = frontend.expressionHandler.handle(node.test)
ret.thenStatement =
if (node.body.isNotEmpty()) {
makeBlock(node.body)
makeBlock(node.body).codeAndLocationFromChildren(node)
} else {
null
}
ret.elseStatement =
if (node.orelse.isNotEmpty()) {
makeBlock(node.orelse)
makeBlock(node.orelse).codeAndLocationFromChildren(node)
} else {
null
}
Expand Down Expand Up @@ -330,7 +330,7 @@ class StatementHandler(frontend: PythonLanguageFrontend) :
// END HANDLE ARGUMENTS

if (s.body.isNotEmpty()) {
result.body = makeBlock(s.body)
result.body = makeBlock(s.body).codeAndLocationFromChildren(s)
}

frontend.scopeManager.leaveScope(result)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -726,13 +726,13 @@ class PythonFrontendTest : BaseTest() {
val p = tu.namespaces["literal"]
assertNotNull(p)

assertEquals(Region(1, 0, 1, 8), (p.statements[0]).location?.region)
assertEquals(Region(1, 4, 1, 8), (p.variables["b"])?.firstAssignment?.location?.region)
assertEquals(Region(2, 0, 2, 6), (p.statements[1]).location?.region)
assertEquals(Region(3, 0, 3, 7), (p.statements[2]).location?.region)
assertEquals(Region(4, 0, 4, 10), (p.statements[3]).location?.region)
assertEquals(Region(5, 0, 5, 11), (p.statements[4]).location?.region)
assertEquals(Region(6, 0, 6, 8), (p.statements[5]).location?.region)
assertEquals(Region(1, 1, 1, 9), (p.statements[0]).location?.region)
assertEquals(Region(1, 5, 1, 9), (p.variables["b"])?.firstAssignment?.location?.region)
assertEquals(Region(2, 1, 2, 7), (p.statements[1]).location?.region)
assertEquals(Region(3, 1, 3, 8), (p.statements[2]).location?.region)
assertEquals(Region(4, 1, 4, 11), (p.statements[3]).location?.region)
assertEquals(Region(5, 1, 5, 12), (p.statements[4]).location?.region)
assertEquals(Region(6, 1, 6, 9), (p.statements[5]).location?.region)
}

@Test
Expand Down Expand Up @@ -935,7 +935,6 @@ class PythonFrontendTest : BaseTest() {
}

@Test
@Ignore // TODO
fun testCommentMatching() {
val topLevel = Path.of("src", "test", "resources", "python")
val tu =
Expand All @@ -950,7 +949,7 @@ class PythonFrontendTest : BaseTest() {

val commentedNodes = SubgraphWalker.flattenAST(tu).filter { it.comment != null }

assertEquals(10, commentedNodes.size)
assertEquals(9, commentedNodes.size)

val functions = commentedNodes.filterIsInstance<FunctionDeclaration>()
assertEquals(1, functions.size)
Expand All @@ -968,9 +967,10 @@ class PythonFrontendTest : BaseTest() {
assertEquals("# a parameter", params.first { it.name.localName == "i" }.comment)
assertEquals("# another parameter", params.first { it.name.localName == "j" }.comment)

val variable = commentedNodes.filterIsInstance<VariableDeclaration>()
assertEquals(1, variable.size)
assertEquals("# A comment", variable.first().comment)
val assignment = commentedNodes.filterIsInstance<AssignExpression>()
assertEquals(2, assignment.size)
assertEquals("# A comment# a number", assignment.first().comment)
assertEquals("# comment end", assignment.last().comment)

val block = commentedNodes.filterIsInstance<Block>()
assertEquals(1, block.size)
Expand All @@ -980,14 +980,6 @@ class PythonFrontendTest : BaseTest() {
assertEquals(2, kvs.size)
assertEquals("# a entry", kvs.first { it.code?.contains("a") ?: false }.comment)
assertEquals("# b entry", kvs.first { it.code?.contains("b") ?: false }.comment)

val declStmts = commentedNodes.filterIsInstance<DeclarationStatement>()
assertEquals(2, declStmts.size)
assertEquals("# a number", declStmts.first { it.location?.region?.startLine == 3 }.comment)
assertEquals(
"# comment end",
declStmts.first { it.location?.region?.startLine == 18 }.comment
)
}

@Test
Expand Down
Loading