Python: Autoformat everything using qlformat.

Will need subsequent PRs fixing up test failures (due to deprecated
methods moving around), but other than that everything should be
straight-forward.
This commit is contained in:
Taus Brock-Nannestad
2020-07-07 15:43:52 +02:00
parent 993506d781
commit f07a7bf8cf
602 changed files with 26777 additions and 26790 deletions

View File

@@ -13,80 +13,80 @@ private string relativePath(File file) { result = file.getRelativePath().replace
*/
pragma[noinline, nomagic]
private predicate tokenLocation(File file, int sl, int sc, int ec, int el, Copy copy, int index) {
file = copy.sourceFile() and
tokens(copy, index, sl, sc, ec, el)
file = copy.sourceFile() and
tokens(copy, index, sl, sc, ec, el)
}
/** A token block used for detection of duplicate and similar code. */
class Copy extends @duplication_or_similarity {
private int lastToken() { result = max(int i | tokens(this, i, _, _, _, _) | i) }
private int lastToken() { result = max(int i | tokens(this, i, _, _, _, _) | i) }
/** Gets the index of the token in this block starting at the location `loc`, if any. */
int tokenStartingAt(Location loc) {
tokenLocation(loc.getFile(), loc.getStartLine(), loc.getStartColumn(), _, _, this, result)
}
/** Gets the index of the token in this block starting at the location `loc`, if any. */
int tokenStartingAt(Location loc) {
tokenLocation(loc.getFile(), loc.getStartLine(), loc.getStartColumn(), _, _, this, result)
}
/** Gets the index of the token in this block ending at the location `loc`, if any. */
int tokenEndingAt(Location loc) {
tokenLocation(loc.getFile(), _, _, loc.getEndLine(), loc.getEndColumn(), this, result)
}
/** Gets the index of the token in this block ending at the location `loc`, if any. */
int tokenEndingAt(Location loc) {
tokenLocation(loc.getFile(), _, _, loc.getEndLine(), loc.getEndColumn(), this, result)
}
/** Gets the line on which the first token in this block starts. */
int sourceStartLine() { tokens(this, 0, result, _, _, _) }
/** Gets the line on which the first token in this block starts. */
int sourceStartLine() { tokens(this, 0, result, _, _, _) }
/** Gets the column on which the first token in this block starts. */
int sourceStartColumn() { tokens(this, 0, _, result, _, _) }
/** Gets the column on which the first token in this block starts. */
int sourceStartColumn() { tokens(this, 0, _, result, _, _) }
/** Gets the line on which the last token in this block ends. */
int sourceEndLine() { tokens(this, this.lastToken(), _, _, result, _) }
/** Gets the line on which the last token in this block ends. */
int sourceEndLine() { tokens(this, this.lastToken(), _, _, result, _) }
/** Gets the column on which the last token in this block ends. */
int sourceEndColumn() { tokens(this, this.lastToken(), _, _, _, result) }
/** Gets the column on which the last token in this block ends. */
int sourceEndColumn() { tokens(this, this.lastToken(), _, _, _, result) }
/** Gets the number of lines containing at least (part of) one token in this block. */
int sourceLines() { result = this.sourceEndLine() + 1 - this.sourceStartLine() }
/** Gets the number of lines containing at least (part of) one token in this block. */
int sourceLines() { result = this.sourceEndLine() + 1 - this.sourceStartLine() }
/** Gets an opaque identifier for the equivalence class of this block. */
int getEquivalenceClass() { duplicateCode(this, _, result) or similarCode(this, _, result) }
/** Gets an opaque identifier for the equivalence class of this block. */
int getEquivalenceClass() { duplicateCode(this, _, result) or similarCode(this, _, result) }
/** Gets the source file in which this block appears. */
File sourceFile() {
exists(string name | duplicateCode(this, name, _) or similarCode(this, name, _) |
name.replaceAll("\\", "/") = relativePath(result)
)
}
/** Gets the source file in which this block appears. */
File sourceFile() {
exists(string name | duplicateCode(this, name, _) or similarCode(this, name, _) |
name.replaceAll("\\", "/") = relativePath(result)
)
}
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
sourceFile().getAbsolutePath() = filepath and
startline = sourceStartLine() and
startcolumn = sourceStartColumn() and
endline = sourceEndLine() and
endcolumn = sourceEndColumn()
}
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
sourceFile().getAbsolutePath() = filepath and
startline = sourceStartLine() and
startcolumn = sourceStartColumn() and
endline = sourceEndLine() and
endcolumn = sourceEndColumn()
}
/** Gets a textual representation of this element. */
string toString() { result = "Copy" }
/** Gets a textual representation of this element. */
string toString() { result = "Copy" }
/**
* Gets a block that extends this one, that is, its first token is also
* covered by this block, but they are not the same block.
*/
Copy extendingBlock() {
exists(File file, int sl, int sc, int ec, int el |
tokenLocation(file, sl, sc, ec, el, this, _) and
tokenLocation(file, sl, sc, ec, el, result, 0)
) and
this != result
}
/**
* Gets a block that extends this one, that is, its first token is also
* covered by this block, but they are not the same block.
*/
Copy extendingBlock() {
exists(File file, int sl, int sc, int ec, int el |
tokenLocation(file, sl, sc, ec, el, this, _) and
tokenLocation(file, sl, sc, ec, el, result, 0)
) and
this != result
}
}
/**
@@ -96,18 +96,18 @@ class Copy extends @duplication_or_similarity {
* `start2`, and `end` the equivalence class of `end1` and `end2`.
*/
predicate similar_extension(
SimilarBlock start1, SimilarBlock start2, SimilarBlock ext1, SimilarBlock ext2, int start, int ext
SimilarBlock start1, SimilarBlock start2, SimilarBlock ext1, SimilarBlock ext2, int start, int ext
) {
start1.getEquivalenceClass() = start and
start2.getEquivalenceClass() = start and
ext1.getEquivalenceClass() = ext and
ext2.getEquivalenceClass() = ext and
start1 != start2 and
(
ext1 = start1 and ext2 = start2
or
similar_extension(start1.extendingBlock(), start2.extendingBlock(), ext1, ext2, _, ext)
)
start1.getEquivalenceClass() = start and
start2.getEquivalenceClass() = start and
ext1.getEquivalenceClass() = ext and
ext2.getEquivalenceClass() = ext and
start1 != start2 and
(
ext1 = start1 and ext2 = start2
or
similar_extension(start1.extendingBlock(), start2.extendingBlock(), ext1, ext2, _, ext)
)
}
/**
@@ -117,31 +117,31 @@ predicate similar_extension(
* `start2`, and `end` the equivalence class of `end1` and `end2`.
*/
predicate duplicate_extension(
DuplicateBlock start1, DuplicateBlock start2, DuplicateBlock ext1, DuplicateBlock ext2, int start,
int ext
DuplicateBlock start1, DuplicateBlock start2, DuplicateBlock ext1, DuplicateBlock ext2, int start,
int ext
) {
start1.getEquivalenceClass() = start and
start2.getEquivalenceClass() = start and
ext1.getEquivalenceClass() = ext and
ext2.getEquivalenceClass() = ext and
start1 != start2 and
(
ext1 = start1 and ext2 = start2
or
duplicate_extension(start1.extendingBlock(), start2.extendingBlock(), ext1, ext2, _, ext)
)
start1.getEquivalenceClass() = start and
start2.getEquivalenceClass() = start and
ext1.getEquivalenceClass() = ext and
ext2.getEquivalenceClass() = ext and
start1 != start2 and
(
ext1 = start1 and ext2 = start2
or
duplicate_extension(start1.extendingBlock(), start2.extendingBlock(), ext1, ext2, _, ext)
)
}
/** A block of duplicated code. */
class DuplicateBlock extends Copy, @duplication {
override string toString() { result = "Duplicate code: " + sourceLines() + " duplicated lines." }
override string toString() { result = "Duplicate code: " + sourceLines() + " duplicated lines." }
}
/** A block of similar code. */
class SimilarBlock extends Copy, @similarity {
override string toString() {
result = "Similar code: " + sourceLines() + " almost duplicated lines."
}
override string toString() {
result = "Similar code: " + sourceLines() + " almost duplicated lines."
}
}
/**
@@ -149,14 +149,14 @@ class SimilarBlock extends Copy, @similarity {
* respectively, where `scope1` and `scope2` are not the same.
*/
predicate duplicateStatement(Scope scope1, Scope scope2, Stmt stmt1, Stmt stmt2) {
exists(int equivstart, int equivend, int first, int last |
scope1.contains(stmt1) and
scope2.contains(stmt2) and
duplicateCoversStatement(equivstart, equivend, first, last, stmt1) and
duplicateCoversStatement(equivstart, equivend, first, last, stmt2) and
stmt1 != stmt2 and
scope1 != scope2
)
exists(int equivstart, int equivend, int first, int last |
scope1.contains(stmt1) and
scope2.contains(stmt2) and
duplicateCoversStatement(equivstart, equivend, first, last, stmt1) and
duplicateCoversStatement(equivstart, equivend, first, last, stmt2) and
stmt1 != stmt2 and
scope1 != scope2
)
}
/**
@@ -167,17 +167,17 @@ predicate duplicateStatement(Scope scope1, Scope scope2, Stmt stmt1, Stmt stmt2)
* block, respectively.
*/
private predicate duplicateCoversStatement(
int equivstart, int equivend, int first, int last, Stmt stmt
int equivstart, int equivend, int first, int last, Stmt stmt
) {
exists(DuplicateBlock b1, DuplicateBlock b2, Location startloc, Location endloc |
stmt.getLocation() = startloc and
stmt.getLastStatement().getLocation() = endloc and
first = b1.tokenStartingAt(startloc) and
last = b2.tokenEndingAt(endloc) and
b1.getEquivalenceClass() = equivstart and
b2.getEquivalenceClass() = equivend and
duplicate_extension(b1, _, b2, _, equivstart, equivend)
)
exists(DuplicateBlock b1, DuplicateBlock b2, Location startloc, Location endloc |
stmt.getLocation() = startloc and
stmt.getLastStatement().getLocation() = endloc and
first = b1.tokenStartingAt(startloc) and
last = b2.tokenEndingAt(endloc) and
b1.getEquivalenceClass() = equivstart and
b2.getEquivalenceClass() = equivend and
duplicate_extension(b1, _, b2, _, equivstart, equivend)
)
}
/**
@@ -185,23 +185,23 @@ private predicate duplicateCoversStatement(
* toplevel that has `duplicate` lines in common with `scope1`.
*/
predicate duplicateStatements(Scope scope1, Scope scope2, int duplicate, int total) {
duplicate = strictcount(Stmt stmt | duplicateStatement(scope1, scope2, stmt, _)) and
total = strictcount(Stmt stmt | scope1.contains(stmt))
duplicate = strictcount(Stmt stmt | duplicateStatement(scope1, scope2, stmt, _)) and
total = strictcount(Stmt stmt | scope1.contains(stmt))
}
/**
* Find pairs of scopes that are identical or almost identical
*/
predicate duplicateScopes(Scope s, Scope other, float percent, string message) {
exists(int total, int duplicate | duplicateStatements(s, other, duplicate, total) |
percent = 100.0 * duplicate / total and
percent >= 80.0 and
if duplicate = total
then message = "All " + total + " statements in " + s.getName() + " are identical in $@."
else
message =
duplicate + " out of " + total + " statements in " + s.getName() + " are duplicated in $@."
)
exists(int total, int duplicate | duplicateStatements(s, other, duplicate, total) |
percent = 100.0 * duplicate / total and
percent >= 80.0 and
if duplicate = total
then message = "All " + total + " statements in " + s.getName() + " are identical in $@."
else
message =
duplicate + " out of " + total + " statements in " + s.getName() + " are duplicated in $@."
)
}
/**
@@ -209,14 +209,14 @@ predicate duplicateScopes(Scope s, Scope other, float percent, string message) {
* respectively, where `scope1` and `scope2` are not the same.
*/
private predicate similarStatement(Scope scope1, Scope scope2, Stmt stmt1, Stmt stmt2) {
exists(int start, int end, int first, int last |
scope1.contains(stmt1) and
scope2.contains(stmt2) and
similarCoversStatement(start, end, first, last, stmt1) and
similarCoversStatement(start, end, first, last, stmt2) and
stmt1 != stmt2 and
scope1 != scope2
)
exists(int start, int end, int first, int last |
scope1.contains(stmt1) and
scope2.contains(stmt2) and
similarCoversStatement(start, end, first, last, stmt1) and
similarCoversStatement(start, end, first, last, stmt2) and
stmt1 != stmt2 and
scope1 != scope2
)
}
/**
@@ -227,17 +227,17 @@ private predicate similarStatement(Scope scope1, Scope scope2, Stmt stmt1, Stmt
* block, respectively.
*/
private predicate similarCoversStatement(
int equivstart, int equivend, int first, int last, Stmt stmt
int equivstart, int equivend, int first, int last, Stmt stmt
) {
exists(SimilarBlock b1, SimilarBlock b2, Location startloc, Location endloc |
stmt.getLocation() = startloc and
stmt.getLastStatement().getLocation() = endloc and
first = b1.tokenStartingAt(startloc) and
last = b2.tokenEndingAt(endloc) and
b1.getEquivalenceClass() = equivstart and
b2.getEquivalenceClass() = equivend and
similar_extension(b1, _, b2, _, equivstart, equivend)
)
exists(SimilarBlock b1, SimilarBlock b2, Location startloc, Location endloc |
stmt.getLocation() = startloc and
stmt.getLastStatement().getLocation() = endloc and
first = b1.tokenStartingAt(startloc) and
last = b2.tokenEndingAt(endloc) and
b1.getEquivalenceClass() = equivstart and
b2.getEquivalenceClass() = equivend and
similar_extension(b1, _, b2, _, equivstart, equivend)
)
}
/**
@@ -245,23 +245,23 @@ private predicate similarCoversStatement(
* toplevel that has `similar` similar lines to `scope1`.
*/
private predicate similarStatements(Scope scope1, Scope scope2, int similar, int total) {
similar = strictcount(Stmt stmt | similarStatement(scope1, scope2, stmt, _)) and
total = strictcount(Stmt stmt | scope1.contains(stmt))
similar = strictcount(Stmt stmt | similarStatement(scope1, scope2, stmt, _)) and
total = strictcount(Stmt stmt | scope1.contains(stmt))
}
/**
* Find pairs of scopes that are similar
*/
predicate similarScopes(Scope s, Scope other, float percent, string message) {
exists(int total, int similar | similarStatements(s, other, similar, total) |
percent = 100.0 * similar / total and
percent >= 80.0 and
if similar = total
then message = "All statements in " + s.getName() + " are similar in $@."
else
message =
similar + " out of " + total + " statements in " + s.getName() + " are similar in $@."
)
exists(int total, int similar | similarStatements(s, other, similar, total) |
percent = 100.0 * similar / total and
percent >= 80.0 and
if similar = total
then message = "All statements in " + s.getName() + " are similar in $@."
else
message =
similar + " out of " + total + " statements in " + s.getName() + " are similar in $@."
)
}
/**
@@ -269,5 +269,5 @@ predicate similarScopes(Scope s, Scope other, float percent, string message) {
* This is true for blocks of import statements.
*/
predicate allowlistedLineForDuplication(File f, int line) {
exists(ImportingStmt i | i.getLocation().getFile() = f and i.getLocation().getStartLine() = line)
exists(ImportingStmt i | i.getLocation().getFile() = f and i.getLocation().getStartLine() = line)
}

