-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathutils.cpp
190 lines (164 loc) · 6.45 KB
/
utils.cpp
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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
// SPDX-License-Identifier: GPL-3.0-only
/**
* @file utils.cpp
*
* @copyright Copyright (C) 2021-2024 srcML, LLC. (www.srcML.org)
*
* This file is part of the Stereocode application.
*/
#include "utils.hpp"
extern primitiveTypes PRIMITIVES;
extern std::vector<std::string> LANGUAGE;
extern typeModifiers TYPE_MODIFIERS;
bool isNonPrimitiveType(const std::string& type, variable& var,
const std::string& unitLanguage, const std::string& className) {
std::string typeParsed = type;
std::size_t listOpen = typeParsed.find("<");
if (listOpen != std::string::npos) {
std::string typeLeft = typeParsed.substr(0, listOpen);
std::string typeRight = typeParsed.substr(listOpen, typeParsed.size() - listOpen);
// removeNamespace() can mess up the string when there is a namespace inside <>
// For example: Factory <hippodraw::DataRep> --> removeNamespace() --> DataRep>
// This is why we need to separate them
//
removeNamespace(typeLeft, true, unitLanguage); // No generics and no comma separated list
typeParsed = typeLeft + typeRight;
}
removeTypeModifiers(typeParsed, unitLanguage); // Can take full type as is
trimWhitespace(typeParsed); // Can take full type as is
bool isNonPrimitive = false;
std::size_t start = 0;
std::size_t end = typeParsed.find(",");
std::string subType;
while (end != std::string::npos) {
subType = typeParsed.substr(start, end - start);
removeNamespace(subType, true, unitLanguage);
if (!isPrimitiveType(subType, unitLanguage)) {
isNonPrimitive = true;
if (subType != className)
var.setNonPrimitiveExternal(true);
}
start = end + 1;
end = typeParsed.find(",", start);
}
subType = typeParsed.substr(start, typeParsed.size() - start);
removeNamespace(subType, true, unitLanguage);
if (!isPrimitiveType(subType, unitLanguage)) {
isNonPrimitive = true;
if (subType != className)
var.setNonPrimitiveExternal(true);
}
return isNonPrimitive;
}
// Checks if a type is primitive.
//
bool isPrimitiveType(const std::string& type, const std::string& unitLanguage) {
std::istringstream subType(type);
std::string token;
while (std::getline(subType, token, ','))
if (!PRIMITIVES.isPrimitive(token, unitLanguage)) return false;
return true;
}
bool matchSubstring(const std::string& text, const std::string& substring) {
const std::string pattern = "\\b" + substring + "\\b";
const std::regex regexPattern(pattern);
std::smatch match;
return std::regex_search(text, match, regexPattern);
}
// Removes specifiers from type name
//
void removeTypeModifiers(std::string& type, std::string unitLanguage) {
std::regex regexPattern(TYPE_MODIFIERS.getTypeModifiers(unitLanguage));
type = std::regex_replace(type, regexPattern, " ");
}
// Removes all whitespace from string
//
void trimWhitespace(std::string& s) {
s.erase(std::remove_if(s.begin(), s.end(), [](unsigned char c) { return std::isspace(c); }), s.end());
}
// Trim blanks of the right of string
//
void Rtrim(std::string& s) {
std::size_t lastNonSpace = s.find_last_not_of(' ');
if (lastNonSpace != std::string::npos)
s = s.substr(0, lastNonSpace + 1);
}
// Removes namespaces from names
// all = false keeps the last :: or .
//
void removeNamespace(std::string& name, bool all, std::string_view unitLanguage) {
std::size_t last, secondLast;
if (unitLanguage == "C++") last = name.rfind("::");
else last = name.rfind(".");
if (last != std::string::npos) {
if (all) {
if (unitLanguage == "C++") name = name.substr(last + 2);
else name = name.substr(last + 1);
}
else {
if (unitLanguage == "C++") secondLast = name.rfind("::", last - 1);
else secondLast = name.rfind(".", last - 1);
if (secondLast != std::string::npos) {
if (unitLanguage == "C++") name = name.substr(secondLast + 2);
else name = name.substr(secondLast + 1);
}
}
}
}
// Converts all whitespaces to blanks ('\r' => ' ')
void WStoBlank(std::string& s) {
std::replace_if(s.begin(),
s.end(),
[](char c) { return isspace(c); },
' ');
}
// Removes all characters inside <> or () except for comma
// For example, myObject<int, std::pair<int, int>> becomes myObject<,>
// and Foo(int, std::pair<int, int>, double) becomes Foo(,,)
//
void removeBetweenComma(std::string& s, bool isGeneric) {
std::size_t opening;
if (isGeneric)
opening = s.find("<");
else
opening = s.find("(");
if (opening != std::string::npos) {
std::string name = s.substr(0, opening + 1);
s = s.substr(opening + 1);
// This could be nested inside () or <> for types
// <[^>]*> --> starts at <, then matches everything except > and stops at > including the >
std::string pattern = R"(<[^>]*>)";
std::regex regexPattern(pattern);
s = std::regex_replace(s, regexPattern, "");
pattern = "";
if (isGeneric)
pattern = R"(([^,]*)(,|>))";
else
pattern = R"(([^,]*)(,|\)))";
const std::regex regexPatternTwo (pattern);
s = std::regex_replace(s, regexPatternTwo, "$2"); // $2 is used to replace the content with the second group
s = name + s;
}
}
// Workaround to get Stereocode to work with srcML 1.0.0
// It works by removing the item= attribute, which has an issue in srcML 1.0.0
//
void srcmlBackwardCompatibility(std::string& xmlText) {
const std::vector<std::string> tags = {"><property", "><constructor", "><destructor", "><function"};
std::size_t pos = std::string::npos;
for (const auto& tag : tags) {
pos = xmlText.find(tag);
if (pos != std::string::npos) {
break;
}
}
if (pos != std::string::npos) {
std::string beforeFunction = xmlText.substr(0, pos);
std::string afterFunction = xmlText.substr(pos);
std::size_t item = beforeFunction.find("item=");
if (item != std::string::npos) {}
beforeFunction = beforeFunction.substr(0, item);
beforeFunction.pop_back();
xmlText = beforeFunction + afterFunction;
}
}