-
Notifications
You must be signed in to change notification settings - Fork 30
Expand file tree
/
Copy pathFeaturesFilter.cpp
More file actions
153 lines (139 loc) · 7.63 KB
/
FeaturesFilter.cpp
File metadata and controls
153 lines (139 loc) · 7.63 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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/*
* Copyright (c) Huawei Technologies Co., Ltd. 2012-2021. All rights reserved.
*/
#include "FeaturesFilter.h"
#include "TimeExecStatistics.h"
#include "clang-utils/ClangUtils.h"
#include "exceptions/NoTestGeneratedException.h"
#include "loguru.h"
static void updateIfNotCompleteType(types::TypeSupport &typeSupport,
bool condition,
std::string const &message) {
if (typeSupport.isSupported && condition) {
typeSupport = { false, message };
}
}
void FeaturesFilter::filter(utbot::SettingsContext const &settingsContext,
const types::TypesHandler &typesHandler,
tests::TestsMap &testsMap,
bool throwIfZeroFunctions) {
bool hasSupportedMethods = false;
std::unordered_map<string, int> unsupportedStatistics;
for (auto testsMapIterator = testsMap.begin(); testsMapIterator != testsMap.end();
testsMapIterator++) {
fs::path const &sourceFile = testsMapIterator.key();
tests::Tests &tests = testsMapIterator.value();
filterGlobalParameters(typesHandler, tests);
size_t erased = CollectionUtils::erase_if(tests.methods,
[&](const tests::Tests::MethodDescription &method) {
if (!method.hasPointerToIncompleteReturnType) {
auto returnTypeSupport =
typesHandler.isSupportedType(method.returnType, types::TypeUsage::RETURN);
if (!returnTypeSupport.isSupported) {
unsupportedStatistics[returnTypeSupport.info]++;
std::stringstream message;
message << "Function '" << method.name << "' was skipped, as return type '"
<< method.returnType.typeName()
<< "' is not fully supported: " << returnTypeSupport.info;
LOG_S(WARNING) << message.str();
tests.commentBlocks.push_back(message.str());
return true;
}
}
for (const auto ¶m: method.params) {
auto paramTypeSupport = typesHandler.isSupportedType(param.type, types::TypeUsage::PARAMETER);
updateIfNotCompleteType(paramTypeSupport, param.isPointerToIncomplete,
"Parameter has incomplete type");
if (!paramTypeSupport.isSupported) {
unsupportedStatistics[paramTypeSupport.info]++;
std::stringstream message;
message << "Function '" << method.name << "' was skipped, as parameter '" << param.name
<< "' is not fully supported: " << paramTypeSupport.info;
LOG_S(WARNING) << message.str();
tests.commentBlocks.push_back(message.str());
return true;
}
}
if (method.modifiers.isStatic && !settingsContext.generateForStaticFunctions) {
std::stringstream message;
message << "Function '" << method.name
<< "' was skipped, as option \"Generate For Static Functions\""
<< "is disabled";
LOG_S(DEBUG) << message.str();
tests.commentBlocks.push_back(message.str());
return true;
}
if (method.modifiers.isInline &&
(!method.modifiers.isStatic && !method.modifiers.isExtern)) {
std::stringstream message;
message
<< "Function '" << method.name
<< "' was skipped, as inline function without static or extern "
"modifier is not supported by now";
LOG_S(DEBUG) << message.str();
tests.commentBlocks.push_back(message.str());
return true;
}
unsupportedStatistics["passed features filter"]++;
return false;
});
LOG_S(DEBUG) << erased << " erased methods for file " << sourceFile;
if (!tests.methods.empty()) {
hasSupportedMethods = true;
}
}
std::stringstream statsMessage;
statsMessage << "Unsupported statistics:\n";
for (const auto &[reason, count] : unsupportedStatistics) {
statsMessage << StringUtils::stringFormat("%d functions: %s\n", count, reason);
}
LOG_S(DEBUG) << statsMessage.str();
if (!hasSupportedMethods && throwIfZeroFunctions) {
throw NoTestGeneratedException("Couldn't find any supported methods. "
"Please check if source directories are specified correctly. "
"See logs for more details about unsupported functions.");
}
}
static void logReason(const types::TypeName& typeName, std::string_view methodName, std::string_view info) {
LOG_S(DEBUG) << "Global parameter " << typeName
<< " for function \'" << methodName
<< "\' was skipped: " << info;
}
void FeaturesFilter::filterGlobalParameters(const types::TypesHandler &typesHandler,
tests::Tests &tests) {
for (auto it = tests.methods.begin(); it != tests.methods.end(); it++) {
auto &methodName = it.key();
auto &methodDescription = it.value();
size_t erased = CollectionUtils::erase_if(
methodDescription.globalParams, [&](tests::Tests::MethodParam const ¶m) {
auto globalParamSupport =
typesHandler.isSupportedType(param.type, types::TypeUsage::PARAMETER);
if (!globalParamSupport.isSupported) {
logReason(param.name, methodName, globalParamSupport.info);
return true;
}
if (param.type.baseTypeObj().isPointerToFunction()) {
logReason(param.name, methodName, "Type or its base is 'pointer to function'");
return true;
}
if (param.type.baseTypeObj().isUnnamed()) {
logReason(param.name, methodName, "Type or its base is unnamed");
return true;
}
if (typesHandler.isVoid(param.type.baseTypeObj())) {
logReason(param.name, methodName, "Type or its base is void");
return true;
}
if (typesHandler.isIncompleteArrayType(param.type)) {
logReason(param.name, methodName, "Type is incomplete array");
return true;
}
if (typesHandler.isArrayType(param.type) && param.type.baseTypeObj(1).isObjectPointer()) {
logReason(param.name, methodName, "Type is array of pointers");
return true;
}
return false;
});
LOG_S(DEBUG) << erased << " erased global variables for method " << methodName;
}
}