View File

@@ -11,71 +11,71 @@ import semmle.python.Files
* For more information, see [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
*/
external predicate defectResults(
int id, string queryPath, string filepath, int startline, int startcol, int endline, int endcol,
string message
int id, string queryPath, string filepath, int startline, int startcol, int endline, int endcol,
string message
);
/**
* A defect query result stored in a dashboard database.
*/
class DefectResult extends int {
DefectResult() { defectResults(this, _, _, _, _, _, _, _) }
DefectResult() { defectResults(this, _, _, _, _, _, _, _) }
/** Gets the path of the query that reported the result. */
string getQueryPath() { defectResults(this, result, _, _, _, _, _, _) }
/** Gets the path of the query that reported the result. */
string getQueryPath() { defectResults(this, result, _, _, _, _, _, _) }
/** Gets the file in which this query result was reported. */
File getFile() {
exists(string path |
defectResults(this, _, path, _, _, _, _, _) and result.getAbsolutePath() = path
)
}
/** Gets the file in which this query result was reported. */
File getFile() {
exists(string path |
defectResults(this, _, path, _, _, _, _, _) and result.getAbsolutePath() = path
)
}
/** Gets the file path in which this query result was reported. */
string getFilePath() { defectResults(this, _, result, _, _, _, _, _) }
/** Gets the file path in which this query result was reported. */
string getFilePath() { defectResults(this, _, result, _, _, _, _, _) }
/** Gets the line on which the location of this query result starts. */
int getStartLine() { defectResults(this, _, _, result, _, _, _, _) }
/** Gets the line on which the location of this query result starts. */
int getStartLine() { defectResults(this, _, _, result, _, _, _, _) }
/** Gets the column on which the location of this query result starts. */
int getStartColumn() { defectResults(this, _, _, _, result, _, _, _) }
/** Gets the column on which the location of this query result starts. */
int getStartColumn() { defectResults(this, _, _, _, result, _, _, _) }
/** Gets the line on which the location of this query result ends. */
int getEndLine() { defectResults(this, _, _, _, _, result, _, _) }
/** Gets the line on which the location of this query result ends. */
int getEndLine() { defectResults(this, _, _, _, _, result, _, _) }
/** Gets the column on which the location of this query result ends. */
int getEndColumn() { defectResults(this, _, _, _, _, _, result, _) }
/** Gets the column on which the location of this query result ends. */
int getEndColumn() { defectResults(this, _, _, _, _, _, result, _) }
/** Gets the message associated with this query result. */
string getMessage() { defectResults(this, _, _, _, _, _, _, result) }
/** Gets the message associated with this query result. */
string getMessage() { defectResults(this, _, _, _, _, _, _, result) }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
defectResults(this, _, filepath, startline, startcolumn, endline, endcolumn, _)
}
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
defectResults(this, _, filepath, startline, startcolumn, endline, endcolumn, _)
}
/** Gets the URL corresponding to the location of this query result. */
string getURL() {
result =
"file://" + getFile().getAbsolutePath() + ":" + getStartLine() + ":" + getStartColumn() + ":" +
getEndLine() + ":" + getEndColumn()
}
/** Gets the URL corresponding to the location of this query result. */
string getURL() {
result =
"file://" + getFile().getAbsolutePath() + ":" + getStartLine() + ":" + getStartColumn() + ":" +
getEndLine() + ":" + getEndColumn()
}
}
// crude containment by line number only
predicate contains(Location l, DefectResult res) {
exists(string path, int bl1, int el1, int bl2, int el2 |
l.hasLocationInfo(path, bl1, _, el1, _) and
res.hasLocationInfo(path, bl2, _, el2, _) and
bl1 <= bl2 and
el1 >= el2
)
exists(string path, int bl1, int el1, int bl2, int el2 |
l.hasLocationInfo(path, bl1, _, el1, _) and
res.hasLocationInfo(path, bl2, _, el2, _) and
bl1 <= bl2 and
el1 >= el2
)
}

