1 // ASResource.cpp
2 // Copyright (c) 2018 by Jim Pattee <jimp03@email.com>.
3 // This code is licensed under the MIT License.
4 // License.md describes the conditions under which this software may be distributed.
5
6 //-----------------------------------------------------------------------------
7 // headers
8 //-----------------------------------------------------------------------------
9
10 #include "astyle/astyle.h"
11 #include <algorithm>
12
13 //-----------------------------------------------------------------------------
14 // astyle namespace
15 //-----------------------------------------------------------------------------
16
17 namespace astyle {
18 //
19 const string ASResource::_AS_EXCEPT = string("__except");
20 const string ASResource::_AS_FINALLY = string("__finally");
21 const string ASResource::_AS_TRY = string("__try");
22 const string ASResource::AS_ADD = string("add");
23 const string ASResource::AS_AUTO = string("auto");
24 const string ASResource::AS_AUTORELEASEPOOL = string("autoreleasepool");
25 const string ASResource::AS_CASE = string("case");
26 const string ASResource::AS_CATCH = string("catch");
27 const string ASResource::AS_CLASS = string("class");
28 const string ASResource::AS_CONST = string("const");
29 const string ASResource::AS_CONST_CAST = string("const_cast");
30 const string ASResource::AS_DEFAULT = string("default");
31 const string ASResource::AS_DELEGATE = string("delegate");
32 const string ASResource::AS_DELETE = string("delete");
33 const string ASResource::AS_DO = string("do");
34 const string ASResource::AS_DYNAMIC_CAST = string("dynamic_cast");
35 const string ASResource::AS_ELSE = string("else");
36 const string ASResource::AS_END = string("end");
37 const string ASResource::AS_ENUM = string("enum");
38 const string ASResource::AS_EXTERN = string("extern");
39 const string ASResource::AS_FINAL = string("final");
40 const string ASResource::AS_FINALLY = string("finally");
41 const string ASResource::AS_FIXED = string("fixed");
42 const string ASResource::AS_FOR = string("for");
43 const string ASResource::AS_FOREACH = string("foreach");
44 const string ASResource::AS_FOREVER = string("forever");
45 const string ASResource::AS_GET = string("get");
46 const string ASResource::AS_IF = string("if");
47 const string ASResource::AS_INTERFACE = string("interface");
48 const string ASResource::AS_INTERRUPT = string("interrupt");
49 const string ASResource::AS_LET = string("let");
50 const string ASResource::AS_LOCK = string("lock");
51 const string ASResource::AS_MODULE = string("module"); // CORBA IDL module definition
52 const string ASResource::AS_NAMESPACE = string("namespace");
53 const string ASResource::AS_NEW = string("new");
54 const string ASResource::AS_NOEXCEPT = string("noexcept");
55 const string ASResource::AS_NS_DURING = string("NS_DURING");
56 const string ASResource::AS_NS_HANDLER = string("NS_HANDLER");
57 const string ASResource::AS_OPERATOR = string("operator");
58 const string ASResource::AS_OVERRIDE = string("override");
59 const string ASResource::AS_PRIVATE = string("private");
60 const string ASResource::AS_PROTECTED = string("protected");
61 const string ASResource::AS_PUBLIC = string("public");
62 const string ASResource::AS_QFOREACH = string("Q_FOREACH");
63 const string ASResource::AS_QFOREVER = string("Q_FOREVER");
64 const string ASResource::AS_REINTERPRET_CAST = string("reinterpret_cast");
65 const string ASResource::AS_REMOVE = string("remove");
66 const string ASResource::AS_SEALED = string("sealed");
67 const string ASResource::AS_SELECTOR = string("selector");
68 const string ASResource::AS_SET = string("set");
69 const string ASResource::AS_STATIC = string("static");
70 const string ASResource::AS_STATIC_CAST = string("static_cast");
71 const string ASResource::AS_STRUCT = string("struct");
72 const string ASResource::AS_SWITCH = string("switch");
73 const string ASResource::AS_SYNCHRONIZED = string("synchronized");
74 const string ASResource::AS_TEMPLATE = string("template");
75 const string ASResource::AS_THROW = string("throw");
76 const string ASResource::AS_THROWS = string("throws");
77 const string ASResource::AS_TRY = string("try");
78 const string ASResource::AS_UNCHECKED = string("unchecked");
79 const string ASResource::AS_UNION = string("union");
80 const string ASResource::AS_UNSAFE = string("unsafe");
81 const string ASResource::AS_USING = string("using");
82 const string ASResource::AS_VOLATILE = string("volatile");
83 const string ASResource::AS_WHERE = string("where");
84 const string ASResource::AS_WHILE = string("while");
85
86 const string ASResource::AS_ASM = string("asm");
87 const string ASResource::AS__ASM__ = string("__asm__");
88 const string ASResource::AS_MS_ASM = string("_asm");
89 const string ASResource::AS_MS__ASM = string("__asm");
90
91 const string ASResource::AS_BAR_DEFINE = string("#define");
92 const string ASResource::AS_BAR_INCLUDE = string("#include");
93 const string ASResource::AS_BAR_IF = string("#if");
94 const string ASResource::AS_BAR_EL = string("#el");
95 const string ASResource::AS_BAR_ENDIF = string("#endif");
96
97 const string ASResource::AS_OPEN_BRACE = string("{");
98 const string ASResource::AS_CLOSE_BRACE = string("}");
99 const string ASResource::AS_OPEN_LINE_COMMENT = string("//");
100 const string ASResource::AS_OPEN_COMMENT = string("/*");
101 const string ASResource::AS_CLOSE_COMMENT = string("*/");
102
103 const string ASResource::AS_ASSIGN = string("=");
104 const string ASResource::AS_PLUS_ASSIGN = string("+=");
105 const string ASResource::AS_MINUS_ASSIGN = string("-=");
106 const string ASResource::AS_MULT_ASSIGN = string("*=");
107 const string ASResource::AS_DIV_ASSIGN = string("/=");
108 const string ASResource::AS_MOD_ASSIGN = string("%=");
109 const string ASResource::AS_OR_ASSIGN = string("|=");
110 const string ASResource::AS_AND_ASSIGN = string("&=");
111 const string ASResource::AS_XOR_ASSIGN = string("^=");
112 const string ASResource::AS_GR_GR_ASSIGN = string(">>=");
113 const string ASResource::AS_LS_LS_ASSIGN = string("<<=");
114 const string ASResource::AS_GR_GR_GR_ASSIGN = string(">>>=");
115 const string ASResource::AS_LS_LS_LS_ASSIGN = string("<<<=");
116 const string ASResource::AS_GCC_MIN_ASSIGN = string("<?");
117 const string ASResource::AS_GCC_MAX_ASSIGN = string(">?");
118
119 const string ASResource::AS_RETURN = string("return");
120 const string ASResource::AS_CIN = string("cin");
121 const string ASResource::AS_COUT = string("cout");
122 const string ASResource::AS_CERR = string("cerr");
123
124 const string ASResource::AS_EQUAL = string("==");
125 const string ASResource::AS_PLUS_PLUS = string("++");
126 const string ASResource::AS_MINUS_MINUS = string("--");
127 const string ASResource::AS_NOT_EQUAL = string("!=");
128 const string ASResource::AS_GR_EQUAL = string(">=");
129 const string ASResource::AS_GR_GR = string(">>");
130 const string ASResource::AS_GR_GR_GR = string(">>>");
131 const string ASResource::AS_LS_EQUAL = string("<=");
132 const string ASResource::AS_LS_LS = string("<<");
133 const string ASResource::AS_LS_LS_LS = string("<<<");
134 const string ASResource::AS_QUESTION_QUESTION = string("??");
135 const string ASResource::AS_LAMBDA = string("=>"); // C# lambda expression arrow
136 const string ASResource::AS_ARROW = string("->");
137 const string ASResource::AS_AND = string("&&");
138 const string ASResource::AS_OR = string("||");
139 const string ASResource::AS_SCOPE_RESOLUTION = string("::");
140
141 const string ASResource::AS_PLUS = string("+");
142 const string ASResource::AS_MINUS = string("-");
143 const string ASResource::AS_MULT = string("*");
144 const string ASResource::AS_DIV = string("/");
145 const string ASResource::AS_MOD = string("%");
146 const string ASResource::AS_GR = string(">");
147 const string ASResource::AS_LS = string("<");
148 const string ASResource::AS_NOT = string("!");
149 const string ASResource::AS_BIT_OR = string("|");
150 const string ASResource::AS_BIT_AND = string("&");
151 const string ASResource::AS_BIT_NOT = string("~");
152 const string ASResource::AS_BIT_XOR = string("^");
153 const string ASResource::AS_QUESTION = string("?");
154 const string ASResource::AS_COLON = string(":");
155 const string ASResource::AS_COMMA = string(",");
156 const string ASResource::AS_SEMICOLON = string(";");
157
158 /**
159 * Sort comparison function.
160 * Compares the length of the value of pointers in the vectors.
161 * The LONGEST strings will be first in the vector.
162 *
163 * @param a and b, the string pointers to be compared.
164 */
sortOnLength(const string * a,const string * b)165 bool sortOnLength(const string* a, const string* b)
166 {
167 return (*a).length() > (*b).length();
168 }
169
170 /**
171 * Sort comparison function.
172 * Compares the value of pointers in the vectors.
173 *
174 * @param a and b, the string pointers to be compared.
175 */
sortOnName(const string * a,const string * b)176 bool sortOnName(const string* a, const string* b)
177 {
178 return *a < *b;
179 }
180
181 /**
182 * Build the vector of assignment operators.
183 * Used by BOTH ASFormatter.cpp and ASBeautifier.cpp
184 *
185 * @param assignmentOperators a reference to the vector to be built.
186 */
buildAssignmentOperators(vector<const string * > * assignmentOperators)187 void ASResource::buildAssignmentOperators(vector<const string*>* assignmentOperators)
188 {
189 const size_t elements = 15;
190 assignmentOperators->reserve(elements);
191
192 assignmentOperators->emplace_back(&AS_ASSIGN);
193 assignmentOperators->emplace_back(&AS_PLUS_ASSIGN);
194 assignmentOperators->emplace_back(&AS_MINUS_ASSIGN);
195 assignmentOperators->emplace_back(&AS_MULT_ASSIGN);
196 assignmentOperators->emplace_back(&AS_DIV_ASSIGN);
197 assignmentOperators->emplace_back(&AS_MOD_ASSIGN);
198 assignmentOperators->emplace_back(&AS_OR_ASSIGN);
199 assignmentOperators->emplace_back(&AS_AND_ASSIGN);
200 assignmentOperators->emplace_back(&AS_XOR_ASSIGN);
201
202 // Java
203 assignmentOperators->emplace_back(&AS_GR_GR_GR_ASSIGN);
204 assignmentOperators->emplace_back(&AS_GR_GR_ASSIGN);
205 assignmentOperators->emplace_back(&AS_LS_LS_ASSIGN);
206
207 // Unknown
208 assignmentOperators->emplace_back(&AS_LS_LS_LS_ASSIGN);
209
210 assert(assignmentOperators->size() < elements);
211 sort(assignmentOperators->begin(), assignmentOperators->end(), sortOnLength);
212 }
213
214 /**
215 * Build the vector of C++ cast operators.
216 * Used by ONLY ASFormatter.cpp
217 *
218 * @param castOperators a reference to the vector to be built.
219 */
buildCastOperators(vector<const string * > * castOperators)220 void ASResource::buildCastOperators(vector<const string*>* castOperators)
221 {
222 const size_t elements = 5;
223 castOperators->reserve(elements);
224
225 castOperators->emplace_back(&AS_CONST_CAST);
226 castOperators->emplace_back(&AS_DYNAMIC_CAST);
227 castOperators->emplace_back(&AS_REINTERPRET_CAST);
228 castOperators->emplace_back(&AS_STATIC_CAST);
229
230 assert(castOperators->size() < elements);
231 sort(castOperators->begin(), castOperators->end(), sortOnName);
232 }
233
234 /**
235 * Build the vector of header words.
236 * Used by BOTH ASFormatter.cpp and ASBeautifier.cpp
237 *
238 * @param headers a reference to the vector to be built.
239 */
buildHeaders(vector<const string * > * headers,int fileType,bool beautifier)240 void ASResource::buildHeaders(vector<const string*>* headers, int fileType, bool beautifier)
241 {
242 const size_t elements = 25;
243 headers->reserve(elements);
244
245 headers->emplace_back(&AS_IF);
246 headers->emplace_back(&AS_ELSE);
247 headers->emplace_back(&AS_FOR);
248 headers->emplace_back(&AS_WHILE);
249 headers->emplace_back(&AS_DO);
250 headers->emplace_back(&AS_SWITCH);
251 headers->emplace_back(&AS_CASE);
252 headers->emplace_back(&AS_DEFAULT);
253 headers->emplace_back(&AS_TRY);
254 headers->emplace_back(&AS_CATCH);
255 headers->emplace_back(&AS_QFOREACH); // QT
256 headers->emplace_back(&AS_QFOREVER); // QT
257 headers->emplace_back(&AS_FOREACH); // QT & C#
258 headers->emplace_back(&AS_FOREVER); // Qt & Boost
259
260 if (fileType == C_TYPE)
261 {
262 headers->emplace_back(&_AS_TRY); // __try
263 headers->emplace_back(&_AS_FINALLY); // __finally
264 headers->emplace_back(&_AS_EXCEPT); // __except
265 }
266 if (fileType == JAVA_TYPE)
267 {
268 headers->emplace_back(&AS_FINALLY);
269 headers->emplace_back(&AS_SYNCHRONIZED);
270 }
271
272 if (fileType == SHARP_TYPE)
273 {
274 headers->emplace_back(&AS_FINALLY);
275 headers->emplace_back(&AS_LOCK);
276 headers->emplace_back(&AS_FIXED);
277 headers->emplace_back(&AS_GET);
278 headers->emplace_back(&AS_SET);
279 headers->emplace_back(&AS_ADD);
280 headers->emplace_back(&AS_REMOVE);
281 headers->emplace_back(&AS_USING);
282 }
283
284 if (beautifier)
285 {
286 if (fileType == C_TYPE)
287 {
288 headers->emplace_back(&AS_TEMPLATE);
289 }
290
291 if (fileType == JAVA_TYPE)
292 {
293 headers->emplace_back(&AS_STATIC); // for static constructor
294 }
295 }
296
297 assert(headers->size() < elements);
298 sort(headers->begin(), headers->end(), sortOnName);
299 }
300
301 /**
302 * Build the vector of indentable headers.
303 * Used by ONLY ASBeautifier.cpp
304 *
305 * @param indentableHeaders a reference to the vector to be built.
306 */
buildIndentableHeaders(vector<const string * > * indentableHeaders)307 void ASResource::buildIndentableHeaders(vector<const string*>* indentableHeaders)
308 {
309 indentableHeaders->emplace_back(&AS_RETURN);
310
311 // sort(indentableHeaders->begin(), indentableHeaders->end(), sortOnName);
312 }
313
314 /**
315 * Build the vector of indentable macros pairs.
316 * Initialized by ASFormatter, used by ONLY ASEnhancer.cpp
317 *
318 * @param indentableMacros a reference to the vector to be built.
319 */
buildIndentableMacros(vector<const pair<const string,const string> * > * indentableMacros)320 void ASResource::buildIndentableMacros(vector<const pair<const string, const string>* >* indentableMacros)
321 {
322 const size_t elements = 10;
323 indentableMacros->reserve(elements);
324
325 // the pairs must be retained in memory because of pair pointers
326 using macro_pair = pair<const string, const string>;
327 static const macro_pair macros[] =
328 {
329 // wxWidgets
330 macro_pair("BEGIN_EVENT_TABLE", "END_EVENT_TABLE"),
331 macro_pair("wxBEGIN_EVENT_TABLE", "wxEND_EVENT_TABLE"),
332 // MFC
333 macro_pair("BEGIN_DISPATCH_MAP", "END_DISPATCH_MAP"),
334 macro_pair("BEGIN_EVENT_MAP", "END_EVENT_MAP"),
335 macro_pair("BEGIN_MESSAGE_MAP", "END_MESSAGE_MAP"),
336 macro_pair("BEGIN_PROPPAGEIDS", "END_PROPPAGEIDS"),
337 };
338
339 for (const macro_pair& macro : macros)
340 indentableMacros->emplace_back(¯o);
341
342 assert(indentableMacros->size() < elements);
343 }
344
345 /**
346 * Build the vector of non-assignment operators.
347 * Used by ONLY ASBeautifier.cpp
348 *
349 * @param nonAssignmentOperators a reference to the vector to be built.
350 */
buildNonAssignmentOperators(vector<const string * > * nonAssignmentOperators)351 void ASResource::buildNonAssignmentOperators(vector<const string*>* nonAssignmentOperators)
352 {
353 const size_t elements = 15;
354 nonAssignmentOperators->reserve(elements);
355
356 nonAssignmentOperators->emplace_back(&AS_EQUAL);
357 nonAssignmentOperators->emplace_back(&AS_PLUS_PLUS);
358 nonAssignmentOperators->emplace_back(&AS_MINUS_MINUS);
359 nonAssignmentOperators->emplace_back(&AS_NOT_EQUAL);
360 nonAssignmentOperators->emplace_back(&AS_GR_EQUAL);
361 nonAssignmentOperators->emplace_back(&AS_GR_GR_GR);
362 nonAssignmentOperators->emplace_back(&AS_GR_GR);
363 nonAssignmentOperators->emplace_back(&AS_LS_EQUAL);
364 nonAssignmentOperators->emplace_back(&AS_LS_LS_LS);
365 nonAssignmentOperators->emplace_back(&AS_LS_LS);
366 nonAssignmentOperators->emplace_back(&AS_ARROW);
367 nonAssignmentOperators->emplace_back(&AS_AND);
368 nonAssignmentOperators->emplace_back(&AS_OR);
369 nonAssignmentOperators->emplace_back(&AS_LAMBDA);
370
371 assert(nonAssignmentOperators->size() < elements);
372 sort(nonAssignmentOperators->begin(), nonAssignmentOperators->end(), sortOnLength);
373 }
374
375 /**
376 * Build the vector of header non-paren headers.
377 * Used by BOTH ASFormatter.cpp and ASBeautifier.cpp.
378 * NOTE: Non-paren headers should also be included in the headers vector.
379 *
380 * @param nonParenHeaders a reference to the vector to be built.
381 */
buildNonParenHeaders(vector<const string * > * nonParenHeaders,int fileType,bool beautifier)382 void ASResource::buildNonParenHeaders(vector<const string*>* nonParenHeaders, int fileType, bool beautifier)
383 {
384 const size_t elements = 20;
385 nonParenHeaders->reserve(elements);
386
387 nonParenHeaders->emplace_back(&AS_ELSE);
388 nonParenHeaders->emplace_back(&AS_DO);
389 nonParenHeaders->emplace_back(&AS_TRY);
390 nonParenHeaders->emplace_back(&AS_CATCH); // can be paren or non-paren
391 nonParenHeaders->emplace_back(&AS_CASE); // can be paren or non-paren
392 nonParenHeaders->emplace_back(&AS_DEFAULT);
393 nonParenHeaders->emplace_back(&AS_QFOREVER); // QT
394 nonParenHeaders->emplace_back(&AS_FOREVER); // Boost
395
396 if (fileType == C_TYPE)
397 {
398 nonParenHeaders->emplace_back(&_AS_TRY); // __try
399 nonParenHeaders->emplace_back(&_AS_FINALLY); // __finally
400 }
401 if (fileType == JAVA_TYPE)
402 {
403 nonParenHeaders->emplace_back(&AS_FINALLY);
404 }
405
406 if (fileType == SHARP_TYPE)
407 {
408 nonParenHeaders->emplace_back(&AS_FINALLY);
409 nonParenHeaders->emplace_back(&AS_GET);
410 nonParenHeaders->emplace_back(&AS_SET);
411 nonParenHeaders->emplace_back(&AS_ADD);
412 nonParenHeaders->emplace_back(&AS_REMOVE);
413 }
414
415 if (beautifier)
416 {
417 if (fileType == C_TYPE)
418 {
419 nonParenHeaders->emplace_back(&AS_TEMPLATE);
420 }
421 if (fileType == JAVA_TYPE)
422 {
423 nonParenHeaders->emplace_back(&AS_STATIC);
424 }
425 }
426
427 assert(nonParenHeaders->size() < elements);
428 sort(nonParenHeaders->begin(), nonParenHeaders->end(), sortOnName);
429 }
430
431 /**
432 * Build the vector of operators.
433 * Used by ONLY ASFormatter.cpp
434 *
435 * @param operators a reference to the vector to be built.
436 */
buildOperators(vector<const string * > * operators,int fileType)437 void ASResource::buildOperators(vector<const string*>* operators, int fileType)
438 {
439 const size_t elements = 50;
440 operators->reserve(elements);
441
442 operators->emplace_back(&AS_PLUS_ASSIGN);
443 operators->emplace_back(&AS_MINUS_ASSIGN);
444 operators->emplace_back(&AS_MULT_ASSIGN);
445 operators->emplace_back(&AS_DIV_ASSIGN);
446 operators->emplace_back(&AS_MOD_ASSIGN);
447 operators->emplace_back(&AS_OR_ASSIGN);
448 operators->emplace_back(&AS_AND_ASSIGN);
449 operators->emplace_back(&AS_XOR_ASSIGN);
450 operators->emplace_back(&AS_EQUAL);
451 operators->emplace_back(&AS_PLUS_PLUS);
452 operators->emplace_back(&AS_MINUS_MINUS);
453 operators->emplace_back(&AS_NOT_EQUAL);
454 operators->emplace_back(&AS_GR_EQUAL);
455 operators->emplace_back(&AS_GR_GR_GR_ASSIGN);
456 operators->emplace_back(&AS_GR_GR_ASSIGN);
457 operators->emplace_back(&AS_GR_GR_GR);
458 operators->emplace_back(&AS_GR_GR);
459 operators->emplace_back(&AS_LS_EQUAL);
460 operators->emplace_back(&AS_LS_LS_LS_ASSIGN);
461 operators->emplace_back(&AS_LS_LS_ASSIGN);
462 operators->emplace_back(&AS_LS_LS_LS);
463 operators->emplace_back(&AS_LS_LS);
464 operators->emplace_back(&AS_QUESTION_QUESTION);
465 operators->emplace_back(&AS_LAMBDA);
466 operators->emplace_back(&AS_ARROW);
467 operators->emplace_back(&AS_AND);
468 operators->emplace_back(&AS_OR);
469 operators->emplace_back(&AS_SCOPE_RESOLUTION);
470 operators->emplace_back(&AS_PLUS);
471 operators->emplace_back(&AS_MINUS);
472 operators->emplace_back(&AS_MULT);
473 operators->emplace_back(&AS_DIV);
474 operators->emplace_back(&AS_MOD);
475 operators->emplace_back(&AS_QUESTION);
476 operators->emplace_back(&AS_COLON);
477 operators->emplace_back(&AS_ASSIGN);
478 operators->emplace_back(&AS_LS);
479 operators->emplace_back(&AS_GR);
480 operators->emplace_back(&AS_NOT);
481 operators->emplace_back(&AS_BIT_OR);
482 operators->emplace_back(&AS_BIT_AND);
483 operators->emplace_back(&AS_BIT_NOT);
484 operators->emplace_back(&AS_BIT_XOR);
485 if (fileType == C_TYPE)
486 {
487 operators->emplace_back(&AS_GCC_MIN_ASSIGN);
488 operators->emplace_back(&AS_GCC_MAX_ASSIGN);
489 }
490
491 assert(operators->size() < elements);
492 sort(operators->begin(), operators->end(), sortOnLength);
493 }
494
495 /**
496 * Build the vector of pre-block statements.
497 * Used by ONLY ASBeautifier.cpp
498 * NOTE: Cannot be both a header and a preBlockStatement.
499 *
500 * @param preBlockStatements a reference to the vector to be built.
501 */
buildPreBlockStatements(vector<const string * > * preBlockStatements,int fileType)502 void ASResource::buildPreBlockStatements(vector<const string*>* preBlockStatements, int fileType)
503 {
504 const size_t elements = 10;
505 preBlockStatements->reserve(elements);
506
507 preBlockStatements->emplace_back(&AS_CLASS);
508 if (fileType == C_TYPE)
509 {
510 preBlockStatements->emplace_back(&AS_STRUCT);
511 preBlockStatements->emplace_back(&AS_UNION);
512 preBlockStatements->emplace_back(&AS_NAMESPACE);
513 preBlockStatements->emplace_back(&AS_MODULE); // for CORBA IDL
514 preBlockStatements->emplace_back(&AS_INTERFACE); // for CORBA IDL
515 }
516 if (fileType == JAVA_TYPE)
517 {
518 preBlockStatements->emplace_back(&AS_INTERFACE);
519 preBlockStatements->emplace_back(&AS_THROWS);
520 }
521 if (fileType == SHARP_TYPE)
522 {
523 preBlockStatements->emplace_back(&AS_INTERFACE);
524 preBlockStatements->emplace_back(&AS_NAMESPACE);
525 preBlockStatements->emplace_back(&AS_WHERE);
526 preBlockStatements->emplace_back(&AS_STRUCT);
527 }
528
529 assert(preBlockStatements->size() < elements);
530 sort(preBlockStatements->begin(), preBlockStatements->end(), sortOnName);
531 }
532
533 /**
534 * Build the vector of pre-command headers.
535 * Used by BOTH ASFormatter.cpp and ASBeautifier.cpp.
536 * NOTE: Cannot be both a header and a preCommandHeader.
537 *
538 * A preCommandHeader is in a function definition between
539 * the closing paren and the opening brace.
540 * e.g. in "void foo() const {}", "const" is a preCommandHeader.
541 */
buildPreCommandHeaders(vector<const string * > * preCommandHeaders,int fileType)542 void ASResource::buildPreCommandHeaders(vector<const string*>* preCommandHeaders, int fileType)
543 {
544 const size_t elements = 10;
545 preCommandHeaders->reserve(elements);
546
547 if (fileType == C_TYPE)
548 {
549 preCommandHeaders->emplace_back(&AS_CONST);
550 preCommandHeaders->emplace_back(&AS_FINAL);
551 preCommandHeaders->emplace_back(&AS_INTERRUPT);
552 preCommandHeaders->emplace_back(&AS_NOEXCEPT);
553 preCommandHeaders->emplace_back(&AS_OVERRIDE);
554 preCommandHeaders->emplace_back(&AS_VOLATILE);
555 preCommandHeaders->emplace_back(&AS_SEALED); // Visual C only
556 preCommandHeaders->emplace_back(&AS_AUTORELEASEPOOL); // Obj-C only
557 }
558
559 if (fileType == JAVA_TYPE)
560 {
561 preCommandHeaders->emplace_back(&AS_THROWS);
562 }
563
564 if (fileType == SHARP_TYPE)
565 {
566 preCommandHeaders->emplace_back(&AS_WHERE);
567 }
568
569 assert(preCommandHeaders->size() < elements);
570 sort(preCommandHeaders->begin(), preCommandHeaders->end(), sortOnName);
571 }
572
573 /**
574 * Build the vector of pre-definition headers.
575 * Used by ONLY ASFormatter.cpp
576 * NOTE: Do NOT add 'enum' here. It is an array type brace.
577 * NOTE: Do NOT add 'extern' here. Do not want an extra indent.
578 *
579 * @param preDefinitionHeaders a reference to the vector to be built.
580 */
buildPreDefinitionHeaders(vector<const string * > * preDefinitionHeaders,int fileType)581 void ASResource::buildPreDefinitionHeaders(vector<const string*>* preDefinitionHeaders, int fileType)
582 {
583 const size_t elements = 10;
584 preDefinitionHeaders->reserve(elements);
585
586 preDefinitionHeaders->emplace_back(&AS_CLASS);
587 if (fileType == C_TYPE)
588 {
589 preDefinitionHeaders->emplace_back(&AS_STRUCT);
590 preDefinitionHeaders->emplace_back(&AS_UNION);
591 preDefinitionHeaders->emplace_back(&AS_NAMESPACE);
592 preDefinitionHeaders->emplace_back(&AS_MODULE); // for CORBA IDL
593 preDefinitionHeaders->emplace_back(&AS_INTERFACE); // for CORBA IDL
594 }
595 if (fileType == JAVA_TYPE)
596 {
597 preDefinitionHeaders->emplace_back(&AS_INTERFACE);
598 }
599 if (fileType == SHARP_TYPE)
600 {
601 preDefinitionHeaders->emplace_back(&AS_STRUCT);
602 preDefinitionHeaders->emplace_back(&AS_INTERFACE);
603 preDefinitionHeaders->emplace_back(&AS_NAMESPACE);
604 }
605
606 assert(preDefinitionHeaders->size() < elements);
607 sort(preDefinitionHeaders->begin(), preDefinitionHeaders->end(), sortOnName);
608 }
609
610 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
611 * ASBase Functions
612 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
613
614 // check if a specific line position contains a header.
findHeader(const string & line,int i,const vector<const string * > * possibleHeaders) const615 const string* ASBase::findHeader(const string& line, int i,
616 const vector<const string*>* possibleHeaders) const
617 {
618 assert(isCharPotentialHeader(line, i));
619 // check the word
620 size_t maxHeaders = possibleHeaders->size();
621 for (size_t p = 0; p < maxHeaders; p++)
622 {
623 const string* header = (*possibleHeaders)[p];
624 const size_t wordEnd = i + header->length();
625 if (wordEnd > line.length())
626 continue;
627 int result = (line.compare(i, header->length(), *header));
628 if (result > 0)
629 continue;
630 if (result < 0)
631 break;
632 // check that this is not part of a longer word
633 if (wordEnd == line.length())
634 return header;
635 if (isLegalNameChar(line[wordEnd]))
636 continue;
637 const char peekChar = peekNextChar(line, wordEnd - 1);
638 // is not a header if part of a definition
639 if (peekChar == ',' || peekChar == ')')
640 break;
641 // the following accessor definitions are NOT headers
642 // goto default; is NOT a header
643 // default(int) keyword in C# is NOT a header
644 if ((header == &AS_GET
645 || header == &AS_SET
646 || header == &AS_DEFAULT)
647 && (peekChar == ';' || peekChar == '(' || peekChar == '='))
648 break;
649 return header;
650 }
651 return nullptr;
652 }
653
654 // check if a specific line position contains a keyword.
findKeyword(const string & line,int i,const string & keyword) const655 bool ASBase::findKeyword(const string& line, int i, const string& keyword) const
656 {
657 assert(isCharPotentialHeader(line, i));
658 // check the word
659 const size_t keywordLength = keyword.length();
660 const size_t wordEnd = i + keywordLength;
661 if (wordEnd > line.length())
662 return false;
663 if (line.compare(i, keywordLength, keyword) != 0)
664 return false;
665 // check that this is not part of a longer word
666 if (wordEnd == line.length())
667 return true;
668 if (isLegalNameChar(line[wordEnd]))
669 return false;
670 // is not a keyword if part of a definition
671 const char peekChar = peekNextChar(line, (int) wordEnd - 1);
672 if (peekChar == ',' || peekChar == ')')
673 return false;
674 return true;
675 }
676
677 // check if a specific line position contains an operator.
findOperator(const string & line,int i,const vector<const string * > * possibleOperators) const678 const string* ASBase::findOperator(const string& line, int i,
679 const vector<const string*>* possibleOperators) const
680 {
681 assert(isCharPotentialOperator(line[i]));
682 // find the operator in the vector
683 // the vector contains the LONGEST operators first
684 // must loop thru the entire vector
685 size_t maxOperators = possibleOperators->size();
686 for (size_t p = 0; p < maxOperators; p++)
687 {
688 const size_t wordEnd = i + (*(*possibleOperators)[p]).length();
689 if (wordEnd > line.length())
690 continue;
691 if (line.compare(i, (*(*possibleOperators)[p]).length(), *(*possibleOperators)[p]) == 0)
692 return (*possibleOperators)[p];
693 }
694 return nullptr;
695 }
696
697 // get the current word on a line
698 // index must point to the beginning of the word
getCurrentWord(const string & line,size_t index) const699 string ASBase::getCurrentWord(const string& line, size_t index) const
700 {
701 assert(isCharPotentialHeader(line, index));
702 size_t lineLength = line.length();
703 size_t i;
704 for (i = index; i < lineLength; i++)
705 {
706 if (!isLegalNameChar(line[i]))
707 break;
708 }
709 return line.substr(index, i - index);
710 }
711
712 // check if a specific character can be used in a legal variable/method/class name
isLegalNameChar(char ch) const713 bool ASBase::isLegalNameChar(char ch) const
714 {
715 if (isWhiteSpace(ch))
716 return false;
717 if ((unsigned char) ch > 127)
718 return false;
719 return (isalnum((unsigned char) ch)
720 || ch == '.' || ch == '_'
721 || (isJavaStyle() && ch == '$')
722 || (isSharpStyle() && ch == '@')); // may be used as a prefix
723 }
724
725 // check if a specific character can be part of a header
isCharPotentialHeader(const string & line,size_t i) const726 bool ASBase::isCharPotentialHeader(const string& line, size_t i) const
727 {
728 assert(!isWhiteSpace(line[i]));
729 char prevCh = ' ';
730 if (i > 0)
731 prevCh = line[i - 1];
732 if (i > 1 && line[i - 2] == '\\')
733 prevCh = ' ';
734 if (!isLegalNameChar(prevCh) && isLegalNameChar(line[i]))
735 return true;
736 return false;
737 }
738
739 // check if a specific character can be part of an operator
isCharPotentialOperator(char ch) const740 bool ASBase::isCharPotentialOperator(char ch) const
741 {
742 assert(!isWhiteSpace(ch));
743 if ((unsigned) ch > 127)
744 return false;
745 return (ispunct((unsigned char) ch)
746 && ch != '{' && ch != '}'
747 && ch != '(' && ch != ')'
748 && ch != '[' && ch != ']'
749 && ch != ';' && ch != ','
750 && ch != '#' && ch != '\\'
751 && ch != '\'' && ch != '\"');
752 }
753
754 // check if a specific character is a digit
755 // NOTE: Visual C isdigit() gives assert error if char > 256
isDigit(char ch) const756 bool ASBase::isDigit(char ch) const
757 {
758 return (ch >= '0' && ch <= '9');
759 }
760
761 // check if a specific character is a digit separator
isDigitSeparator(const string & line,int i) const762 bool ASBase::isDigitSeparator(const string& line, int i) const
763 {
764 assert(line[i] == '\'');
765 // casting to (unsigned char) eliminates negative characters
766 // will get a "Debug Assertion Failed" if not cast
767 bool foundDigitSeparator = i > 0
768 && isxdigit((unsigned char) line[i - 1])
769 && i < (int) line.length() - 1
770 && isxdigit((unsigned char) line[i + 1]);
771 return foundDigitSeparator;
772 }
773
774 // peek at the next unread character.
peekNextChar(const string & line,int i) const775 char ASBase::peekNextChar(const string& line, int i) const
776 {
777 char ch = ' ';
778 size_t peekNum = line.find_first_not_of(" \t", i + 1);
779 if (peekNum == string::npos)
780 return ch;
781 ch = line[peekNum];
782 return ch;
783 }
784
785 } // end namespace astyle
786