Skip to content

Commit

Permalink
Merge pull request #17774 from geoffw0/astcount
Browse files Browse the repository at this point in the history
Rust: Count number of AST inconsistencies
  • Loading branch information
geoffw0 authored Oct 16, 2024
2 parents bee073d + feed0eb commit 7d62cda
Show file tree
Hide file tree
Showing 9 changed files with 113 additions and 35 deletions.
29 changes: 8 additions & 21 deletions rust/ql/consistency-queries/AstConsistency.ql
Original file line number Diff line number Diff line change
@@ -1,21 +1,8 @@
import rust
import codeql.rust.elements.internal.generated.ParentChild

query predicate multipleToString(Element e, string s) {
s = strictconcat(e.toString(), ",") and
strictcount(e.toString()) > 1
}

query predicate multipleLocations(Locatable e) { strictcount(e.getLocation()) > 1 }

query predicate multiplePrimaryQlClasses(Element e, string s) {
s = e.getPrimaryQlClasses() and
strictcount(e.getAPrimaryQlClass()) > 1
}

private Element getParent(Element child) { child = getChildAndAccessor(result, _, _) }

query predicate multipleParents(Element child, Element parent) {
parent = getParent(child) and
strictcount(getParent(child)) > 1
}
/**
* @name Abstract syntax tree inconsistencies
* @description Lists the abstract syntax tree inconsistencies in the database. This query is intended for internal use.
* @kind table
* @id rust/diagnostics/ast-consistency
*/

import codeql.rust.AstConsistency
7 changes: 7 additions & 0 deletions rust/ql/consistency-queries/ExtractionConsistency.ql
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
/**
* @name Extraction consistency
* @description Lists the extraction inconsistencies (errors) in the database. This query is intended for internal use.
* @kind table
* @id rust/diagnostics/extraction-consistency
*/

import codeql.rust.Diagnostics

query predicate extractionError(ExtractionError ee) { any() }
Expand Down
55 changes: 55 additions & 0 deletions rust/ql/lib/codeql/rust/AstConsistency.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* Provides classes for recognizing control flow graph inconsistencies.
*/

private import rust
private import codeql.rust.elements.internal.generated.ParentChild

/**
* Holds if `e` has more than one `toString()` result.
*/
query predicate multipleToStrings(Element e, string s) {
s = strictconcat(e.toString(), ", ") and
strictcount(e.toString()) > 1
}

/**
* Holds if `e` has more than one `Location`.
*/
query predicate multipleLocations(Locatable e) { strictcount(e.getLocation()) > 1 }

/**
* Holds if `e` has more than one `getPrimaryQlClasses()` result.
*/
query predicate multiplePrimaryQlClasses(Element e, string s) {
s = strictconcat(e.getPrimaryQlClasses(), ", ") and
strictcount(e.getAPrimaryQlClass()) > 1
}

private Element getParent(Element child) { child = getChildAndAccessor(result, _, _) }

/**
* Holds if `child` has more than one AST parent.
*/
query predicate multipleParents(Element child, Element parent) {
parent = getParent(child) and
strictcount(getParent(child)) > 1
}

/**
* Gets counts of abstract syntax tree inconsistencies of each type.
*/
int getAstInconsistencyCounts(string type) {
// total results from all the AST consistency query predicates.
type = "Multiple toStrings" and
result = count(Element e | multipleToStrings(e, _) | e)
or
type = "Multiple locations" and
result = count(Element e | multipleLocations(e) | e)
or
type = "Multiple primary QL classes" and
result = count(Element e | multiplePrimaryQlClasses(e, _) | e)
or
type = "Multiple parents" and
result = count(Element e | multipleParents(e, _) | e)
}
15 changes: 15 additions & 0 deletions rust/ql/src/queries/diagnostics/AstConsistencyCounts.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* @name Abstract syntax tree inconsistency counts
* @description Counts the number of abstract syntax tree inconsistencies of each type. This query is intended for internal use.
* @kind diagnostic
* @id rust/diagnostics/ast-consistency-counts
*/

