1 /**
2 * @file align_func_params.cpp
3 *
4 * @author Guy Maurel
5 * split from align.cpp
6 * @author Ben Gardner
7 * @license GPL v2+
8 */
9
10 #include "align_func_params.h"
11
12 #include "align_stack.h"
13 #include "log_rules.h"
14
15 #include <algorithm> // to get max
16
17 constexpr static auto LCURRENT = LALIGN;
18
19 using namespace uncrustify;
20
21
align_func_param(chunk_t * start)22 chunk_t *align_func_param(chunk_t *start)
23 {
24 LOG_FUNC_ENTRY();
25
26 LOG_FMT(LAS, "AlignStack::%s(%d): Candidate is '%s': orig_line is %zu, column is %zu, type is %s, level is %zu\n",
27 __func__, __LINE__, start->text(), start->orig_line, start->column,
28 get_token_name(start->type), start->level);
29 // Defaults, if the align_func_params = true
30 size_t myspan = 2;
31 size_t mythresh = 0;
32 size_t mygap = 0;
33
34 // Override, if the align_func_params_span > 0
35 log_rule_B("align_func_params_span");
36
37 if (options::align_func_params_span() > 0)
38 {
39 myspan = options::align_func_params_span();
40 log_rule_B("align_func_params_thresh");
41 mythresh = options::align_func_params_thresh();
42 log_rule_B("align_func_params_gap");
43 mygap = options::align_func_params_gap();
44 }
45 const size_t HOW_MANY_AS = 16; // Issue #2921
46 AlignStack many_as[HOW_MANY_AS + 1];
47
48 size_t max_level_is = 0;
49
50 log_rule_B("align_var_def_star_style");
51 log_rule_B("align_var_def_amp_style");
52
53 for (size_t idx = 0; idx <= HOW_MANY_AS; idx++)
54 {
55 many_as[idx].Start(myspan, mythresh);
56 many_as[idx].m_gap = mygap;
57 many_as[idx].m_star_style = static_cast<AlignStack::StarStyle>(options::align_var_def_star_style());
58 many_as[idx].m_amp_style = static_cast<AlignStack::StarStyle>(options::align_var_def_amp_style());
59 }
60
61 size_t comma_count = 0;
62 size_t chunk_count = 0;
63 chunk_t *pc = start;
64
65 while ((pc = chunk_get_next(pc)) != nullptr)
66 {
67 chunk_count++;
68 LOG_FMT(LFLPAREN, "%s(%d): orig_line is %zu, orig_col is %zu, text() is '%s', type is %s\n",
69 __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text(),
70 get_token_name(pc->type));
71
72 if (chunk_is_token(pc, CT_FUNC_VAR)) // Issue #2278
73 {
74 // look after 'protect parenthesis'
75 chunk_t *after = chunk_get_next_nc(pc);
76
77 if (chunk_is_token(after, CT_PAREN_CLOSE))
78 {
79 chunk_t *before = chunk_get_prev_type(after, CT_PAREN_OPEN, after->level);
80
81 if (before != nullptr)
82 {
83 // these are 'protect parenthesis'
84 // change the types and the level
85 set_chunk_type(before, CT_PPAREN_OPEN);
86 set_chunk_type(after, CT_PPAREN_CLOSE);
87 pc->level = before->level;
88 chunk_t *tmp = chunk_get_prev_nc(pc);
89
90 if (chunk_is_token(tmp, CT_PTR_TYPE))
91 {
92 tmp->level = before->level;
93 }
94 }
95 }
96 }
97
98 if (chunk_is_newline(pc))
99 {
100 comma_count = 0;
101 chunk_count = 0;
102 many_as[pc->level].NewLines(pc->nl_count);
103 }
104 else if (pc->level <= start->level)
105 {
106 break;
107 }
108 else if (pc->flags.test(PCF_VAR_DEF))
109 {
110 if (chunk_count > 1)
111 {
112 if (pc->level > HOW_MANY_AS)
113 {
114 fprintf(stderr, "%s(%d): Not enought memory for Stack\n",
115 __func__, __LINE__);
116 fprintf(stderr, "%s(%d): the current maximum is %zu\n",
117 __func__, __LINE__, HOW_MANY_AS);
118 log_flush(true);
119 exit(EX_SOFTWARE);
120 }
121 max_level_is = max(max_level_is, pc->level);
122 many_as[pc->level].Add(pc);
123 }
124 }
125 else if (comma_count > 0)
126 {
127 if (!chunk_is_comment(pc))
128 {
129 comma_count = 2;
130 break;
131 }
132 }
133 else if (chunk_is_token(pc, CT_COMMA))
134 {
135 if (pc->flags.test(PCF_IN_TEMPLATE)) // Issue #2757
136 {
137 LOG_FMT(LFLPAREN, "%s(%d): comma is in template\n",
138 __func__, __LINE__);
139 }
140 else
141 {
142 chunk_t *tmp_prev = chunk_get_prev_nc(pc);
143
144 if (!chunk_is_newline(tmp_prev)) // don't count leading commas
145 {
146 comma_count++;
147 LOG_FMT(LFLPAREN, "%s(%d): comma_count is %zu\n",
148 __func__, __LINE__, comma_count);
149 }
150 }
151 }
152 }
153
154 if (comma_count <= 1)
155 {
156 for (size_t idx = 1; idx <= max_level_is; idx++)
157 {
158 many_as[idx].End();
159 }
160 }
161 return(pc);
162 } // align_func_param
163
164
align_func_params(void)165 void align_func_params(void)
166 {
167 LOG_FUNC_ENTRY();
168 chunk_t *pc = chunk_get_head();
169
170 while ((pc = chunk_get_next(pc)) != nullptr)
171 {
172 LOG_FMT(LFLPAREN, "%s(%d): orig_line is %zu, orig_col is %zu, text() is '%s', parent_type is %s, parent_type is %s\n",
173 __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text(),
174 get_token_name(pc->type), get_token_name(pc->parent_type));
175
176 if ( chunk_is_not_token(pc, CT_FPAREN_OPEN)
177 || ( get_chunk_parent_type(pc) != CT_FUNC_PROTO
178 && get_chunk_parent_type(pc) != CT_FUNC_DEF
179 && get_chunk_parent_type(pc) != CT_FUNC_CLASS_PROTO
180 && get_chunk_parent_type(pc) != CT_FUNC_CLASS_DEF
181 && get_chunk_parent_type(pc) != CT_TYPEDEF))
182 {
183 continue;
184 }
185 // We are on a open parenthesis of a prototype
186 pc = align_func_param(pc);
187 }
188 } // void align_func_params
189