Merge commit '7bfed6e517cbcabfe06cf614981baee8cbde5342' into attribute

This commit is contained in:
Pavel Avgustinov 2019-08-20 14:08:57 +01:00
Родитель 127c33700c 7bfed6e517
Коммит 7176b438c4
18 изменённых файлов: 1 добавлений и 1677 удалений

Просмотреть файл

@ -15,4 +15,5 @@
targets for `Object.toString()` calls. This affects all security queries and
removes false positives that arose from paths through impossible `toString()`
calls.
* The library `VCS.qll` and all queries that imported it have been removed.

Просмотреть файл

@ -1,42 +0,0 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
This metric measures the number of lines of text that have been added, deleted
or modified in files below this location in the tree.
</p>
<p>
Code churn is known to be a good (if not the best) predictor of defects in a
code component (see e.g. [Nagappan] or [Khoshgoftaar]). The intuition is that
files, packages or projects that have experienced a disproportionately high
amount of churn for the amount of code involved may have been harder to write,
and are thus likely to contain more bugs.
</p>
</overview>
<recommendation>
<p>
It is a fact of life that some code is going to be changed more than the rest,
and little can be done to change this. However, bearing in mind code churn's
effectiveness as a defect predictor, code that has been repeatedly changed
should be subjected to vigorous testing and code review.
</p>
</recommendation>
<references>
<li>
N. Nagappan et al. <em>Change Bursts as Defect Predictors</em>. In Proceedings of the 21st IEEE International Symposium on Software Reliability Engineering, 2010.
</li>
<li>
T. M. Khoshgoftaar and R. M. Szabo. <em>Improving code churn predictions during the system test and maintenance phases</em>. In ICSM '94, 1994, pp. 58-67.
</li>
</references>
</qhelp>

Просмотреть файл

@ -1,22 +0,0 @@
/**
* @name Churned lines
* @description The number of churned lines of a file (by version control history).
* @kind treemap
* @treemap.warnOn highValues
* @metricType file
* @metricAggregate avg sum max
* @id java/vcs/churn-per-file
* @deprecated
*/
import java
import external.VCS
from File f, int n
where
n = sum(Commit entry, int churn |
churn = entry.getRecentChurnForFile(f) and not artificialChange(entry)
|
churn
)
select f, n order by n desc

Просмотреть файл

@ -1,6 +0,0 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<include src="HChurn.qhelp" />
</qhelp>

Просмотреть файл

@ -1,22 +0,0 @@
/**
* @name Added lines
* @description The number of added lines of a file (by version control history).
* @kind treemap
* @treemap.warnOn highValues
* @metricType file
* @metricAggregate avg sum max
* @id java/vcs/added-lines-per-file
* @deprecated
*/
import java
import external.VCS
from File f, int n
where
n = sum(Commit entry, int churn |
churn = entry.getRecentAdditionsForFile(f) and not artificialChange(entry)
|
churn
)
select f, n order by n desc

Просмотреть файл

@ -1,6 +0,0 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<include src="HChurn.qhelp" />
</qhelp>

Просмотреть файл

@ -1,22 +0,0 @@
/**
* @name Deleted lines
* @description The number of deleted lines of a file (by version control history).
* @kind treemap
* @treemap.warnOn highValues
* @metricType file
* @metricAggregate avg sum max
* @id java/vcs/deleted-lines-per-file
* @deprecated
*/
import java
import external.VCS
from File f, int n
where
n = sum(Commit entry, int churn |
churn = entry.getRecentDeletionsForFile(f) and not artificialChange(entry)
|
churn
)
select f, n order by n desc

Просмотреть файл