import rust
import codeql.rust.AstConsistency as Consistency

// see also `rust/diagnostics/ast-consistency`, which lists the
// individual inconsistency results.
from string type, int num
where num = Consistency::getAstInconsistencyCounts(type)
select type, num
8 changes: 8 additions & 0 deletions rust/ql/src/queries/summary/Stats.qll
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*/

import rust
import codeql.rust.AstConsistency as AstConsistency
private import codeql.rust.controlflow.internal.CfgConsistency as CfgConsistency

/**
Expand All @@ -17,6 +18,13 @@ int getLinesOfUserCode() {
result = sum(File f | exists(f.getRelativePath()) | f.getNumberOfLinesOfCode())
}

/**
* Gets a count of the total number of abstract syntax tree inconsistencies in the database.
*/
int getTotalAstInconsistencies() {
result = sum(string type | | AstConsistency::getAstInconsistencyCounts(type))
}

/**
* Gets a count of the total number of control flow graph inconsistencies in the database.
*/
Expand Down
28 changes: 14 additions & 14 deletions rust/ql/src/queries/summary/SummaryStats.ql
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* @name Summary Statistics
* @description A table of summary statistics about a database.
* @kind table
* @kind metric
* @id rust/summary/summary-statistics
* @tags summary
*/
Expand All @@ -10,29 +10,29 @@ import rust
import codeql.rust.Diagnostics
import Stats

from string key, string value
from string key, int value
where
key = "Elements extracted" and value = count(Element e | not e instanceof Unextracted).toString()
key = "Elements extracted" and value = count(Element e | not e instanceof Unextracted)
or
key = "Elements unextracted" and value = count(Unextracted e).toString()
key = "Elements unextracted" and value = count(Unextracted e)
or
key = "Extraction errors" and value = count(ExtractionError e).toString()
key = "Extraction errors" and value = count(ExtractionError e)
or
key = "Extraction warnings" and value = count(ExtractionWarning w).toString()
key = "Extraction warnings" and value = count(ExtractionWarning w)
or
key = "Files extracted - total" and value = count(File f | exists(f.getRelativePath())).toString()
key = "Files extracted - total" and value = count(File f | exists(f.getRelativePath()))
or
key = "Files extracted - with errors" and
value =
count(File f | exists(f.getRelativePath()) and not f instanceof SuccessfullyExtractedFile)
.toString()
value = count(File f | exists(f.getRelativePath()) and not f instanceof SuccessfullyExtractedFile)
or
key = "Files extracted - without errors" and
value = count(SuccessfullyExtractedFile f | exists(f.getRelativePath())).toString()
value = count(SuccessfullyExtractedFile f | exists(f.getRelativePath()))
or
key = "Lines of code extracted" and value = getLinesOfCode().toString()
key = "Lines of code extracted" and value = getLinesOfCode()
or
key = "Lines of user code extracted" and value = getLinesOfUserCode().toString()
key = "Lines of user code extracted" and value = getLinesOfUserCode()
or
key = "Inconsistencies - CFG" and value = getTotalCfgInconsistencies().toString()
key = "Inconsistencies - AST" and value = getTotalAstInconsistencies()
or
key = "Inconsistencies - CFG" and value = getTotalCfgInconsistencies()
select key, value
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
| Multiple locations | 0 |
| Multiple parents | 0 |
| Multiple primary QL classes | 0 |
| Multiple toStrings | 0 |
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
queries/diagnostics/AstConsistencyCounts.ql
1 change: 1 addition & 0 deletions rust/ql/test/query-tests/diagnostics/SummaryStats.expected
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
| Files extracted - total | 7 |
| Files extracted - with errors | 2 |
| Files extracted - without errors | 5 |
| Inconsistencies - AST | 0 |
| Inconsistencies - CFG | 0 |
| Lines of code extracted | 59 |
| Lines of user code extracted | 59 |

0 comments on commit 7d62cda

Please sign in to comment.