View File

@@ -19,16 +19,16 @@ import python
import CodeDuplication
predicate sorted_by_location(DuplicateBlock x, DuplicateBlock y) {
if x.sourceFile() = y.sourceFile()
then x.sourceStartLine() < y.sourceStartLine()
else x.sourceFile().getAbsolutePath() < y.sourceFile().getAbsolutePath()
if x.sourceFile() = y.sourceFile()
then x.sourceStartLine() < y.sourceStartLine()
else x.sourceFile().getAbsolutePath() < y.sourceFile().getAbsolutePath()
}
from DuplicateBlock d, DuplicateBlock other
where
d.sourceLines() > 10 and
other.getEquivalenceClass() = d.getEquivalenceClass() and
sorted_by_location(other, d)
d.sourceLines() > 10 and
other.getEquivalenceClass() = d.getEquivalenceClass() and
sorted_by_location(other, d)
select d,
"Duplicate code: " + d.sourceLines() + " lines are duplicated at " +
other.sourceFile().getShortName() + ":" + other.sourceStartLine().toString()
"Duplicate code: " + d.sourceLines() + " lines are duplicated at " +
other.sourceFile().getShortName() + ":" + other.sourceStartLine().toString()

View File

@@ -21,9 +21,9 @@ predicate relevant(Function m) { m.getMetrics().getNumberOfLinesOfCode() > 5 }
from Function m, Function other, string message, int percent
where
duplicateScopes(m, other, percent, message) and
relevant(m) and
percent > 95.0 and
not duplicateScopes(m.getEnclosingModule(), other.getEnclosingModule(), _, _) and
not duplicateScopes(m.getScope(), other.getScope(), _, _)
duplicateScopes(m, other, percent, message) and
relevant(m) and
percent > 95.0 and
not duplicateScopes(m.getEnclosingModule(), other.getEnclosingModule(), _, _) and
not duplicateScopes(m.getScope(), other.getScope(), _, _)
select m, message, other, other.getName()

