00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00012
00013 #ifdef __GNUG__
00014 #pragma implementation "CRCppEmitter.h"
00015 #endif
00016
00017 #include <wxGuiTest/CRCppEmitter.h>
00018
00019 #include <stdexcept>
00020
00021 using namespace wxTst;
00022
00023
00024
00025 CRCppEmitter *CRCppEmitter::ms_instance = NULL;
00026
00027
00028 CRCppEmitter::CRCppEmitter ()
00029 {
00030 this->SetTabSize (4);
00031 m_maxChars = 80;
00032 }
00033
00034
00035 CRCppEmitter::~CRCppEmitter ()
00036 {
00037
00038 while (!m_origFile.Eof ()) {
00039
00040 wxString line = m_origFile.GetNextLine ();
00041 m_newFile.AddLine (line);
00042 }
00043
00044 m_origFile.Close ();
00045 m_newFile.Write ();
00046 m_newFile.Close ();
00047
00048 m_contMap.clear ();
00049 m_varNameSet.clear ();
00050 }
00051
00052
00053 CRCppEmitter * CRCppEmitter::GetInstance ()
00054 {
00055 if (ms_instance == NULL) {
00056
00057 ms_instance = new CRCppEmitter ();
00058 }
00059 return ms_instance;
00060 }
00061
00062
00063 void CRCppEmitter::Destroy ()
00064 {
00065 if (ms_instance != NULL) {
00066
00067 delete ms_instance;
00068 ms_instance = NULL;
00069 }
00070 }
00071
00072
00073 void CRCppEmitter::SetTabSize (unsigned int size)
00074 {
00075 m_tab = wxString (_T(' '), size);
00076 }
00077
00078
00079 unsigned int CRCppEmitter::GetTabSize () const
00080 {
00081 return m_tab.Length ();
00082 }
00083
00084
00085 wxString CRCppEmitter::GetTab () const
00086 {
00087 return m_tab;
00088 }
00089
00090
00091 void CRCppEmitter::SetTestCaseFileContext (const wxString &filename,
00092 size_t lineNmb)
00093 {
00094 wxASSERT_MSG (::wxFileExists (filename), _T("File does not exist"));
00095 wxASSERT (lineNmb != 0);
00096 if (!m_origFile.Open (filename)) {
00097 std::string error("Could not open test case file: ");
00098 error += filename.char_str();
00099 throw std::invalid_argument(error);
00100 }
00101
00102
00103
00104 wxString newFilename;
00105 unsigned int uniqueCnt = 0;
00106 do {
00107
00108 uniqueCnt++;
00109 newFilename = wxString::Format (_T("%s.cr%d"), filename.c_str (),
00110 uniqueCnt);
00111
00112 } while (::wxFileExists (newFilename));
00113 if (!m_newFile.Create (newFilename)) {
00114 std::string error("Could not open test case file: ");
00115 error += filename.char_str();
00116 throw new std::invalid_argument (error);
00117 }
00118
00119 const wxString CAPTURE_KEYWORD = _T("CAPTURE");
00120 for (wxString line = m_origFile.GetFirstLine ();
00121 (!m_origFile.Eof() &&
00122 (lineNmb > 0 && (lineNmb - 1) <= m_origFile.GetCurrentLine ()));
00123 line = m_origFile.GetNextLine ()) {
00124
00125 wxString stripped = line.Strip (wxString::both);
00126 if (CAPTURE_KEYWORD == stripped)
00127 break;
00128 m_newFile.AddLine (line);
00129 }
00130
00131 m_newFile.Write ();
00132 }
00133
00134
00135 wxString CRCppEmitter::GetCaptureFilename() const {
00136 return m_newFile.GetName ();
00137 }
00138
00139 void CRCppEmitter::AddComment (wxString str)
00140 {
00141 wxArrayString COMMENT_BREAK_CHARS;
00142 COMMENT_BREAK_CHARS.Add (_T(" "));
00143 COMMENT_BREAK_CHARS.Add (_T(","));
00144 COMMENT_BREAK_CHARS.Add (_T("."));
00145 COMMENT_BREAK_CHARS.Add (_T(":"));
00146 COMMENT_BREAK_CHARS.Add (_T("!"));
00147 COMMENT_BREAK_CHARS.Add (_T("?"));
00148
00149 wxString pre = m_tab + _T("// ");
00150 const unsigned int MIN_CONTENT_LEN = 20;
00151 str.Prepend (pre);
00152
00153 unsigned int idx;
00154 do {
00155
00156 m_newFile.AddLine (this->BreakString (str, COMMENT_BREAK_CHARS, idx,
00157 pre.Length () + MIN_CONTENT_LEN));
00158 if (idx != 0) {
00159
00160 str = str.Mid (idx);
00161 str.Prepend (pre);
00162 }
00163
00164 } while (idx != 0);
00165
00166 m_newFile.Write ();
00167 }
00168
00169
00170 void CRCppEmitter::AddCode (wxString str)
00171 {
00172 wxArrayString CODE_BREAK_CHARS;
00173 CODE_BREAK_CHARS.Add (_T(" "));
00174 CODE_BREAK_CHARS.Add (_T(","));
00175 CODE_BREAK_CHARS.Add (_T("."));
00176 CODE_BREAK_CHARS.Add (_T("("));
00177 CODE_BREAK_CHARS.Add (_T("::"));
00178 CODE_BREAK_CHARS.Add (_T("->"));
00179
00180 wxString pre = m_tab;
00181 const unsigned int MIN_CONTENT_LEN = 20;
00182 str.Prepend (pre);
00183
00184 bool isInString = false;
00185 unsigned int idx;
00186 do {
00187
00188 wxString line = this->BreakString (str, CODE_BREAK_CHARS, idx,
00189 pre.Length () + MIN_CONTENT_LEN, true);
00190
00191 isInString = this->HasBrokenInString (line);
00192 if (isInString) {
00193
00194 line.Append (_T("\""));
00195 }
00196
00197 m_newFile.AddLine (line);
00198 if (idx != 0) {
00199
00200 str = str.Mid (idx);
00201
00202
00203
00204 if (isInString) {
00205
00206 str.Prepend (_T("\""));
00207 }
00208
00209 for (int i = 0; i < 3; i++) {
00210
00211 str.Prepend (pre);
00212 }
00213 }
00214
00215 } while (idx != 0);
00216
00217 m_newFile.Write ();
00218 }
00219
00220
00221 void CRCppEmitter::AddVerbatimStringWithLineBreaks (wxString str)
00222 {
00223 m_newFile.AddLine (str);
00224
00225 m_newFile.Write ();
00226 }
00227
00228
00229 wxString CRCppEmitter::AddContainerLookupCode (const wxString &containerName,
00230 const wxString &itemDesc, const wxString &containerVarNameSuffix)
00231 {
00232
00233 ContainerMap::iterator it = m_contMap.find (containerName);
00234 if (it != m_contMap.end ()) {
00235
00236 return it->second;
00237 }
00238
00239
00240 wxString containerVarName = MakeFirstCharLowerCase(containerName +
00241 containerVarNameSuffix);
00242
00243 unsigned int cnt = 0;
00244 wxString uniqueContainerVarName = containerVarName;
00245 while ((this->IsContainerVarNameDuplicate (uniqueContainerVarName)) ||
00246 (m_varNameSet.find (uniqueContainerVarName) != m_varNameSet.end ())) {
00247
00248 cnt++;
00249 uniqueContainerVarName = wxString::Format (_T("%s%d"), containerVarName.c_str (), cnt);
00250 }
00251 m_contMap[containerName] = uniqueContainerVarName;
00252 m_varNameSet.insert (uniqueContainerVarName);
00253
00254 wxString lookup, assert;
00255 lookup << _T("wxWindow *") << uniqueContainerVarName <<
00256 _T(" = wxWindow::FindWindowByName (_T(\"") << containerName << _T("\"));");
00257 this->AddCode (lookup);
00258
00259 assert << _T("CPPUNIT_ASSERT_MESSAGE (\"Container window ");
00260 if (itemDesc.IsEmpty ()) {
00261
00262 assert << _T("'") << containerName << _T("'");
00263
00264 } else {
00265
00266 assert << _T("for ") << itemDesc;
00267 }
00268 assert << _T(" not found\", ") << uniqueContainerVarName << _T(" != NULL);");
00269 this->AddCode (assert);
00270
00271 return uniqueContainerVarName;
00272 }
00273
00274
00275 wxString CRCppEmitter::MakeVarName (const wxString &name,
00276 const wxString &suffix)
00277 {
00278
00279
00280 wxString varNameToClean = name;
00281 varNameToClean.Replace (_T(" "), _T(""));
00282 varNameToClean.Replace (_T("&"), _T(""));
00283
00284
00285 wxString varName;
00286 if ((isalpha (varNameToClean.GetChar (0))) || (varNameToClean.GetChar (0) == '_')) {
00287
00288 varName.Append (varNameToClean.GetChar (0));
00289
00290 } else {
00291
00292
00293 varName.Append (_T("var"));
00294 }
00295 for (size_t idx = 1; (idx < varNameToClean.Length ()); idx++) {
00296
00297 if ((isalnum (varNameToClean.GetChar (idx))) ||
00298 (varNameToClean.GetChar (idx) == '_'))
00299
00300 varName.Append (varNameToClean.GetChar (idx));
00301
00302 else
00303 break;
00304 }
00305
00306 varName = MakeFirstCharLowerCase(varName);
00307
00308 varName.Append (suffix);
00309
00310 unsigned int cnt = 0;
00311 wxString uniqueVarName = varName;
00312 while ((this->IsContainerVarNameDuplicate (uniqueVarName)) ||
00313 (m_varNameSet.find (uniqueVarName) != m_varNameSet.end ())) {
00314
00315 cnt++;
00316 uniqueVarName = wxString::Format (_T("%s%d"), varName.c_str (), cnt);
00317 }
00318 wxASSERT(!uniqueVarName.IsEmpty());
00319 m_varNameSet.insert (uniqueVarName);
00320
00321 return uniqueVarName;
00322 }
00323
00324
00325 wxString CRCppEmitter::BreakString (const wxString &str,
00326 const wxArrayString &breakStrs, unsigned int &idx, size_t minIdx,
00327 bool isCode) const
00328 {
00329 if (str.Length () > m_maxChars) {
00330
00331 size_t foundIdx = 0;
00332 size_t maxFoundIdx = 0;
00333 unsigned int breakStrsIdx = 0;
00334 for (size_t i = 0; i < breakStrs.Count (); i++) {
00335
00336
00337 int breakStrLen;
00338 if (isCode) {
00339
00340 breakStrLen = breakStrs.Item (i).Length ();
00341
00342 } else {
00343
00344 breakStrLen = breakStrs.Item (i).Strip ().Length ();
00345 }
00346
00347 foundIdx = str.rfind (breakStrs.Item (i),
00348 m_maxChars - breakStrLen);
00349 if (foundIdx != wxString::npos) {
00350
00351
00352 if (breakStrs.Item (i) == _T(".")) {
00353
00354 wxString line = str.Left (foundIdx);
00355 if (!HasBrokenInString(line)) {
00356
00357
00358 int charIdx = foundIdx - 1;
00359 bool foundComma = false;
00360 bool foundWhitespace = false;
00361 bool finished = false;
00362 while (charIdx > 0 && !finished) {
00363 if (isdigit (line.GetChar (charIdx))) {
00364 if (foundWhitespace || foundComma) {
00365 finished = true;
00366 }
00367 charIdx--;
00368 } else if (line.GetChar (charIdx) == ' ') {
00369 if (foundComma) {
00370 finished = true;
00371 }
00372 foundWhitespace = true;
00373 charIdx--;
00374 } else if (line.GetChar (charIdx) == ',') {
00375 finished = true;
00376 foundComma = true;
00377 foundIdx = 0;
00378 } else {
00379 finished = true;
00380 }
00381 }
00382 }
00383 }
00384
00385 if (foundIdx > maxFoundIdx) {
00386
00387 maxFoundIdx = foundIdx;
00388 breakStrsIdx = i;
00389 }
00390 }
00391 }
00392
00393 if ((maxFoundIdx == 0) || ((minIdx != wxString::npos) &&
00394 (maxFoundIdx < minIdx))) {
00395
00396 idx = m_maxChars;
00397 return str.Left (m_maxChars);
00398
00399 } else {
00400
00401 idx = maxFoundIdx + breakStrs.Item (breakStrsIdx).Length ();
00402
00403 wxString firstLine;
00404 if (isCode) {
00405
00406 firstLine = str.Left (idx);
00407
00408 } else {
00409
00410 firstLine = str.Left (idx).Strip ();
00411 }
00412 return firstLine;
00413 }
00414
00415 } else {
00416
00417 idx = 0;
00418 return str;
00419 }
00420 }
00421
00422
00423 bool CRCppEmitter::HasBrokenInString (const wxString &line) const
00424 {
00425 int freq = line.Freq ('"');
00426 return (freq % 2 == 1);
00427 }
00428
00429
00430 bool CRCppEmitter::IsContainerVarNameDuplicate (const wxString &str) const
00431 {
00432 bool found = false;
00433 ContainerMap::const_iterator it = m_contMap.begin ();
00434 while ((!found) && (it != m_contMap.end ())) {
00435
00436 if (str == it->second) {
00437
00438 found = true;
00439
00440 } else {
00441
00442 it++;
00443 }
00444 }
00445 return found;
00446 }
00447
00448
00449 wxString CRCppEmitter::MakeFirstCharLowerCase (const wxString &str) const
00450 {
00451 wxString firstChar = str.Mid(0, 1).Lower();
00452 return firstChar + str.Mid(1);
00453 }