C++: Autoformat Architecture + Best Practices

This commit is contained in:
Jonas Jensen
2019-04-11 14:27:07 +02:00
parent 75ab311c3a
commit 6049c2ccfd
42 changed files with 762 additions and 518 deletions

View File

@@ -10,11 +10,12 @@
* statistical
* non-attributable
*/
import cpp
predicate functionUsesVariable(Function source, Variable v, File target) {
v.getAnAccess().getEnclosingFunction() = source and
not (v.(LocalScopeVariable).getFunction() = source) and
not v.(LocalScopeVariable).getFunction() = source and
v.getFile() = target
}
@@ -25,15 +26,15 @@ predicate functionUsesFunction(Function source, Function f, File target) {
predicate dependencyCount(Function source, File target, int res) {
res = strictcount(Declaration d |
functionUsesVariable(source, d, target) or
functionUsesFunction(source, d, target)
)
functionUsesVariable(source, d, target) or
functionUsesFunction(source, d, target)
)
}
predicate selfDependencyCountOrZero(Function source, int res) {
exists(File target
| target = source.getFile() and onlyInFile(source, target)
| res = max(int i | dependencyCount(source, target, i) or i = 0))
exists(File target | target = source.getFile() and onlyInFile(source, target) |
res = max(int i | dependencyCount(source, target, i) or i = 0)
)
}
predicate dependsHighlyOn(Function source, File target, int res) {
@@ -41,7 +42,7 @@ predicate dependsHighlyOn(Function source, File target, int res) {
target.fromSource() and
exists(int selfCount |
selfDependencyCountOrZero(source, selfCount) and
res > 2*selfCount and
res > 2 * selfCount and
res > 4
)
}
@@ -52,14 +53,18 @@ predicate onlyInFile(Function f, File file) {
}
from Function f, File other, int selfCount, int depCount, string selfDeps
where dependsHighlyOn(f, other, depCount) and
selfDependencyCountOrZero(f, selfCount) and
not exists(File yetAnother | dependsHighlyOn(f, yetAnother, _) and yetAnother != other) and
not other instanceof HeaderFile and
not f instanceof MemberFunction
and if selfCount = 0 then selfDeps = "0 dependencies"
else if selfCount = 1 then selfDeps = "only 1 dependency"
else selfDeps = "only " + selfCount.toString() + " dependencies"
select f, "Function " + f.getName() + " could be moved to file $@" +
" since it has " + depCount.toString() + " dependencies to that file, but " +
selfDeps + " to its own file.", other, other.getBaseName()
where
dependsHighlyOn(f, other, depCount) and
selfDependencyCountOrZero(f, selfCount) and
not exists(File yetAnother | dependsHighlyOn(f, yetAnother, _) and yetAnother != other) and
not other instanceof HeaderFile and
not f instanceof MemberFunction and
if selfCount = 0
then selfDeps = "0 dependencies"
else
if selfCount = 1
then selfDeps = "only 1 dependency"
else selfDeps = "only " + selfCount.toString() + " dependencies"
select f,
"Function " + f.getName() + " could be moved to file $@" + " since it has " + depCount.toString() +
" dependencies to that file, but " + selfDeps + " to its own file.", other, other.getBaseName()

View File

@@ -9,6 +9,7 @@
* @result_ondemand succeed 48
* @tags maintainability
*/
import cpp
from Class s

View File

@@ -7,11 +7,10 @@
* @treemap.warnOn highValues
* @tags maintainability
*/
import cpp
from Class c
where c.fromSource()
select c as Class,
c.getMetrics().getAfferentCoupling() as AfferentCoupling,
c.getMetrics().getEfferentSourceCoupling() as EfferentCoupling
order by AfferentCoupling desc
select c as Class, c.getMetrics().getAfferentCoupling() as AfferentCoupling,
c.getMetrics().getEfferentSourceCoupling() as EfferentCoupling order by AfferentCoupling desc

View File

@@ -9,6 +9,7 @@
* @result_ondemand succeed 48
* @tags maintainability
*/
import cpp
/** does source class c have inheritance depth d? */
@@ -18,6 +19,5 @@ predicate hasInheritanceDepth(Class c, int d) {
from int depth
where hasInheritanceDepth(_, depth)
select depth as InheritanceDepth,
count(Class c | hasInheritanceDepth(c, depth)) as NumberOfClasses
order by InheritanceDepth
select depth as InheritanceDepth, count(Class c | hasInheritanceDepth(c, depth)) as NumberOfClasses
order by InheritanceDepth

View File

@@ -7,6 +7,7 @@
* @tags maintainability
* modularity
*/
import cpp
from MetricNamespace a, MetricNamespace b

View File

@@ -6,10 +6,12 @@
* @tags maintainability
* modularity
*/
import cpp
from Class c
where c.fromSource()
and c.isTopLevel()
and c.getParentScope() instanceof GlobalNamespace
where
c.fromSource() and
c.isTopLevel() and
c.getParentScope() instanceof GlobalNamespace
select c, "This class is not declared in any namespace"

View File

@@ -7,6 +7,7 @@
* @tags maintainability
* modularity
*/
import cpp
from MetricNamespace a, MetricNamespace b

View File

@@ -5,31 +5,57 @@
* @id cpp/architecture/general-statistics
* @tags maintainability
*/
import cpp
from string l, string n
where (l = "Number of Namespaces" and
n = count(Namespace p | p.fromSource()).toString())
or (l = "Number of Files" and
n = count(File f | f.fromSource()).toString())
or (l = "Number of Header Files" and
n = count(HeaderFile f | f.fromSource()).toString())
or (l = "Number of C Files" and
n = count(CFile f | f.fromSource()).toString())
or (l = "Number of C++ Files" and
n = count(CppFile f | f.fromSource()).toString())
or (l = "Number of Classes" and
n = count(Class c | c.fromSource() and not c instanceof Struct).toString())
or (l = "Number of Structs" and
n = count(Struct s | s.fromSource()and not s instanceof Union).toString())
or (l = "Number of Unions" and
n = count(Union u | u.fromSource()).toString())
or (l = "Number of Functions" and
n = count(Function f | f.fromSource()).toString())
or (l = "Number of Lines Of Code" and
n = sum(File f, int toSum | (f.fromSource()) and (toSum = f.getMetrics().getNumberOfLinesOfCode()) | toSum).toString())
or (l = "Self-Containedness" and
n = (100 * sum(Class c, int toSum | (c.fromSource()) and (toSum = c.getMetrics().getEfferentSourceCoupling()) | toSum)
/ sum(Class c, int toSum | (c.fromSource()) and (toSum = c.getMetrics().getEfferentCoupling()) | toSum)).toString()
+ "%")
where
l = "Number of Namespaces" and
n = count(Namespace p | p.fromSource()).toString()
or
l = "Number of Files" and
n = count(File f | f.fromSource()).toString()
or
l = "Number of Header Files" and
n = count(HeaderFile f | f.fromSource()).toString()
or
l = "Number of C Files" and
n = count(CFile f | f.fromSource()).toString()
or
l = "Number of C++ Files" and
n = count(CppFile f | f.fromSource()).toString()
or
l = "Number of Classes" and
n = count(Class c | c.fromSource() and not c instanceof Struct).toString()
or
l = "Number of Structs" and
n = count(Struct s | s.fromSource() and not s instanceof Union).toString()
or
l = "Number of Unions" and
n = count(Union u | u.fromSource()).toString()
or
l = "Number of Functions" and
n = count(Function f | f.fromSource()).toString()
or
l = "Number of Lines Of Code" and
n = sum(File f, int toSum |
f.fromSource() and toSum = f.getMetrics().getNumberOfLinesOfCode()
|
toSum
).toString()
or
l = "Self-Containedness" and
n = (
100 *
sum(Class c, int toSum |
c.fromSource() and toSum = c.getMetrics().getEfferentSourceCoupling()
|
toSum
) /
sum(Class c, int toSum |
c.fromSource() and toSum = c.getMetrics().getEfferentCoupling()
|
toSum
)
).toString() + "%"
select l as Title, n as Value

View File

@@ -10,6 +10,7 @@
* statistical
* non-attributable
*/
import cpp
predicate remoteVarAccess(File source, File target, VariableAccess va) {
@@ -48,16 +49,19 @@ predicate highDependencyCount(File source, File target, int res) {
variableDependencyCount(source, target, varCount) and
functionDependencyCount(source, target, funCount) and
res = varCount + funCount and
res > 20)
res > 20
)
}
from File a, File b, int ca, int cb
where highDependencyCount(a, b, ca) and
highDependencyCount(b, a, cb) and
ca >= cb and
a != b and
not a instanceof HeaderFile and
not b instanceof HeaderFile and
b.getShortName().trim().length() > 0
select a, "File is too closely tied to $@ (" + ca.toString() + " dependencies one way and " + cb.toString() + " the other).",
b, b.getBaseName()
where
highDependencyCount(a, b, ca) and
highDependencyCount(b, a, cb) and
ca >= cb and
a != b and
not a instanceof HeaderFile and
not b instanceof HeaderFile and
b.getShortName().trim().length() > 0
select a,
"File is too closely tied to $@ (" + ca.toString() + " dependencies one way and " + cb.toString() +
" the other).", b, b.getBaseName()

View File

@@ -11,10 +11,12 @@
* statistical
* non-attributable
*/
import cpp
from Class t, int n
where t.fromSource() and
n = t.getMetrics().getEfferentSourceCoupling() and
n > 10
where
t.fromSource() and
n = t.getMetrics().getEfferentSourceCoupling() and
n > 10
select t as Class, "This class has too many dependencies (" + n.toString() + ")"

View File

@@ -9,41 +9,51 @@
* statistical
* non-attributable
*/
import cpp
string kindstr(Class c)
{
string kindstr(Class c) {
exists(int kind | usertypes(unresolveElement(c), _, kind) |
(kind = 1 and result = "Struct") or
(kind = 2 and result = "Class") or
(kind = 6 and result = "Template class")
kind = 1 and result = "Struct"
or
kind = 2 and result = "Class"
or
kind = 6 and result = "Template class"
)
}
predicate vdeInfo(VariableDeclarationEntry vde, Class c, File f, int line)
{
predicate vdeInfo(VariableDeclarationEntry vde, Class c, File f, int line) {
c = vde.getVariable().getDeclaringType() and
f = vde.getLocation().getFile() and
line = vde.getLocation().getStartLine()
}
predicate previousVde(VariableDeclarationEntry previous, VariableDeclarationEntry vde)
{
predicate previousVde(VariableDeclarationEntry previous, VariableDeclarationEntry vde) {
exists(Class c, File f, int line | vdeInfo(vde, c, f, line) |
vdeInfo(previous, c, f, line - 3) or
vdeInfo(previous, c, f, line - 2) or
vdeInfo(previous, c, f, line - 1) or
(vdeInfo(previous, c, f, line) and exists(int prevCol, int vdeCol |
prevCol = previous.getLocation().getStartColumn() and vdeCol = vde.getLocation().getStartColumn() |
prevCol < vdeCol or (prevCol = vdeCol and previous.getName() < vde.getName())
))
vdeInfo(previous, c, f, line - 3)
or
vdeInfo(previous, c, f, line - 2)
or
vdeInfo(previous, c, f, line - 1)
or
vdeInfo(previous, c, f, line) and
exists(int prevCol, int vdeCol |
prevCol = previous.getLocation().getStartColumn() and
vdeCol = vde.getLocation().getStartColumn()
|
prevCol < vdeCol
or
prevCol = vdeCol and previous.getName() < vde.getName()
)
)
}
predicate masterVde(VariableDeclarationEntry master, VariableDeclarationEntry vde)
{
(not previousVde(_, vde) and master = vde) or
exists(VariableDeclarationEntry previous | previousVde(previous, vde) and masterVde(master, previous))
predicate masterVde(VariableDeclarationEntry master, VariableDeclarationEntry vde) {
not previousVde(_, vde) and master = vde
or
exists(VariableDeclarationEntry previous |
previousVde(previous, vde) and masterVde(master, previous)
)
}
class VariableDeclarationGroup extends ElementBase {
@@ -51,9 +61,8 @@ class VariableDeclarationGroup extends ElementBase {
this instanceof VariableDeclarationEntry and
not previousVde(_, this)
}
Class getClass() {
vdeInfo(this, result, _, _)
}
Class getClass() { vdeInfo(this, result, _, _) }
// pragma[noopt] since otherwise the two locationInfo relations get join-ordered
// after each other
@@ -63,7 +72,9 @@ class VariableDeclarationGroup extends ElementBase {
masterVde(this, last) and
this instanceof VariableDeclarationGroup and
not previousVde(last, _) and
exists(VariableDeclarationEntry vde | vde=this and vde instanceof VariableDeclarationEntry and vde.getLocation() = lstart) and
exists(VariableDeclarationEntry vde |
vde = this and vde instanceof VariableDeclarationEntry and vde.getLocation() = lstart
) and
last.getLocation() = lend and
lstart.hasLocationInfo(path, startline, startcol, _, _) and
lend.hasLocationInfo(path, _, _, endline, endcol)
@@ -71,15 +82,16 @@ class VariableDeclarationGroup extends ElementBase {
}
string describeGroup() {
if previousVde(this, _) then
result = "group of "
+ strictcount(string name
| exists(VariableDeclarationEntry vde
| masterVde(this, vde) and
name = vde.getName()))
+ " fields here"
else
result = "declaration of " + this.(VariableDeclarationEntry).getVariable().getName()
if previousVde(this, _)
then
result = "group of " +
strictcount(string name |
exists(VariableDeclarationEntry vde |
masterVde(this, vde) and
name = vde.getName()
)
) + " fields here"
else result = "declaration of " + this.(VariableDeclarationEntry).getVariable().getName()
}
}
@@ -89,26 +101,32 @@ class ExtClass extends Class {
}
predicate hasLocationInfo(string path, int startline, int startcol, int endline, int endcol) {
if hasOneVariableGroup() then
exists(VariableDeclarationGroup vdg | vdg.getClass() = this | vdg.hasLocationInfo(path, startline, startcol, endline, endcol))
else
getLocation().hasLocationInfo(path, startline, startcol, endline, endcol)
if hasOneVariableGroup()
then
exists(VariableDeclarationGroup vdg | vdg.getClass() = this |
vdg.hasLocationInfo(path, startline, startcol, endline, endcol)
)
else getLocation().hasLocationInfo(path, startline, startcol, endline, endcol)
}
}
from ExtClass c, int n, VariableDeclarationGroup vdg, string suffix
where n = strictcount(string fieldName
| exists(Field f
| f.getDeclaringType() = c and
fieldName = f.getName() and
// IBOutlet's are a way of building GUIs
// automatically out of ObjC properties.
// We don't want to count those for the
// purposes of this query.
not (f.getType().getAnAttribute().hasName("iboutlet")))) and
n > 15 and
not c.isConstructedFrom(_) and
c = vdg.getClass() and
if c.hasOneVariableGroup() then suffix = "" else suffix = " - see $@"
select c, kindstr(c) + " " + c.getName() + " has " + n + " fields; we suggest refactoring to 15 fields or fewer" + suffix + ".",
vdg, vdg.describeGroup()
where
n = strictcount(string fieldName |
exists(Field f |
f.getDeclaringType() = c and
fieldName = f.getName() and
// IBOutlet's are a way of building GUIs
// automatically out of ObjC properties.
// We don't want to count those for the
// purposes of this query.
not f.getType().getAnAttribute().hasName("iboutlet")
)
) and
n > 15 and
not c.isConstructedFrom(_) and
c = vdg.getClass() and
if c.hasOneVariableGroup() then suffix = "" else suffix = " - see $@"
select c,
kindstr(c) + " " + c.getName() + " has " + n +
" fields; we suggest refactoring to 15 fields or fewer" + suffix + ".", vdg, vdg.describeGroup()

View File

@@ -8,11 +8,13 @@
* statistical
* non-attributable
*/
import cpp
from Function f, int n
where f.fromSource() and
n = f.getMetrics().getNumberOfCalls() and
n > 99 and
not f.isMultiplyDefined()
where
f.fromSource() and
n = f.getMetrics().getNumberOfCalls() and
n > 99 and
not f.isMultiplyDefined()
select f as Function, "This function makes too many calls (" + n.toString() + ")"

View File

@@ -8,9 +8,11 @@
* statistical
* non-attributable
*/
import cpp
from Function f, int complexity
where complexity = f.getMetrics().getCyclomaticComplexity()
and complexity > 250
where
complexity = f.getMetrics().getCyclomaticComplexity() and
complexity > 250
select f, "Function has high cyclomatic complexity: " + complexity.toString()

View File

@@ -9,10 +9,13 @@
* statistical
* non-attributable
*/
import cpp
from Function f
where f.fromSource() and
f.getMetrics().getNumberOfParameters() > 15
select f, "This function has too many parameters ("
+ f.getMetrics().getNumberOfParameters().toString() + ")"
where
f.fromSource() and
f.getMetrics().getNumberOfParameters() > 15
select f,
"This function has too many parameters (" + f.getMetrics().getNumberOfParameters().toString() +
")"