View File

@@ -5,83 +5,83 @@
import python
class ExternalDefect extends @externalDefect {
string getQueryPath() {
exists(string path |
externalDefects(this, path, _, _, _) and
result = path.replaceAll("\\", "/")
)
}
string getQueryPath() {
exists(string path |
externalDefects(this, path, _, _, _) and
result = path.replaceAll("\\", "/")
)
}
string getMessage() { externalDefects(this, _, _, result, _) }
string getMessage() { externalDefects(this, _, _, result, _) }
float getSeverity() { externalDefects(this, _, _, _, result) }
float getSeverity() { externalDefects(this, _, _, _, result) }
Location getLocation() { externalDefects(this, _, result, _, _) }
Location getLocation() { externalDefects(this, _, result, _, _) }
/** Gets a textual representation of this element. */
string toString() { result = getQueryPath() + ": " + getLocation() + " - " + getMessage() }
/** Gets a textual representation of this element. */
string toString() { result = getQueryPath() + ": " + getLocation() + " - " + getMessage() }
}
class ExternalMetric extends @externalMetric {
string getQueryPath() { externalMetrics(this, result, _, _) }
string getQueryPath() { externalMetrics(this, result, _, _) }
float getValue() { externalMetrics(this, _, _, result) }
float getValue() { externalMetrics(this, _, _, result) }
Location getLocation() { externalMetrics(this, _, result, _) }
Location getLocation() { externalMetrics(this, _, result, _) }
/** Gets a textual representation of this element. */
string toString() { result = getQueryPath() + ": " + getLocation() + " - " + getValue() }
/** Gets a textual representation of this element. */
string toString() { result = getQueryPath() + ": " + getLocation() + " - " + getValue() }
}
/**
* An external data item.
*/
class ExternalData extends @externalDataElement {
/** Gets the path of the file this data was loaded from. */
string getDataPath() { externalData(this, result, _, _) }
/** Gets the path of the file this data was loaded from. */
string getDataPath() { externalData(this, result, _, _) }
/**
* Gets the path of the file this data was loaded from, with its
* extension replaced by `.ql`.
*/
string getQueryPath() { result = getDataPath().regexpReplaceAll("\\.[^.]*$", ".ql") }
/**
* Gets the path of the file this data was loaded from, with its
* extension replaced by `.ql`.
*/
string getQueryPath() { result = getDataPath().regexpReplaceAll("\\.[^.]*$", ".ql") }
/** Gets the number of fields in this data item. */
int getNumFields() { result = 1 + max(int i | externalData(this, _, i, _) | i) }
/** Gets the number of fields in this data item. */
int getNumFields() { result = 1 + max(int i | externalData(this, _, i, _) | i) }
/** Gets the value of the field at position `index` of this data item. */
string getField(int index) { externalData(this, _, index, result) }
/** Gets the value of the field at position `index` of this data item. */
string getField(int index) { externalData(this, _, index, result) }
/** Gets the integer value of the field at position `index` of this data item. */
int getFieldAsInt(int index) { result = getField(index).toInt() }
/** Gets the integer value of the field at position `index` of this data item. */
int getFieldAsInt(int index) { result = getField(index).toInt() }
/** Gets the floating-point value of the field at position `index` of this data item. */
float getFieldAsFloat(int index) { result = getField(index).toFloat() }
/** Gets the floating-point value of the field at position `index` of this data item. */
float getFieldAsFloat(int index) { result = getField(index).toFloat() }
/** Gets the value of the field at position `index` of this data item, interpreted as a date. */
date getFieldAsDate(int index) { result = getField(index).toDate() }
/** Gets the value of the field at position `index` of this data item, interpreted as a date. */
date getFieldAsDate(int index) { result = getField(index).toDate() }
/** Gets a textual representation of this data item. */
string toString() { result = getQueryPath() + ": " + buildTupleString(0) }
/** Gets a textual representation of this data item. */
string toString() { result = getQueryPath() + ": " + buildTupleString(0) }
/** Gets a textual representation of this data item, starting with the field at position `start`. */
private string buildTupleString(int start) {
start = getNumFields() - 1 and result = getField(start)
or
start < getNumFields() - 1 and result = getField(start) + "," + buildTupleString(start + 1)
}
/** Gets a textual representation of this data item, starting with the field at position `start`. */
private string buildTupleString(int start) {
start = getNumFields() - 1 and result = getField(start)
or
start < getNumFields() - 1 and result = getField(start) + "," + buildTupleString(start + 1)
}
}
/**
* External data with a location, and a message, as produced by tools that used to produce QLDs.
*/
class DefectExternalData extends ExternalData {
DefectExternalData() {
this.getField(0).regexpMatch("\\w+://.*:[0-9]+:[0-9]+:[0-9]+:[0-9]+$") and
this.getNumFields() = 2
}
DefectExternalData() {
this.getField(0).regexpMatch("\\w+://.*:[0-9]+:[0-9]+:[0-9]+:[0-9]+$") and
this.getNumFields() = 2
}
string getURL() { result = getField(0) }
string getURL() { result = getField(0) }
string getMessage() { result = getField(1) }
string getMessage() { result = getField(1) }
}