@ -1,48 +0,0 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
This metric measures the number of different authors (by examining the
version control history)
for files below this location in the tree. (This is a better version
of the metric that counts the number of different authors using Javadoc
tags.)
</p>
<p>
Files that have been changed by a large number of different authors are
by definition the product of many minds. New authors working on a file
may be less familiar with the design and implementation of the code than
the original authors, which can be a potential source of bugs. Furthermore,
code that has been worked on by many people, if not carefully maintained,
often ends up lacking conceptual integrity. For both of these reasons, any
code that has been worked on by an unusually high number of different people
merits careful inspection in code reviews.
</p>
</overview>
<recommendation>
<p>
There is clearly no way to reduce the number of authors that have worked
on a file - it is impossible to rewrite history. However, files highlighted
by this metric should be given special attention in a code review, and may
ultimately be good candidates for refactoring/rewriting by an individual,
experienced developer.
</p>
</recommendation>
<references>
<li>
F. P. Brooks Jr. <em>The Mythical Man-Month</em>, Chapter 4. Addison-Wesley, 1974.
</li>
</references>
</qhelp>

Просмотреть файл

@ -1,16 +0,0 @@
/**
* @name Number of authors (version control)
* @description The number of distinct authors (by version control history) of a file.
* @kind treemap
* @treemap.warnOn highValues
* @metricType file
* @metricAggregate avg min max
* @id java/vcs/authors-per-file
* @deprecated
*/
import java
import external.VCS
from File f
select f, count(Author author | author.getAnEditedFile() = f)

Просмотреть файл

@ -1,30 +0,0 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
This metric measures the total number of file-level changes made to files
below this location in the tree. For an individual file, it measures the
number of commits that have affected that file. For a directory of files, it
measures the sum of the file-level changes for each of the files in the
directory.
</p>
<p>
For example, suppose we have a directory containing two files, A and B. If the
number of file-level changes to A is <code>100</code>, and the number of
file-level changes to B is <code>80</code>, then the total number of
file-level changes to the directory is <code>180</code>. Note that this is
likely to be different (in some cases very different) from the number of
commits that affected any file in the directory, since more than one file can
be changed by a single commit. (Note what would happen if we performed
<code>80</code> commits on A and B, followed by another <code>20</code>
commits on A alone - the total number of file-level changes would be
<code>180</code>, but the number of commits involved would be
<code>100</code>.)
</p>
</overview>
</qhelp>

Просмотреть файл

@ -1,16 +0,0 @@
/**
* @name Number of file-level changes
* @description The number of file-level changes made (by version control history).
* @kind treemap
* @treemap.warnOn highValues
* @metricType file
* @metricAggregate avg min max sum
* @id java/vcs/commits-per-file
* @deprecated
*/
import java
import external.VCS
from File f
select f, count(Commit svn | f = svn.getAnAffectedFile() and not artificialChange(svn))

Просмотреть файл

