-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathDatabaseQuality.qll
More file actions
130 lines (103 loc) · 3.9 KB
/
Copy pathDatabaseQuality.qll
File metadata and controls
130 lines (103 loc) · 3.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/**
* Provides database quality statistics that are reported by csharp/telemetry/extractor-information
* and perhaps warned about by csharp/diagnostics/database-quality.
*/
import csharp
signature module StatsSig {
int getNumberOfOk();
int getNumberOfNotOk();
string getOkText();
string getNotOkText();
}
module ReportStats<StatsSig Stats> {
predicate numberOfOk(string key, int value) {
value = Stats::getNumberOfOk() and
key = "Number of " + Stats::getOkText()
}
predicate numberOfNotOk(string key, int value) {
value = Stats::getNumberOfNotOk() and
key = "Number of " + Stats::getNotOkText()
}
predicate percentageOfOk(string key, float value) {
value = Stats::getNumberOfOk() * 100.0 / (Stats::getNumberOfOk() + Stats::getNumberOfNotOk()) and
key = "Percentage of " + Stats::getOkText()
}
}
module CallTargetStats implements StatsSig {
int getNumberOfOk() { result = count(Call c | exists(c.getTarget())) }
private predicate isNoSetterPropertyCallInConstructor(PropertyCall c) {
exists(Property p, Constructor ctor |
p = c.getProperty() and
not exists(Setter a | a = p.getAnAccessor()) and
c.getEnclosingCallable() = ctor and
(
c.hasThisQualifier()
or
ctor instanceof StaticConstructor and p.getDeclaringType() = ctor.getDeclaringType()
)
)
}
private predicate isNoSetterPropertyInitialization(PropertyCall c) {
exists(Property p, AssignExpr assign |
p = c.getProperty() and
not exists(Setter a | a = p.getAnAccessor()) and
assign = c.getParent() and
assign.getLValue() = c and
assign.getParent() instanceof Property
)
}
private predicate isAnonymousObjectMemberDeclaration(PropertyCall c) {
exists(Property p, AssignExpr assign |
p = c.getProperty() and
assign = c.getParent() and
assign.getLValue() = c and
assign.getParent() instanceof ObjectInitializer and
assign.getParent().getParent() instanceof AnonymousObjectCreation
)
}
private predicate isInitializedWithObjectOrCollectionInitializer(PropertyCall c) {
exists(Property p, AssignExpr assign |
p = c.getProperty() and
assign = c.getParent() and
assign.getLValue() = c and
assign.getRValue() instanceof ObjectOrCollectionInitializer
)
}
private predicate isEventFieldAccess(EventCall c) {
exists(Event e | c.getEvent() = e |
forall(Accessor a | e.getAnAccessor() = a | a.isCompilerGenerated())
)
}
private predicate isTypeParameterInstantiation(ObjectCreation e) {
e.getType() instanceof TypeParameter
}
additional predicate isNotOkCall(Call c) {
not exists(c.getTarget()) and
not c instanceof DelegateCall and
not c instanceof DynamicExpr and
not isNoSetterPropertyCallInConstructor(c) and
not isNoSetterPropertyInitialization(c) and
not isAnonymousObjectMemberDeclaration(c) and
not isInitializedWithObjectOrCollectionInitializer(c) and
not c.getParent+() instanceof NameOfExpr and
not isEventFieldAccess(c) and
not isTypeParameterInstantiation(c)
}
int getNumberOfNotOk() { result = count(Call c | isNotOkCall(c)) }
string getOkText() { result = "calls with call target" }
string getNotOkText() { result = "calls with missing call target" }
}
private class SourceExpr extends Expr {
SourceExpr() { this.getFile().fromSource() }
}
private predicate hasGoodType(Expr e) {
exists(e.getType()) and not e.getType() instanceof UnknownType
}
module ExprTypeStats implements StatsSig {
int getNumberOfOk() { result = count(SourceExpr e | hasGoodType(e)) }
int getNumberOfNotOk() { result = count(SourceExpr e | not hasGoodType(e)) }
string getOkText() { result = "expressions with known type" }
string getNotOkText() { result = "expressions with unknown type" }
}
module CallTargetStatsReport = ReportStats<CallTargetStats>;
module ExprTypeStatsReport = ReportStats<ExprTypeStats>;