View File

@@ -19,7 +19,7 @@ import CodeDuplication
from Class c, Class other, string message
where
duplicateScopes(c, other, _, message) and
count(c.getAStmt()) > 3 and
not duplicateScopes(c.getEnclosingModule(), _, _, _)
duplicateScopes(c, other, _, message) and
count(c.getAStmt()) > 3 and
not duplicateScopes(c.getEnclosingModule(), _, _, _)
select c, message, other, other.getName()

View File

@@ -21,10 +21,10 @@ predicate relevant(Function m) { m.getMetrics().getNumberOfLinesOfCode() > 10 }
from Function m, Function other, string message, int percent
where
similarScopes(m, other, percent, message) and
relevant(m) and
percent > 95.0 and
not duplicateScopes(m, other, _, _) and
not duplicateScopes(m.getEnclosingModule(), other.getEnclosingModule(), _, _) and
not duplicateScopes(m.getScope(), other.getScope(), _, _)
similarScopes(m, other, percent, message) and
relevant(m) and
percent > 95.0 and
not duplicateScopes(m, other, _, _) and
not duplicateScopes(m.getEnclosingModule(), other.getEnclosingModule(), _, _) and
not duplicateScopes(m.getScope(), other.getScope(), _, _)
select m, message, other, other.getName()

