-
Notifications
You must be signed in to change notification settings - Fork 0
/
stereocode.cpp
143 lines (123 loc) · 6.83 KB
/
stereocode.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
// SPDX-License-Identifier: GPL-3.0-only
/**
* @file stereocode.cpp
*
* @copyright Copyright (C) 2021-2024 srcML, LLC. (www.srcML.org)
*
* This file is part of the Stereocode application.
*/
#include "ClassModelCollection.hpp"
#include "CLI11.hpp"
primitiveTypes PRIMITIVES; // Primitive types per language + any user supplied
ignorableCalls IGNORED_CALLS; // Calls to ignore + any user supplied
typeTokens TYPE_TOKENS; // Tokens to remove from data types + any user supplied
int METHODS_PER_CLASS_THRESHOLD = 21; // Threshold for large class stereotype (from ICSM10)
bool STRUCT = false; // Identify and stereotype structs (C++ or C#)
bool INTERFACE = false; // Identify and stereotype interfaces (C# or Java)
bool IS_VERBOSE = false; // Prints primitives, ignored calls, and type tokens
std::unordered_map
<int, std::unordered_map
<std::string, std::string>> XPATH_LIST; // Map key = unit number. Each map value is a pair of xpath and stereotype
std::vector<std::string> LANGUAGE = {"C++", "C#", "Java"}; // Supported languages
XPathBuilder XPATH_TRANSFORMATION; // List of xpaths used for transformations
int main (int argc, char const *argv[]) {
std::string inputFile;
std::string primitivesFile;
std::string ignoredCallsFile;
std::string typeTokensFile;
std::string outputFile;
bool outputTxtReport = false;
bool outputCsvReport = false;
bool overWriteInput = false;
bool reDocComment = false;
CLI::App app{"Stereocode: Determines method and class stereotypes\n"
"Supports C++, C#, and Java\n" };
app.add_flag ("-v,--verbose", IS_VERBOSE, "Enable verbose output");
app.add_option("input-archive", inputFile, "File name of a srcML input archive")->required();
app.add_option("-o,--output-file", outputFile, "File name of output - srcML archive with stereotypes");
app.add_option("-p,--primitive-file", primitivesFile, "File name of user supplied primitive types (one per line)");
app.add_option("-g,--ignore-call-file", ignoredCallsFile, "File name of user supplied calls to ignore (one per line)");
app.add_option("-t,--type-token-file", typeTokensFile, "File name of user supplied data type tokens to remove (one per line)");
app.add_flag ("-i,--interface", INTERFACE, "Identify stereotypes for interfaces (C# and Java)");
app.add_flag ("-s,--struct", STRUCT, "Identify stereotypes for structs (C# and Java)");
app.add_flag ("-e,--input-overwrite", overWriteInput, "Overwrite input with stereotype information");
app.add_flag ("-x,--txt-report", outputTxtReport, "Output optional TXT report file containing stereotype information");
app.add_flag ("-z,--csv-report", outputCsvReport, "Output optional CSV report file containing stereotype information");
app.add_flag ("-c,--comment", reDocComment, "Annotates stereotypes as a comment before method and class definitetions (/** @stereotype stereotype */)");
app.add_option("-l,--large-class", METHODS_PER_CLASS_THRESHOLD, "Method threshold for the large-class stereotype (default = 21)");
CLI11_PARSE(app, argc, argv);
// Add user-defined primitive types to initial set
if (primitivesFile != "") {
std::ifstream in(primitivesFile);
if (in.is_open())
in >> PRIMITIVES;
else {
std::cerr << "Error: Primitive types file not found: " << primitivesFile << '\n';
return -1;
}
in.close();
}
// Add user-defined ignored calls to initial set
if (ignoredCallsFile != "") {
std::ifstream in(ignoredCallsFile);
if (in.is_open())
in >> IGNORED_CALLS;
else {
std::cerr << "Error: Ignorable calls file not found: " << ignoredCallsFile << '\n';
return -1;
}
in.close();
}
// Add user-defined type tokens to initial set
if (typeTokensFile != "") {
std::ifstream in(typeTokensFile);
if (in.is_open())
in >> TYPE_TOKENS;
else {
std::cerr << "Error: Type tokens file not found: " << typeTokensFile << '\n';
return -1;
}
in.close();
}
srcml_archive* archive = srcml_archive_create();
int error = srcml_archive_read_open_filename(archive, inputFile.c_str());
if (error) {
std::cerr << "Error: File not found: " << inputFile << ", error == " << error << '\n';
srcml_archive_free(archive);
return -1;
}
// Default output file name if output file name is not specified
if (outputFile == "") {
std::string InputFileNoExt = inputFile.substr(0, inputFile.size() - 4);
outputFile = InputFileNoExt + ".stereotypes.xml";
}
srcml_archive* outputArchive = srcml_archive_create();
error = srcml_archive_write_open_filename(outputArchive, outputFile.c_str());
if (error) {
std::cerr << "Error opening: " << outputFile << std::endl;
srcml_archive_close(archive);
srcml_archive_free(archive);
srcml_archive_free(outputArchive);
return -1;
}
// Register namespace for output of stereotypes
srcml_archive_register_namespace(outputArchive, "st", "http://www.srcML.org/srcML/stereotype");
std::vector<srcml_unit*> units;
srcml_unit* unit = srcml_archive_read_unit(archive);
// Read all units in an archive
while (unit){
units.push_back(unit);
unit = srcml_archive_read_unit(archive);
}
// Find method and class stereotypes
if (units.size() > 0) {
XPATH_TRANSFORMATION.generateXpath(); // Called here since it depends on globals initalized by user input
classModelCollection classObj(archive, outputArchive, units,
inputFile, outputFile, outputTxtReport, outputCsvReport, reDocComment);
}
if (overWriteInput) {
std::filesystem::remove(inputFile);
std::filesystem::rename(outputFile, inputFile);
}
return 0;
}