@ -1,63 +0,0 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
This metric measures the number of recent changes to files that have occurred
below this location in the tree. A recent change is taken to mean a change
that has occurred in the last <code>180</code> days.
</p>
<p>
All code that has changed a great deal may be more than usually prone to
defects, but this is particularly true of code that has been changing
dramatically in the recent past, because it has not yet had a chance to be
properly field-tested in order to iron out the bugs.
</p>
</overview>
<recommendation>
<p>
There is more than one reason why a file may have been changing a lot
recently:
</p>
<ul>
<li>
The file may be part of a new subsystem that is being written. New code is
always going to change a lot in a short period of time, but it is important
to ensure that it is properly code reviewed and unit tested before integrating
it into a working product.
</li>
<li>
The file may be being heavily refactored. Large refactorings are sometimes
essential, but they are also quite risky. You should write proper regression
tests before starting on a major refactoring, and check that they still pass
once you're done.
</li>
<li>
The same bit of code may be being changed repeatedly because it is difficult
to get right. Aside from vigorous code reviewing and testing, it may be a good
idea to rethink the system design - if something is that hard
to get right (and it's not an inherently difficult concept), you might be making life unnecessarily hard for yourself and
risking introducing insidious defects.
</li>
</ul>
</recommendation>
<references>
<li>
N. Nagappan et al. <em>Change Bursts as Defect Predictors</em>. In Proceedings of the 21st IEEE International Symposium on Software Reliability Engineering, 2010.
</li>
</references>
</qhelp>

Просмотреть файл

@ -1,22 +0,0 @@
/**
* @name Number of recent file changes
* @description Number of recent commits to a file (by version control history).
* @kind treemap
* @treemap.warnOn highValues
* @metricType file
* @metricAggregate avg min max sum
* @id java/vcs/recent-commits-per-file
* @deprecated
*/
import java
import external.VCS
from File f, int n
where
n = count(Commit e |
e.getAnAffectedFile() = f and
e.daysToNow() <= 180 and
not artificialChange(e)
)
select f, n order by n desc

Просмотреть файл

@ -171,36 +171,6 @@ tokens(
int endColumn : int ref
);
/*
* Version history
*/
svnentries(
int id : @svnentry,
string revision : string ref,
string author : string ref,
date revisionDate : date ref,
int changeSize : int ref
)
svnaffectedfiles(
int id : @svnentry ref,
int file : @file ref,
string action : string ref
)
svnentrymsg(
int id : @svnentry ref,
string message : string ref
)
svnchurn(
int commit : @svnentry ref,
int file : @file ref,
int addedLines : int ref,
int deletedLines : int ref
)
/*
* Locations and files
*/

Разница между файлами не показана из-за своего большого размера Загрузить разницу

78
java/ql/src/external/VCS.qll поставляемый
Просмотреть файл

@ -1,78 +0,0 @@
import java
class Commit extends @svnentry {
Commit() {
svnaffectedfiles(this, _, _) and
exists(date svnDate, date snapshotDate |
svnentries(this, _, _, svnDate, _) and
snapshotDate(snapshotDate) and
svnDate <= snapshotDate
)
}
string toString() { result = this.getRevisionName() }
string getRevisionName() { svnentries(this, result, _, _, _) }
string getAuthor() { svnentries(this, _, result, _, _) }
date getDate() { svnentries(this, _, _, result, _) }
int getChangeSize() { svnentries(this, _, _, _, result) }
string getMessage() { svnentrymsg(this, result) }
string getAnAffectedFilePath(string action) {
exists(File rawFile | svnaffectedfiles(this, rawFile, action) |
result = rawFile.getAbsolutePath()
)
}
string getAnAffectedFilePath() { result = getAnAffectedFilePath(_) }
File getAnAffectedFile(string action) { svnaffectedfiles(this, result, action) }
File getAnAffectedFile() { exists(string action | result = this.getAnAffectedFile(action)) }
predicate isRecent() { recentCommit(this) }
int daysToNow() {
exists(date now | snapshotDate(now) | result = getDate().daysTo(now) and result >= 0)
}
int getRecentAdditionsForFile(File f) { svnchurn(this, f, result, _) }
int getRecentDeletionsForFile(File f) { svnchurn(this, f, _, result) }
int getRecentChurnForFile(File f) {
exists(int added, int deleted | svnchurn(this, f, added, deleted) and result = added + deleted)
}
}
class Author extends string {
Author() { exists(Commit e | this = e.getAuthor()) }
Commit getACommit() { result.getAuthor() = this }
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
)
}
date firstChange(File f) {
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())
}
predicate artificialChange(Commit e) { firstCommit(e) or e.getChangeSize() >= 50000 }

Просмотреть файл

@ -1,21 +0,0 @@
/**
* @name Filter: only files recently edited
* @description Filter a defect query to only include results in files that have been changed recently, and modify the message.
* @kind problem
* @id java/recently-changed-file-filter
* @deprecated
*/
import java
import external.DefectFilter
import external.VCS
pragma[noopt]
private predicate recent(File file) {
exists(Commit e | file = e.getAnAffectedFile() | e.isRecent() and not artificialChange(e)) and
exists(file.getLocation())
}
from DefectResult res
where recent(res.getFile())
select res, res.getMessage()

Просмотреть файл

@ -1,21 +0,0 @@
/**
* @name Metric filter: only files recently edited
* @description Filter a metric query to only include results in files that have been changed recently, and modify the message.
* @kind treemap
* @id java/recently-changed-file-metric-filter
* @deprecated
*/
import java
import external.MetricFilter
import external.VCS
pragma[noopt]
private predicate recent(File file) {
exists(Commit e | file = e.getAnAffectedFile() | e.isRecent() and not artificialChange(e)) and
exists(file.getLocation())
}
from MetricResult res
where recent(res.getFile())
select res, res.getValue()