View File

@@ -7,197 +7,201 @@ import external.ExternalArtifact
/** An item in the parse tree of the IDL file */
class ThriftElement extends ExternalData {
string kind;
string kind;
ThriftElement() { this.getDataPath() = "thrift-" + kind }
ThriftElement() { this.getDataPath() = "thrift-" + kind }
string getKind() { result = kind }
string getKind() { result = kind }
string getId() { result = getField(0) }
string getId() { result = getField(0) }
int getIndex() { result = getFieldAsInt(1) }
int getIndex() { result = getFieldAsInt(1) }
ThriftElement getParent() { result.getId() = this.getField(2) }
ThriftElement getParent() { result.getId() = this.getField(2) }
string getValue() { result = this.getField(3) }
string getValue() { result = this.getField(3) }
ThriftElement getChild(int n) { result.getIndex() = n and result.getParent() = this }
ThriftElement getChild(int n) { result.getIndex() = n and result.getParent() = this }
ThriftElement getAChild() { result = this.getChild(_) }
ThriftElement getAChild() { result = this.getChild(_) }
override string toString() { result = this.getKind() }
override string toString() { result = this.getKind() }
string getPath() { result = this.getField(4) }
string getPath() { result = this.getField(4) }
private int line() { result = this.getFieldAsInt(5) }
private int line() { result = this.getFieldAsInt(5) }
private int column() { result = this.getFieldAsInt(6) }
private int column() { result = this.getFieldAsInt(6) }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
filepath = this.getPath() and
startline = this.line() and
startcolumn = this.column() and
endline = this.line() and
endcolumn = this.column() + this.getValue().length() - 1
or
exists(ThriftElement first, ThriftElement last |
first = this.getChild(min(int l | exists(this.getChild(l)))) and
last = this.getChild(max(int l | exists(this.getChild(l)))) and
first.hasLocationInfo(filepath, startline, startcolumn, _, _) and
last.hasLocationInfo(filepath, _, _, endline, endcolumn)
)
}
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
filepath = this.getPath() and
startline = this.line() and
startcolumn = this.column() and
endline = this.line() and
endcolumn = this.column() + this.getValue().length() - 1
or
exists(ThriftElement first, ThriftElement last |
first = this.getChild(min(int l | exists(this.getChild(l)))) and
last = this.getChild(max(int l | exists(this.getChild(l)))) and
first.hasLocationInfo(filepath, startline, startcolumn, _, _) and
last.hasLocationInfo(filepath, _, _, endline, endcolumn)
)
}
File getFile() { this.hasLocationInfo(result.getAbsolutePath(), _, _, _, _) }
File getFile() { this.hasLocationInfo(result.getAbsolutePath(), _, _, _, _) }
}
abstract class ThriftNamedElement extends ThriftElement {
abstract ThriftElement getNameElement();
abstract ThriftElement getNameElement();
final string getName() { result = this.getNameElement().getValue() }
final string getName() { result = this.getNameElement().getValue() }
override string toString() {
result = this.getKind() + " " + this.getName()
or
not exists(this.getName()) and result = this.getKind() + " ???"
}
override string toString() {
result = this.getKind() + " " + this.getName()
or
not exists(this.getName()) and result = this.getKind() + " ???"
}
override predicate hasLocationInfo(string filepath, int startline, int startcolumn, int endline, int endcolumn) {
exists(ThriftElement first |
first = this.getChild(min(int l | exists(this.getChild(l)))) and
first.hasLocationInfo(filepath, startline, startcolumn, _, _) and
this.getNameElement().hasLocationInfo(filepath, _, _, endline, endcolumn)
)
}
override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
exists(ThriftElement first |
first = this.getChild(min(int l | exists(this.getChild(l)))) and
first.hasLocationInfo(filepath, startline, startcolumn, _, _) and
this.getNameElement().hasLocationInfo(filepath, _, _, endline, endcolumn)
)
}
}
class ThriftType extends ThriftNamedElement {
ThriftType() { kind.matches("%type") }
ThriftType() { kind.matches("%type") }
override ThriftElement getNameElement() {
result = this.getChild(0)
or
result = this.getChild(0).(ThriftType).getNameElement()
}
override ThriftElement getNameElement() {
result = this.getChild(0)
or
result = this.getChild(0).(ThriftType).getNameElement()
}
override string toString() { result = "type " + this.getName() }
override string toString() { result = "type " + this.getName() }
predicate references(ThriftStruct struct) {
this.getName() = struct.getName() and
exists(string path |
this.hasLocationInfo(path, _, _, _, _) and
struct.hasLocationInfo(path, _, _, _, _)
)
}
predicate references(ThriftStruct struct) {
this.getName() = struct.getName() and
exists(string path |
this.hasLocationInfo(path, _, _, _, _) and
struct.hasLocationInfo(path, _, _, _, _)
)
}
}
/** A thrift typedef */
class ThriftTypeDef extends ThriftNamedElement {
ThriftTypeDef() { kind.matches("typedef") }
ThriftTypeDef() { kind.matches("typedef") }
override ThriftElement getNameElement() { result = this.getChild(2).getChild(0) }
override ThriftElement getNameElement() { result = this.getChild(2).getChild(0) }
}
/** A thrift enum declaration */
class ThriftEnum extends ThriftNamedElement {
ThriftEnum() { kind.matches("enum") }
ThriftEnum() { kind.matches("enum") }
override ThriftElement getNameElement() { result = this.getChild(0).getChild(0) }
override ThriftElement getNameElement() { result = this.getChild(0).getChild(0) }
}
/** A thrift enum field */
class ThriftEnumField extends ThriftNamedElement {
ThriftEnumField() { kind.matches("enumfield") }
ThriftEnumField() { kind.matches("enumfield") }
override ThriftElement getNameElement() { result = this.getChild(0).getChild(0) }
override ThriftElement getNameElement() { result = this.getChild(0).getChild(0) }
}
/** A thrift service declaration */
class ThriftService extends ThriftNamedElement {
ThriftService() { kind.matches("service") }
ThriftService() { kind.matches("service") }
override ThriftElement getNameElement() { result = this.getChild(0).getChild(0) }
override ThriftElement getNameElement() { result = this.getChild(0).getChild(0) }
ThriftFunction getAFunction() { result = this.getChild(_) }
ThriftFunction getAFunction() { result = this.getChild(_) }
ThriftFunction getFunction(string name) {
result.getName() = name and
result = this.getAFunction()
}
ThriftFunction getFunction(string name) {
result.getName() = name and
result = this.getAFunction()
}
}
/** A thrift function declaration */
class ThriftFunction extends ThriftNamedElement {
ThriftFunction() { kind.matches("function") }
ThriftFunction() { kind.matches("function") }
override ThriftElement getNameElement() { result = this.getChild(2).getChild(0) }
override ThriftElement getNameElement() { result = this.getChild(2).getChild(0) }
ThriftField getArgument(int n) { result = this.getChild(n + 3) }
ThriftField getArgument(int n) { result = this.getChild(n + 3) }
ThriftField getAnArgument() { result = this.getArgument(_) }
ThriftField getAnArgument() { result = this.getArgument(_) }
private ThriftThrows getAllThrows() { result = this.getChild(_) }
private ThriftThrows getAllThrows() { result = this.getChild(_) }
ThriftField getAThrows() { result = this.getAllThrows().getAChild() }
ThriftField getAThrows() { result = this.getAllThrows().getAChild() }
ThriftType getReturnType() { result = this.getChild(1).getChild(0) }
ThriftType getReturnType() { result = this.getChild(1).getChild(0) }
override predicate hasLocationInfo(string filepath, int startline, int startcolumn, int endline, int endcolumn) {
this.getChild(1).hasLocationInfo(filepath, startline, startcolumn, _, _) and
this.getChild(2).hasLocationInfo(filepath, _, _, endline, endcolumn)
}
override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.getChild(1).hasLocationInfo(filepath, startline, startcolumn, _, _) and
this.getChild(2).hasLocationInfo(filepath, _, _, endline, endcolumn)
}
ThriftService getService() { result.getAFunction() = this }
ThriftService getService() { result.getAFunction() = this }
string getQualifiedName() { result = this.getService().getName() + "." + this.getName() }
string getQualifiedName() { result = this.getService().getName() + "." + this.getName() }
}
class ThriftField extends ThriftNamedElement {
ThriftField() { kind.matches("field") }
ThriftField() { kind.matches("field") }
override ThriftElement getNameElement() { result = this.getChild(4) }
override ThriftElement getNameElement() { result = this.getChild(4) }
ThriftType getType() { result = this.getChild(2) }
ThriftType getType() { result = this.getChild(2) }
}
class ThriftStruct extends ThriftNamedElement {
ThriftStruct() { kind.matches("struct") }
ThriftStruct() { kind.matches("struct") }
override ThriftElement getNameElement() { result = this.getChild(0).getChild(0) }
override ThriftElement getNameElement() { result = this.getChild(0).getChild(0) }
ThriftField getMember(int n) { result = this.getChild(n + 1) }
ThriftField getMember(int n) { result = this.getChild(n + 1) }
ThriftField getAMember() { result = this.getMember(_) }
ThriftField getAMember() { result = this.getMember(_) }
}
class ThriftException extends ThriftNamedElement {
ThriftException() { kind.matches("exception") }
ThriftException() { kind.matches("exception") }
override ThriftElement getNameElement() { result = this.getChild(0).getChild(0) }
override ThriftElement getNameElement() { result = this.getChild(0).getChild(0) }
ThriftField getMember(int n) { result = this.getChild(n + 1) }
ThriftField getMember(int n) { result = this.getChild(n + 1) }
ThriftField getAMember() { result = this.getMember(_) }
ThriftField getAMember() { result = this.getMember(_) }
}
class ThriftThrows extends ThriftElement {
ThriftThrows() { kind.matches("throws") }
ThriftThrows() { kind.matches("throws") }
ThriftField getAThrows() { result = this.getChild(_) }
ThriftField getAThrows() { result = this.getChild(_) }
}
/** A parse tree element that holds a primitive value */
class ThriftValue extends ThriftElement {
ThriftValue() { exists(this.getValue()) }
ThriftValue() { exists(this.getValue()) }
override string toString() { result = this.getKind() + " " + this.getValue() }
override string toString() { result = this.getKind() + " " + this.getValue() }
}

View File

@@ -1,77 +1,79 @@
import python
class Commit extends @svnentry {
Commit() {
svnaffectedfiles(this, _, _) and
exists(date svnDate, date snapshotDate |
svnentries(this, _, _, svnDate, _) and
snapshotDate(snapshotDate) and
svnDate <= snapshotDate
)
}
Commit() {
svnaffectedfiles(this, _, _) and
exists(date svnDate, date snapshotDate |
svnentries(this, _, _, svnDate, _) and
snapshotDate(snapshotDate) and
svnDate <= snapshotDate
)
}
/** Gets a textual representation of this element. */
string toString() { result = this.getRevisionName() }
/** Gets a textual representation of this element. */
string toString() { result = this.getRevisionName() }
string getRevisionName() { svnentries(this, result, _, _, _) }
string getRevisionName() { svnentries(this, result, _, _, _) }
string getAuthor() { svnentries(this, _, result, _, _) }
string getAuthor() { svnentries(this, _, result, _, _) }
date getDate() { svnentries(this, _, _, result, _) }
date getDate() { svnentries(this, _, _, result, _) }
int getChangeSize() { svnentries(this, _, _, _, result) }
int getChangeSize() { svnentries(this, _, _, _, result) }
string getMessage() { svnentrymsg(this, result) }
string getMessage() { svnentrymsg(this, result) }
string getAnAffectedFilePath(string action) {
exists(File rawFile | svnaffectedfiles(this, rawFile, action) | result = rawFile.getAbsolutePath())
}
string getAnAffectedFilePath(string action) {
exists(File rawFile | svnaffectedfiles(this, rawFile, action) |
result = rawFile.getAbsolutePath()
)
}
string getAnAffectedFilePath() { result = getAnAffectedFilePath(_) }
string getAnAffectedFilePath() { result = getAnAffectedFilePath(_) }
File getAnAffectedFile(string action) { svnaffectedfiles(this, result, action) }
File getAnAffectedFile(string action) { svnaffectedfiles(this, result, action) }
File getAnAffectedFile() { exists(string action | result = this.getAnAffectedFile(action)) }
File getAnAffectedFile() { exists(string action | result = this.getAnAffectedFile(action)) }
predicate isRecent() { recentCommit(this) }
predicate isRecent() { recentCommit(this) }
int daysToNow() {
exists(date now | snapshotDate(now) | result = getDate().daysTo(now) and result >= 0)
}
int daysToNow() {
exists(date now | snapshotDate(now) | result = getDate().daysTo(now) and result >= 0)
}
int getRecentAdditionsForFile(File f) { svnchurn(this, f, result, _) }
int getRecentAdditionsForFile(File f) { svnchurn(this, f, result, _) }
int getRecentDeletionsForFile(File f) { svnchurn(this, f, _, result) }
int getRecentDeletionsForFile(File f) { svnchurn(this, f, _, result) }
int getRecentChurnForFile(File f) {
result = getRecentAdditionsForFile(f) + getRecentDeletionsForFile(f)
}
int getRecentChurnForFile(File f) {
result = getRecentAdditionsForFile(f) + getRecentDeletionsForFile(f)
}
}
class Author extends string {
Author() { exists(Commit e | this = e.getAuthor()) }
Author() { exists(Commit e | this = e.getAuthor()) }
Commit getACommit() { result.getAuthor() = this }
Commit getACommit() { result.getAuthor() = this }
File getAnEditedFile() { result = this.getACommit().getAnAffectedFile() }
File getAnEditedFile() { result = this.getACommit().getAnAffectedFile() }
}
predicate recentCommit(Commit e) {
exists(date snapshotDate, date commitDate, int days |
snapshotDate(snapshotDate) and
e.getDate() = commitDate and
days = commitDate.daysTo(snapshotDate) and
days >= 0 and
days <= 60
)
exists(date snapshotDate, date commitDate, int days |
snapshotDate(snapshotDate) and
e.getDate() = commitDate and
days = commitDate.daysTo(snapshotDate) and
days >= 0 and
days <= 60
)
}
date firstChange(File f) {
result = min(Commit e, date toMin | f = e.getAnAffectedFile() and toMin = e.getDate() | toMin)
result = min(Commit e, date toMin | f = e.getAnAffectedFile() and toMin = e.getDate() | toMin)
}
predicate firstCommit(Commit e) {
not exists(File f | f = e.getAnAffectedFile() | firstChange(f) < e.getDate())
not exists(File f | f = e.getAnAffectedFile() | firstChange(f) < e.getDate())
}
predicate artificialChange(Commit e) { firstCommit(e) or e.getChangeSize() >= 50000 }