You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4005 lines
126 KiB
4005 lines
126 KiB
/**
|
|
* @file space.cpp
|
|
* Adds or removes inter-chunk spaces.
|
|
*
|
|
* Information
|
|
* "Ignore" means do not change it.
|
|
* "Add" in the context of spaces means make sure there is at least 1.
|
|
* "Add" elsewhere means make sure one is present.
|
|
* "Remove" mean remove the space/brace/newline/etc.
|
|
* "Force" in the context of spaces means ensure that there is exactly 1.
|
|
* "Force" in other contexts means the same as "add".
|
|
*
|
|
* Rmk: spaces = space + nl
|
|
*
|
|
* @author Ben Gardner
|
|
* @author Guy Maurel, 2015-2023
|
|
* @license GPL v2+
|
|
*/
|
|
|
|
#include "space.h"
|
|
|
|
#include "add_space_table.h"
|
|
#include "log_rules.h"
|
|
#include "options_for_QT.h"
|
|
#include "punctuators.h"
|
|
|
|
#ifdef WIN32
|
|
#include <algorithm> // to get max
|
|
#endif // ifdef WIN32
|
|
|
|
using namespace std;
|
|
using namespace uncrustify;
|
|
|
|
|
|
/**
|
|
* Ensure to force the space between the \a first and the \a second chunks
|
|
* if the PCF_FORCE_SPACE flag is set in the \a first.
|
|
*
|
|
* @param first The first chunk
|
|
* @param second The second chunk
|
|
* @param av Av from the do_space()
|
|
*
|
|
* @return IARF_IGNORE, IARF_ADD, IARF_REMOVE or IARF_FORCE
|
|
*/
|
|
static iarf_e ensure_force_space(Chunk *first, Chunk *second, iarf_e av);
|
|
|
|
|
|
bool token_is_within_trailing_return(Chunk *pc)
|
|
{
|
|
// look back for '->' type is TRAILING_RET
|
|
// until CT_FPAREN_CLOSE
|
|
// or CT_FPAREN_OPEN is found
|
|
Chunk *prev = pc;
|
|
|
|
while (prev->IsNotNullChunk())
|
|
{
|
|
if (prev->Is(CT_TRAILING_RET))
|
|
{
|
|
return(true);
|
|
}
|
|
else if ( prev->Is(CT_FPAREN_CLOSE)
|
|
|| prev->Is(CT_FPAREN_OPEN)
|
|
|| prev->Is(CT_SEMICOLON)) // Issue #4080
|
|
{
|
|
return(false);
|
|
}
|
|
else
|
|
{
|
|
prev = prev->GetPrev();
|
|
}
|
|
}
|
|
return(false);
|
|
} // token_is_within_trailing_return
|
|
|
|
|
|
/**
|
|
* Decides how to change inter-chunk spacing.
|
|
* Note that the order of the if statements is VERY important.
|
|
*
|
|
* @param first The first chunk
|
|
* @param second The second chunk
|
|
*
|
|
* @return IARF_IGNORE, IARF_ADD, IARF_REMOVE or IARF_FORCE
|
|
*
|
|
* This function is called for every chunk in the input file,
|
|
* thus it is important to keep this function efficient
|
|
*/
|
|
static iarf_e do_space(Chunk *first, Chunk *second, int &min_sp)
|
|
{
|
|
LOG_FUNC_ENTRY();
|
|
|
|
LOG_FMT(LSPACE, "%s(%d): orig line %zu, orig col %zu, first text '%s', type %s\n",
|
|
__func__, __LINE__, first->GetOrigLine(), first->GetOrigCol(), first->Text(), get_token_name(first->GetType()));
|
|
|
|
min_sp = 1;
|
|
|
|
if ( first->Is(CT_VBRACE_OPEN)
|
|
&& first->GetPrev()->Is(CT_SPAREN_CLOSE)
|
|
&& second->IsNot(CT_SEMICOLON))
|
|
{
|
|
// Add or remove space after ')' of control statements.
|
|
log_rule("sp_after_sparen");
|
|
return(options::sp_after_sparen());
|
|
}
|
|
|
|
if (first->Is(CT_SPAREN_CLOSE))
|
|
{
|
|
if (second->Is(CT_VBRACE_OPEN))
|
|
{
|
|
// Fix spacing between SPAREN_CLOSE and VBRACE_OPEN tokens as we don't want the default behavior (which is ADD).
|
|
log_rule("REMOVE");
|
|
return(IARF_REMOVE);
|
|
}
|
|
|
|
if ( options::sp_sparen_brace() == IARF_IGNORE
|
|
&& second->Is(CT_BRACE_OPEN))
|
|
{
|
|
// Do sp_after_sparen if sp_sparen_brace is ignored. No need for VBRACE_OPEN spacing.
|
|
log_rule("sp_after_sparen");
|
|
return(options::sp_after_sparen());
|
|
}
|
|
}
|
|
|
|
if ( first->Is(CT_PP_IGNORE)
|
|
&& second->Is(CT_PP_IGNORE))
|
|
{
|
|
// Leave spacing alone between PP_IGNORE tokens as we don't want the default behavior (which is ADD).
|
|
log_rule("PP_IGNORE");
|
|
return(IARF_IGNORE);
|
|
}
|
|
|
|
if ( first->Is(CT_PP)
|
|
|| second->Is(CT_PP))
|
|
{
|
|
// Add or remove space around preprocessor '##' concatenation operator.
|
|
log_rule("sp_pp_concat");
|
|
return(options::sp_pp_concat());
|
|
}
|
|
|
|
if (first->Is(CT_POUND))
|
|
{
|
|
// Add or remove space after preprocessor '#' stringify operator.
|
|
// Also affects the '#@' charizing operator.
|
|
log_rule("sp_pp_stringify");
|
|
return(options::sp_pp_stringify());
|
|
}
|
|
|
|
if ( second->Is(CT_POUND)
|
|
&& second->TestFlags(PCF_IN_PREPROC)
|
|
&& first->GetParentType() != CT_MACRO_FUNC)
|
|
{
|
|
// Add or remove space before preprocessor '#' stringify operator
|
|
// as in '#define x(y) L#y'.
|
|
log_rule("sp_before_pp_stringify");
|
|
return(options::sp_before_pp_stringify());
|
|
}
|
|
|
|
if ( first->Is(CT_SPACE)
|
|
|| second->Is(CT_SPACE))
|
|
{
|
|
log_rule("REMOVE");
|
|
return(IARF_REMOVE);
|
|
}
|
|
|
|
if (first->Is(CT_DECLSPEC)) // Issue 1289
|
|
{
|
|
log_rule("REMOVE");
|
|
return(IARF_REMOVE);
|
|
}
|
|
|
|
if ( second->Is(CT_NEWLINE)
|
|
|| second->Is(CT_VBRACE_OPEN))
|
|
{
|
|
log_rule("REMOVE");
|
|
return(IARF_REMOVE);
|
|
}
|
|
|
|
if ( first->Is(CT_VBRACE_OPEN)
|
|
&& second->IsNot(CT_NL_CONT)
|
|
&& second->IsNot(CT_SEMICOLON)) // # Issue 1158
|
|
{
|
|
log_rule("FORCE");
|
|
return(IARF_FORCE);
|
|
}
|
|
|
|
if ( first->Is(CT_VBRACE_CLOSE)
|
|
&& second->IsNot(CT_NL_CONT))
|
|
{
|
|
log_rule("REMOVE");
|
|
return(IARF_REMOVE);
|
|
}
|
|
|
|
if (second->Is(CT_VSEMICOLON))
|
|
{
|
|
log_rule("REMOVE");
|
|
return(IARF_REMOVE);
|
|
}
|
|
|
|
if (first->Is(CT_MACRO_FUNC))
|
|
{
|
|
log_rule("REMOVE");
|
|
return(IARF_REMOVE);
|
|
}
|
|
|
|
if (second->Is(CT_NL_CONT))
|
|
{
|
|
// Add or remove space before a backslash-newline at the end of a line.
|
|
log_rule("sp_before_nl_cont");
|
|
return(options::sp_before_nl_cont());
|
|
}
|
|
|
|
if ( language_is_set(LANG_D)
|
|
&& ( first->Is(CT_D_ARRAY_COLON)
|
|
|| second->Is(CT_D_ARRAY_COLON)))
|
|
{
|
|
// (D) Add or remove around the D named array initializer ':' operator.
|
|
log_rule("sp_d_array_colon");
|
|
return(options::sp_d_array_colon());
|
|
}
|
|
|
|
if ( first->Is(CT_CASE)
|
|
&& (( CharTable::IsKw1(second->GetStr()[0])
|
|
|| second->Is(CT_NUMBER))))
|
|
{
|
|
// Fix the spacing between 'case' and the label. Only 'ignore' and 'force' make
|
|
// sense here.
|
|
log_rule("sp_case_label");
|
|
return(options::sp_case_label() | IARF_ADD);
|
|
}
|
|
|
|
if (first->Is(CT_FOR_COLON))
|
|
{
|
|
// java
|
|
// Add or remove space after ':' in a Java/C++11 range-based 'for',
|
|
// as in 'for (Type var : expr)'.
|
|
log_rule("sp_after_for_colon");
|
|
return(options::sp_after_for_colon());
|
|
}
|
|
|
|
if (second->Is(CT_FOR_COLON))
|
|
{
|
|
// java
|
|
// Add or remove space before ':' in a Java/C++11 range-based 'for',
|
|
// as in 'for (Type var : expr)'.
|
|
log_rule("sp_before_for_colon");
|
|
return(options::sp_before_for_colon());
|
|
}
|
|
|
|
if ( first->Is(CT_QUESTION)
|
|
&& second->Is(CT_COND_COLON))
|
|
{
|
|
// In the abbreviated ternary form '(a ?: b)', add or remove space between '?'
|
|
// and ':'.
|
|
// Overrides all other sp_cond_* options.
|
|
log_rule("sp_cond_ternary_short");
|
|
return(options::sp_cond_ternary_short());
|
|
}
|
|
|
|
if ( first->Is(CT_QUESTION) // see the tests cpp:34513-34516
|
|
|| second->Is(CT_QUESTION))
|
|
{
|
|
if ( second->Is(CT_QUESTION)
|
|
&& (options::sp_cond_question_before() != IARF_IGNORE))
|
|
{
|
|
// Add or remove space before the '?' in 'b ? t : f'.
|
|
// Overrides sp_cond_question.
|
|
log_rule("sp_cond_question_before");
|
|
return(options::sp_cond_question_before());
|
|
}
|
|
|
|
if ( first->Is(CT_QUESTION)
|
|
&& (options::sp_cond_question_after() != IARF_IGNORE))
|
|
{
|
|
// Add or remove space after the '?' in 'b ? t : f'.
|
|
// Overrides sp_cond_question.
|
|
log_rule("sp_cond_question_after");
|
|
return(options::sp_cond_question_after());
|
|
}
|
|
log_rule("sp_cond_question");
|
|
return(options::sp_cond_question());
|
|
}
|
|
|
|
if ( first->Is(CT_COND_COLON)
|
|
|| second->Is(CT_COND_COLON))
|
|
{
|
|
if ( second->Is(CT_COND_COLON)
|
|
&& (options::sp_cond_colon_before() != IARF_IGNORE))
|
|
{
|
|
// Add or remove space before the ':' in 'b ? t : f'.
|
|
// Overrides sp_cond_colon.
|
|
log_rule("sp_cond_colon_before");
|
|
return(options::sp_cond_colon_before());
|
|
}
|
|
|
|
if ( first->Is(CT_COND_COLON)
|
|
&& (options::sp_cond_colon_after() != IARF_IGNORE))
|
|
{
|
|
// Add or remove space after the ':' in 'b ? t : f'.
|
|
// Overrides sp_cond_colon.
|
|
log_rule("sp_cond_colon_after");
|
|
return(options::sp_cond_colon_after());
|
|
}
|
|
// Issue #2596
|
|
// replace "if (first->Is(CT_WORD) && second->Is(CT_COND_COLON))"
|
|
// Add or remove space around the ':' in 'b ? t : f'.
|
|
log_rule("sp_cond_colon");
|
|
return(options::sp_cond_colon());
|
|
}
|
|
|
|
if ( language_is_set(LANG_D)
|
|
&& ( first->Is(CT_RANGE)
|
|
|| second->Is(CT_RANGE)))
|
|
{
|
|
// (D) Add or remove space around the D '..' operator.
|
|
log_rule("sp_range");
|
|
return(options::sp_range());
|
|
}
|
|
|
|
if ( first->Is(CT_COLON)
|
|
&& first->GetParentType() == CT_SQL_EXEC)
|
|
{
|
|
log_rule("REMOVE");
|
|
return(IARF_REMOVE);
|
|
}
|
|
|
|
// Macro stuff can only return IGNORE, ADD, or FORCE
|
|
if (first->Is(CT_MACRO))
|
|
{
|
|
// Add or remove space between a macro name and its definition.
|
|
log_rule("sp_macro");
|
|
iarf_e arg = options::sp_macro();
|
|
return(arg | ((arg != IARF_IGNORE) ? IARF_ADD : IARF_IGNORE));
|
|
}
|
|
|
|
if ( first->Is(CT_FPAREN_CLOSE)
|
|
&& first->GetParentType() == CT_MACRO_FUNC)
|
|
{
|
|
// Add or remove space between a macro function ')' and its definition.
|
|
log_rule("sp_macro_func");
|
|
iarf_e arg = options::sp_macro_func();
|
|
return(arg | ((arg != IARF_IGNORE) ? IARF_ADD : IARF_IGNORE));
|
|
}
|
|
|
|
if (first->Is(CT_PREPROC))
|
|
{
|
|
// Remove spaces, unless we are ignoring. See indent_preproc()
|
|
log_rule("pp_space_after");
|
|
|
|
if (options::pp_space_after() == IARF_IGNORE)
|
|
{
|
|
log_rule("IGNORE");
|
|
return(IARF_IGNORE);
|
|
}
|
|
log_rule("REMOVE");
|
|
return(IARF_REMOVE);
|
|
}
|
|
|
|
if (second->Is(CT_PREPROC))
|
|
{
|
|
// Remove spaces, unless we are ignoring. See indent_preproc()
|
|
log_rule("pp_indent");
|
|
|
|
if (options::pp_indent() == IARF_IGNORE)
|
|
{
|
|
log_rule("IGNORE");
|
|
return(IARF_IGNORE);
|
|
}
|
|
log_rule("REMOVE");
|
|
return(IARF_REMOVE);
|
|
}
|
|
|
|
if (second->Is(CT_SEMICOLON)) // see the tests cpp:34517-34519
|
|
{
|
|
if (first->Is(CT_VBRACE_OPEN))
|
|
{
|
|
// Add or remove space before ';'.
|
|
log_rule("sp_before_semi");
|
|
return(options::sp_before_semi());
|
|
}
|
|
|
|
// Issue #4094-03
|
|
if (second->GetParentType() == CT_FOR)
|
|
{
|
|
if (first->Is(CT_SPAREN_OPEN))
|
|
{
|
|
// empty, e.g. for (;;)
|
|
// ^ is first
|
|
// ^ is second
|
|
// Add or remove space before a semicolon of an empty left part of a for statement.
|
|
log_rule("sp_before_semi_for_empty");
|
|
return(options::sp_before_semi_for_empty());
|
|
}
|
|
|
|
if (first->Is(CT_SEMICOLON))
|
|
{
|
|
// empty, e.g. for (;;)
|
|
// ^ is first
|
|
// ^ is second
|
|
// Add or remove space between semicolons of an empty middle part of a for statement.
|
|
log_rule("sp_between_semi_for_empty");
|
|
return(options::sp_between_semi_for_empty());
|
|
}
|
|
// Add or remove space before ';' in non-empty 'for' statements.
|
|
log_rule("sp_before_semi_for");
|
|
return(options::sp_before_semi_for());
|
|
}
|
|
iarf_e arg = options::sp_before_semi(); // see the tests cpp:34517-34519
|
|
|
|
if ( first->Is(CT_VBRACE_OPEN) // Issue #2942
|
|
&& first->GetPrev()->Is(CT_SPAREN_CLOSE)
|
|
&& first->GetParentType() != CT_WHILE_OF_DO)
|
|
{
|
|
// Add or remove space before empty statement ';' on 'if', 'for' and 'while'.
|
|
log_rule("sp_special_semi");
|
|
arg = arg | options::sp_special_semi();
|
|
}
|
|
else
|
|
{
|
|
// Add or remove space before ';'.
|
|
log_rule("sp_before_semi");
|
|
}
|
|
return(arg);
|
|
}
|
|
|
|
if ( ( second->Is(CT_COMMENT)
|
|
|| second->Is(CT_COMMENT_CPP))
|
|
&& ( first->Is(CT_PP_ELSE)
|
|
|| first->Is(CT_PP_ENDIF)))
|
|
{
|
|
if (second->Is(CT_COMMENT_CPP))
|
|
{
|
|
second->SetType(CT_COMMENT_CPP_ENDIF);
|
|
}
|
|
else
|
|
{
|
|
second->SetType(CT_COMMENT_ENDIF);
|
|
}
|
|
// Add or remove space between #else or #endif and a trailing comment.
|
|
log_rule("sp_endif_cmt");
|
|
return(options::sp_endif_cmt());
|
|
}
|
|
|
|
if ( options::sp_before_tr_cmt() != IARF_IGNORE
|
|
&& second->GetParentType() == CT_COMMENT_END)
|
|
{
|
|
// Add or remove space before a trailing comment.
|
|
// Number of spaces before a trailing comment.
|
|
log_rule("sp_num_before_tr_cmt");
|
|
min_sp = options::sp_num_before_tr_cmt();
|
|
return(options::sp_before_tr_cmt());
|
|
}
|
|
|
|
if (second->GetParentType() == CT_COMMENT_END)
|
|
{
|
|
switch (second->GetOrigPrevSp())
|
|
{
|
|
case 0:
|
|
log_rule("orig prev sp - REMOVE");
|
|
return(IARF_REMOVE);
|
|
|
|
case 1:
|
|
log_rule("orig prev sp - FORCE");
|
|
return(IARF_FORCE);
|
|
|
|
default:
|
|
log_rule("orig prev sp - ADD");
|
|
return(IARF_ADD);
|
|
}
|
|
}
|
|
|
|
// Issue #4094-05
|
|
// "for (;;)" vs. "for (;; )" and "for (a;b;c)" vs. "for (a; b; c)"
|
|
if (first->Is(CT_SEMICOLON)) // see the tests cpp:34517-34519
|
|
{
|
|
if (first->GetParentType() == CT_FOR)
|
|
{
|
|
if (second->Is(CT_SPAREN_CLOSE))
|
|
{
|
|
// Add or remove space after the final semicolon of an empty part of a for
|
|
// statement, as in 'for ( ; ; <here> )'.
|
|
log_rule("sp_after_semi_for_empty");
|
|
return(options::sp_after_semi_for_empty());
|
|
}
|
|
|
|
if (second->IsNot(CT_SPAREN_CLOSE)) // Issue 1324
|
|
{
|
|
// Add or remove space after ';' in non-empty 'for' statements.
|
|
log_rule("sp_after_semi_for");
|
|
return(options::sp_after_semi_for());
|
|
}
|
|
}
|
|
else if ( !second->IsComment()
|
|
&& second->IsNot(CT_BRACE_CLOSE)) // issue #197
|
|
{
|
|
// Add or remove space after ';', except when followed by a comment.
|
|
// see the tests cpp:34517-34519
|
|
log_rule("sp_after_semi");
|
|
return(options::sp_after_semi());
|
|
}
|
|
// Let the comment spacing rules handle this
|
|
}
|
|
|
|
// puts a space in the rare '+-' or '-+'
|
|
if ( ( first->Is(CT_NEG)
|
|
|| first->Is(CT_POS)
|
|
|| first->Is(CT_ARITH)
|
|
|| first->Is(CT_SHIFT))
|
|
&& ( second->Is(CT_NEG)
|
|
|| second->Is(CT_POS)
|
|
|| second->Is(CT_ARITH)
|
|
|| second->Is(CT_SHIFT)))
|
|
{
|
|
log_rule("ADD");
|
|
return(IARF_ADD);
|
|
}
|
|
|
|
// "return(a);" vs. "return (foo_t)a + 3;" vs. "return a;" vs. "return;"
|
|
if (first->Is(CT_RETURN))
|
|
{
|
|
if ( second->Is(CT_PAREN_OPEN)
|
|
&& second->GetParentType() == CT_RETURN)
|
|
{
|
|
// Add or remove space between 'return' and '('.
|
|
log_rule("sp_return_paren");
|
|
return(options::sp_return_paren());
|
|
}
|
|
else if ( second->Is(CT_BRACE_OPEN)
|
|
&& second->GetParentType() == CT_BRACED_INIT_LIST)
|
|
{
|
|
// Add or remove space between 'return' and '{'.
|
|
log_rule("sp_return_brace");
|
|
return(options::sp_return_brace());
|
|
}
|
|
// Everything else requires a space
|
|
// The value REMOVE will be overridden with FORCE
|
|
log_rule("sp_return");
|
|
|
|
if (options::sp_return() == IARF_REMOVE)
|
|
{
|
|
return(IARF_FORCE);
|
|
}
|
|
return(options::sp_return());
|
|
}
|
|
|
|
// "sizeof(foo_t)" vs. "sizeof (foo_t)"
|
|
if (first->Is(CT_SIZEOF))
|
|
{
|
|
if (second->Is(CT_PAREN_OPEN))
|
|
{
|
|
// Add or remove space between 'sizeof' and '('.
|
|
log_rule("sp_sizeof_paren");
|
|
return(options::sp_sizeof_paren());
|
|
}
|
|
|
|
if (second->Is(CT_ELLIPSIS))
|
|
{
|
|
// Add or remove space between 'sizeof' and '...'.
|
|
log_rule("sp_sizeof_ellipsis");
|
|
return(options::sp_sizeof_ellipsis());
|
|
}
|
|
log_rule("FORCE");
|
|
return(IARF_FORCE);
|
|
}
|
|
|
|
// "decltype(foo_t)" vs. "decltype (foo_t)"
|
|
if (first->Is(CT_DECLTYPE))
|
|
{
|
|
if (second->Is(CT_PAREN_OPEN))
|
|
{
|
|
// Add or remove space between 'decltype' and '('.
|
|
log_rule("sp_decltype_paren");
|
|
return(options::sp_decltype_paren());
|
|
}
|
|
log_rule("FORCE");
|
|
return(IARF_FORCE);
|
|
}
|
|
|
|
// handle '::'
|
|
if (first->Is(CT_DC_MEMBER))
|
|
{
|
|
// Add or remove space after the '::' operator.
|
|
log_rule("sp_after_dc");
|
|
return(options::sp_after_dc());
|
|
}
|
|
|
|
// Issue #889
|
|
// mapped_file_source abc((int) ::CW2A(sTemp));
|
|
if ( first->Is(CT_PAREN_CLOSE)
|
|
&& second->Is(CT_DC_MEMBER)
|
|
&& second->GetNext()->GetType() == CT_FUNC_CALL)
|
|
{
|
|
log_rule("sp_after_cast");
|
|
return(options::sp_after_cast());
|
|
}
|
|
|
|
if (second->Is(CT_DC_MEMBER))
|
|
{
|
|
/* '::' at the start of an identifier is not member access, but global scope operator.
|
|
* Detect if previous chunk is keyword
|
|
*/
|
|
switch (first->GetType())
|
|
{
|
|
case CT_SBOOL:
|
|
case CT_SASSIGN:
|
|
case CT_ARITH:
|
|
case CT_SHIFT:
|
|
case CT_CASE:
|
|
case CT_CLASS:
|
|
case CT_DELETE:
|
|
case CT_FRIEND:
|
|
case CT_NAMESPACE:
|
|
case CT_NEW:
|
|
case CT_SARITH:
|
|
case CT_SCOMPARE:
|
|
case CT_OPERATOR:
|
|
case CT_ACCESS:
|
|
case CT_QUALIFIER:
|
|
case CT_RETURN:
|
|
case CT_SIZEOF:
|
|
case CT_DECLTYPE:
|
|
case CT_STRUCT:
|
|
case CT_THROW:
|
|
case CT_TYPEDEF:
|
|
case CT_TYPENAME:
|
|
case CT_UNION:
|
|
case CT_USING:
|
|
log_rule("FORCE");
|
|
return(IARF_FORCE);
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if ( ( first->Is(CT_WORD)
|
|
|| first->Is(CT_TYPE)
|
|
|| first->Is(CT_PAREN_CLOSE)
|
|
|| CharTable::IsKw1(first->GetStr()[0]))
|
|
&& (strcmp(first->Text(), "void") != 0)) // Issue 1249
|
|
{
|
|
// Add or remove space before the '::' operator.
|
|
log_rule("sp_before_dc");
|
|
return(options::sp_before_dc());
|
|
}
|
|
}
|
|
|
|
// "a,b" vs. "a, b"
|
|
if (first->Is(CT_COMMA)) // see the tests cpp:34520-34524
|
|
// see the tests c-sharp:12200-12202
|
|
{
|
|
if ( language_is_set(LANG_CS | LANG_VALA)
|
|
&& first->GetParentType() == CT_TYPE)
|
|
{
|
|
// (C#, Vala) multidimensional array type: ',,' vs. ', ,' or ',]' vs. ', ]'
|
|
if (second->Is(CT_COMMA))
|
|
{
|
|
// (C#, Vala) Add or remove space between ',' in multidimensional array type
|
|
// like 'int[,,]'.
|
|
log_rule("sp_between_mdatype_commas");
|
|
return(options::sp_between_mdatype_commas());
|
|
}
|
|
// (C#, Vala) Add or remove space between ',' and ']' in multidimensional array type
|
|
// like 'int[,,]'.
|
|
log_rule("sp_after_mdatype_commas");
|
|
return(options::sp_after_mdatype_commas());
|
|
}
|
|
|
|
// Fix for issue #1243
|
|
// Don't add extra space after comma immediately followed by Angle close
|
|
if (second->Is(CT_ANGLE_CLOSE))
|
|
{
|
|
log_rule("IGNORE");
|
|
return(IARF_IGNORE);
|
|
}
|
|
// Add or remove space after ',', i.e. 'a,b' vs. 'a, b'.
|
|
log_rule("sp_after_comma");
|
|
return(options::sp_after_comma());
|
|
}
|
|
|
|
// test if we are within a SIGNAL/SLOT call
|
|
if (QT_SIGNAL_SLOT_found)
|
|
{
|
|
if ( first->Is(CT_FPAREN_CLOSE)
|
|
&& ( second->Is(CT_FPAREN_CLOSE)
|
|
|| second->Is(CT_COMMA)))
|
|
{
|
|
if (second->GetLevel() == QT_SIGNAL_SLOT_level)
|
|
{
|
|
restoreValues = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (second->Is(CT_COMMA))
|
|
{
|
|
if ( language_is_set(LANG_CS | LANG_VALA)
|
|
&& first->Is(CT_SQUARE_OPEN)
|
|
&& first->GetParentType() == CT_TYPE)
|
|
{
|
|
// (C#, Vala) Add or remove space between '[' and ',' in multidimensional array type
|
|
// like 'int[,,]'.
|
|
log_rule("sp_before_mdatype_commas");
|
|
return(options::sp_before_mdatype_commas());
|
|
}
|
|
|
|
if ( first->Is(CT_PAREN_OPEN)
|
|
|| first->Is(CT_FPAREN_OPEN))
|
|
{
|
|
// Add or remove space between an open parenthesis and comma,
|
|
// i.e. '(,' vs. '( ,'.
|
|
log_rule("sp_paren_comma");
|
|
return(options::sp_paren_comma());
|
|
}
|
|
// Add or remove space before ',', i.e. 'a,b' vs. 'a ,b'.
|
|
log_rule("sp_before_comma");
|
|
return(options::sp_before_comma());
|
|
}
|
|
|
|
if (second->Is(CT_ELLIPSIS))
|
|
{
|
|
// type followed by a ellipsis
|
|
Chunk *tmp = first;
|
|
|
|
if ( tmp->Is(CT_PTR_TYPE)
|
|
|| tmp->Is(CT_BYREF))
|
|
{
|
|
tmp = tmp->GetPrevNcNnl();
|
|
}
|
|
|
|
if ( tmp->Is(CT_TYPE)
|
|
|| tmp->Is(CT_QUALIFIER))
|
|
{
|
|
// Add or remove space between a type and '...'.
|
|
log_rule("sp_type_ellipsis");
|
|
return(options::sp_type_ellipsis());
|
|
}
|
|
|
|
// non-punc followed by a ellipsis
|
|
if ( !first->TestFlags(PCF_PUNCTUATOR)
|
|
&& (options::sp_before_ellipsis() != IARF_IGNORE))
|
|
{
|
|
// Add or remove space before the variadic '...' when preceded by a
|
|
// non-punctuator.
|
|
log_rule("sp_before_ellipsis");
|
|
return(options::sp_before_ellipsis());
|
|
}
|
|
|
|
if ( first->Is(CT_FPAREN_CLOSE)
|
|
|| first->Is(CT_PAREN_CLOSE))
|
|
{
|
|
// Add or remove space between ')' and '...'.
|
|
log_rule("sp_paren_ellipsis");
|
|
return(options::sp_paren_ellipsis());
|
|
}
|
|
|
|
if (first->Is(CT_TAG_COLON))
|
|
{
|
|
log_rule("FORCE");
|
|
return(IARF_FORCE);
|
|
}
|
|
|
|
if (first->Is(CT_BYREF)) // Issue #3309
|
|
{
|
|
log_rule("sp_byref_ellipsis");
|
|
return(options::sp_byref_ellipsis());
|
|
}
|
|
|
|
if (first->Is(CT_PARAMETER_PACK)) // Issue #3309
|
|
{
|
|
log_rule("sp_parameter_pack_ellipsis");
|
|
return(options::sp_parameter_pack_ellipsis());
|
|
}
|
|
}
|
|
|
|
if (first->Is(CT_ELLIPSIS))
|
|
{
|
|
if (second->Is(CT_PARAMETER_PACK)) // Issue #3309
|
|
{
|
|
log_rule("sp_ellipsis_parameter_pack");
|
|
return(options::sp_ellipsis_parameter_pack());
|
|
}
|
|
|
|
if (CharTable::IsKw1(second->GetStr()[0]))
|
|
{
|
|
log_rule("FORCE");
|
|
return(IARF_FORCE);
|
|
}
|
|
|
|
if ( second->Is(CT_PAREN_OPEN)
|
|
&& first->GetPrev()->Is(CT_SIZEOF))
|
|
{
|
|
// Add or remove space between 'sizeof...' and '('.
|
|
log_rule("sp_sizeof_ellipsis_paren");
|
|
return(options::sp_sizeof_ellipsis_paren());
|
|
}
|
|
}
|
|
|
|
if ( language_is_set(LANG_PAWN)
|
|
&& first->Is(CT_TAG_COLON))
|
|
{
|
|
// (Pawn) Add or remove space after the tag keyword.
|
|
log_rule("sp_after_tag");
|
|
return(options::sp_after_tag());
|
|
}
|
|
|
|
if (second->Is(CT_TAG_COLON))
|
|
{
|
|
log_rule("REMOVE");
|
|
return(IARF_REMOVE);
|
|
}
|
|
|
|
// handle '~'
|
|
if (first->Is(CT_DESTRUCTOR))
|
|
{
|
|
log_rule("REMOVE");
|
|
return(IARF_REMOVE);
|
|
}
|
|
|
|
if ( language_is_set(LANG_OC)
|
|
&& first->Is(CT_CATCH)
|
|
&& second->Is(CT_SPAREN_OPEN)
|
|
&& (options::sp_oc_catch_paren() != IARF_IGNORE))
|
|
{
|
|
// (OC) Add or remove space between '@catch' and '('
|
|
// in '@catch (something) { }'. If set to ignore, sp_catch_paren is used.
|
|
log_rule("sp_oc_catch_paren");
|
|
return(options::sp_oc_catch_paren());
|
|
}
|
|
|
|
if ( language_is_set(LANG_OC)
|
|
&& ( first->Is(CT_PAREN_CLOSE)
|
|
|| first->Is(CT_OC_CLASS)
|
|
|| first->Is(CT_WORD))
|
|
&& second->Is(CT_ANGLE_OPEN)
|
|
&& ( second->GetParentType() == CT_OC_PROTO_LIST
|
|
|| second->GetParentType() == CT_OC_GENERIC_SPEC)
|
|
&& (options::sp_before_oc_proto_list() != IARF_IGNORE))
|
|
{
|
|
// (OC) Add or remove space before Objective-C protocol list
|
|
// as in '@protocol Protocol<here><Protocol_A>' or '@interface MyClass : NSObject<here><MyProtocol>'.
|
|
log_rule("sp_before_oc_proto_list");
|
|
return(options::sp_before_oc_proto_list());
|
|
}
|
|
|
|
if ( language_is_set(LANG_OC)
|
|
&& first->Is(CT_OC_CLASS)
|
|
&& second->Is(CT_PAREN_OPEN)
|
|
&& (options::sp_oc_classname_paren() != IARF_IGNORE))
|
|
{
|
|
// (OC) Add or remove space between class name and '('
|
|
// in '@interface className(categoryName)<ProtocolName>:BaseClass'
|
|
log_rule("sp_oc_classname_paren");
|
|
return(options::sp_oc_classname_paren());
|
|
}
|
|
|
|
if ( first->Is(CT_CATCH)
|
|
&& second->Is(CT_SPAREN_OPEN)
|
|
&& (options::sp_catch_paren() != IARF_IGNORE))
|
|
{
|
|
// Add or remove space between 'catch' and '(' in 'catch (something) { }'.
|
|
// If set to ignore, sp_before_sparen is used.
|
|
log_rule("sp_catch_paren");
|
|
return(options::sp_catch_paren());
|
|
}
|
|
|
|
if ( language_is_set(LANG_D)
|
|
&& first->Is(CT_D_VERSION_IF)
|
|
&& second->Is(CT_SPAREN_OPEN)
|
|
&& (options::sp_version_paren() != IARF_IGNORE))
|
|
{
|
|
// (D) Add or remove space between 'version' and '('
|
|
// in 'version (something) { }'. If set to ignore, sp_before_sparen is used.
|
|
log_rule("sp_version_paren");
|
|
return(options::sp_version_paren());
|
|
}
|
|
|
|
if ( language_is_set(LANG_D)
|
|
&& first->Is(CT_D_SCOPE_IF)
|
|
&& second->Is(CT_SPAREN_OPEN)
|
|
&& (options::sp_scope_paren() != IARF_IGNORE))
|
|
{
|
|
// (D) Add or remove space between 'scope' and '('
|
|
// in 'scope (something) { }'. If set to ignore, sp_before_sparen is used.
|
|
log_rule("sp_scope_paren");
|
|
return(options::sp_scope_paren());
|
|
}
|
|
|
|
if ( language_is_set(LANG_OC)
|
|
&& first->Is(CT_SYNCHRONIZED)
|
|
&& second->Is(CT_SPAREN_OPEN))
|
|
{
|
|
// (OC) Add or remove space between '@synchronized' and the open parenthesis,
|
|
// i.e. '@synchronized(foo)' vs. '@synchronized (foo)'.
|
|
log_rule("sp_after_oc_synchronized");
|
|
return(options::sp_after_oc_synchronized());
|
|
}
|
|
|
|
// "if (" vs. "if("
|
|
if (second->Is(CT_SPAREN_OPEN))
|
|
{
|
|
// Add or remove space after 'do' between 'while' and '('. Issue #995
|
|
if ( first->Is(CT_WHILE_OF_DO)
|
|
&& options::sp_while_paren_open() != IARF_IGNORE)
|
|
{
|
|
log_rule("sp_while_paren_open");
|
|
return(options::sp_while_paren_open());
|
|
}
|
|
// Add or remove space before '(' of other control statements ('if', 'for',
|
|
// 'switch', 'while', etc.).
|
|
log_rule("sp_before_sparen");
|
|
return(options::sp_before_sparen());
|
|
}
|
|
|
|
if ( first->Is(CT_LAMBDA)
|
|
|| second->Is(CT_LAMBDA))
|
|
{
|
|
// Add or remove space around assignment operator '=', '+=', etc.
|
|
log_rule("sp_assign (lambda)");
|
|
return(options::sp_assign());
|
|
}
|
|
|
|
// Handle the special lambda case for C++11:
|
|
// [=](Something arg){.....}
|
|
// Add or remove space around '=' in C++11 lambda capture specifications.
|
|
// Overrides sp_assign.
|
|
if ( (options::sp_cpp_lambda_assign() != IARF_IGNORE)
|
|
&& ( ( first->Is(CT_SQUARE_OPEN)
|
|
&& first->GetParentType() == CT_CPP_LAMBDA
|
|
&& second->Is(CT_ASSIGN))
|
|
|| ( first->Is(CT_ASSIGN)
|
|
&& second->Is(CT_SQUARE_CLOSE)
|
|
&& second->GetParentType() == CT_CPP_LAMBDA)))
|
|
{
|
|
log_rule("sp_cpp_lambda_assign");
|
|
return(options::sp_cpp_lambda_assign());
|
|
}
|
|
|
|
if ( first->Is(CT_SQUARE_CLOSE)
|
|
&& first->GetParentType() == CT_CPP_LAMBDA)
|
|
{
|
|
// Handle the special lambda case for C++11:
|
|
// [](Something arg){.....}
|
|
// Add or remove space after the capture specification of a C++11 lambda when
|
|
// an argument list is present, as in '[] <here> (int x){ ... }'.
|
|
if (second->Is(CT_LPAREN_OPEN))
|
|
{
|
|
log_rule("sp_cpp_lambda_square_paren");
|
|
return(options::sp_cpp_lambda_square_paren());
|
|
}
|
|
else if (second->Is(CT_BRACE_OPEN))
|
|
{
|
|
// Add or remove space after the capture specification of a C++11 lambda with
|
|
// no argument list is present, as in '[] <here> { ... }'.
|
|
log_rule("sp_cpp_lambda_square_brace");
|
|
return(options::sp_cpp_lambda_square_brace());
|
|
}
|
|
}
|
|
|
|
if (first->Is(CT_LPAREN_OPEN))
|
|
{
|
|
if (second->Is(CT_LPAREN_CLOSE))
|
|
{
|
|
// Add or remove space after the opening parenthesis and before the closing
|
|
// parenthesis of a argument list of a C++11 lambda, as in
|
|
// '[]( <here> ){ ... }'
|
|
// with an empty list.
|
|
log_rule("sp_cpp_lambda_argument_list_empty");
|
|
return(options::sp_cpp_lambda_argument_list_empty());
|
|
}
|
|
// Add or remove space after the opening parenthesis of a argument list
|
|
// of a C++11 lambda, as in '[]( <here> int x ){ ... }'.
|
|
log_rule("sp_cpp_lambda_argument_list");
|
|
return(options::sp_cpp_lambda_argument_list());
|
|
}
|
|
|
|
if (first->Is(CT_LPAREN_CLOSE))
|
|
{
|
|
if (second->Is(CT_BRACE_OPEN))
|
|
{
|
|
// Add or remove space after the argument list of a C++11 lambda, as in
|
|
// '[](int x) <here> { ... }'.
|
|
log_rule("sp_cpp_lambda_paren_brace");
|
|
return(options::sp_cpp_lambda_paren_brace());
|
|
}
|
|
}
|
|
|
|
if (second->Is(CT_LPAREN_CLOSE))
|
|
{
|
|
// Add or remove space before the closing parenthesis of a argument list
|
|
// of a C++11 lambda, as in '[]( int x <here> ){ ... }'.
|
|
log_rule("sp_cpp_lambda_argument_list");
|
|
return(options::sp_cpp_lambda_argument_list());
|
|
}
|
|
|
|
if ( first->Is(CT_BRACE_CLOSE)
|
|
&& first->GetParentType() == CT_CPP_LAMBDA
|
|
&& second->Is(CT_FPAREN_OPEN))
|
|
{
|
|
// Add or remove space between a lambda body and its call operator of an
|
|
// immediately invoked lambda, as in '[]( ... ){ ... } <here> ( ... )'.
|
|
log_rule("sp_cpp_lambda_fparen");
|
|
return(options::sp_cpp_lambda_fparen());
|
|
}
|
|
|
|
if (first->Is(CT_ENUM))
|
|
{
|
|
if (second->Is(CT_BRACE_OPEN))
|
|
{
|
|
// Add or remove space in 'enum {'.
|
|
log_rule("sp_enum_brace");
|
|
return(options::sp_enum_brace());
|
|
}
|
|
else if (second->Is(CT_FPAREN_OPEN))
|
|
{
|
|
// Add or remove space in 'NS_ENUM ('.
|
|
log_rule("sp_enum_paren");
|
|
return(options::sp_enum_paren());
|
|
}
|
|
}
|
|
|
|
if (second->Is(CT_ASSIGN))
|
|
{
|
|
if (second->TestFlags(PCF_IN_ENUM))
|
|
{
|
|
// Add or remove space before assignment '=' in enum.
|
|
// Overrides sp_enum_assign.
|
|
if (options::sp_enum_before_assign() != IARF_IGNORE)
|
|
{
|
|
log_rule("sp_enum_before_assign");
|
|
return(options::sp_enum_before_assign());
|
|
}
|
|
// Add or remove space around assignment '=' in enum.
|
|
log_rule("sp_enum_assign");
|
|
return(options::sp_enum_assign());
|
|
}
|
|
|
|
// Add or remove space around assignment operator '=' in a prototype.
|
|
// If set to ignore, use sp_assign.
|
|
if ( (options::sp_assign_default() != IARF_IGNORE)
|
|
&& second->GetParentType() == CT_FUNC_PROTO)
|
|
{
|
|
log_rule("sp_assign_default");
|
|
return(options::sp_assign_default());
|
|
}
|
|
|
|
// Add or remove space before assignment operator '=', '+=', etc.
|
|
// Overrides sp_assign.
|
|
if (options::sp_before_assign() != IARF_IGNORE)
|
|
{
|
|
log_rule("sp_before_assign");
|
|
return(options::sp_before_assign());
|
|
}
|
|
// Add or remove space around assignment operator '=', '+=', etc.
|
|
log_rule("sp_assign");
|
|
return(options::sp_assign());
|
|
}
|
|
|
|
if (second->Is(CT_ASSIGN_DEFAULT_ARG))
|
|
{
|
|
// Add or remove space around assignment operator '=' in a prototype.
|
|
// If set to ignore, use sp_assign.
|
|
if ( (options::sp_assign_default() != IARF_IGNORE)
|
|
&& second->GetParentType() == CT_FUNC_PROTO)
|
|
{
|
|
log_rule("sp_assign_default");
|
|
return(options::sp_assign_default());
|
|
}
|
|
|
|
// Add or remove space before assignment operator '=', '+=', etc.
|
|
// Overrides sp_assign.
|
|
if (options::sp_before_assign() != IARF_IGNORE)
|
|
{
|
|
log_rule("sp_before_assign");
|
|
return(options::sp_before_assign());
|
|
}
|
|
// Add or remove space around assignment operator '=', '+=', etc.
|
|
log_rule("sp_assign");
|
|
return(options::sp_assign());
|
|
}
|
|
|
|
if (first->Is(CT_ASSIGN))
|
|
{
|
|
if (first->TestFlags(PCF_IN_ENUM))
|
|
{
|
|
// Add or remove space after assignment '=' in enum.
|
|
// Overrides sp_enum_assign.
|
|
if (options::sp_enum_after_assign() != IARF_IGNORE)
|
|
{
|
|
log_rule("sp_enum_after_assign");
|
|
return(options::sp_enum_after_assign());
|
|
}
|
|
// Add or remove space around assignment '=' in enum.
|
|
log_rule("sp_enum_assign");
|
|
return(options::sp_enum_assign());
|
|
}
|
|
|
|
// Add or remove space around assignment operator '=' in a prototype.
|
|
// If set to ignore, use sp_assign.
|
|
if ( (options::sp_assign_default() != IARF_IGNORE)
|
|
&& first->GetParentType() == CT_FUNC_PROTO)
|
|
{
|
|
log_rule("sp_assign_default");
|
|
return(options::sp_assign_default());
|
|
}
|
|
|
|
// Add or remove space after assignment operator '=', '+=', etc.
|
|
// Overrides sp_assign.
|
|
if (options::sp_after_assign() != IARF_IGNORE)
|
|
{
|
|
log_rule("sp_after_assign");
|
|
return(options::sp_after_assign());
|
|
}
|
|
// Add or remove space around assignment operator '=', '+=', etc.
|
|
log_rule("sp_assign");
|
|
return(options::sp_assign());
|
|
}
|
|
|
|
if ( first->Is(CT_TRAILING_RET)
|
|
|| first->Is(CT_CPP_LAMBDA_RET)
|
|
|| second->Is(CT_TRAILING_RET)
|
|
|| second->Is(CT_CPP_LAMBDA_RET))
|
|
{
|
|
// Add or remove space around trailing return operator '->'.
|
|
log_rule("sp_trailing_return");
|
|
return(options::sp_trailing_return());
|
|
}
|
|
|
|
if (first->Is(CT_ASSIGN_DEFAULT_ARG))
|
|
{
|
|
// Add or remove space around assignment operator '=' in a prototype.
|
|
// If set to ignore, use sp_assign.
|
|
if ( (options::sp_assign_default() != IARF_IGNORE)
|
|
&& first->GetParentType() == CT_FUNC_PROTO)
|
|
{
|
|
log_rule("sp_assign_default");
|
|
return(options::sp_assign_default());
|
|
}
|
|
|
|
// Add or remove space after assignment operator '=', '+=', etc.
|
|
// Overrides sp_assign.
|
|
if (options::sp_after_assign() != IARF_IGNORE)
|
|
{
|
|
log_rule("sp_after_assign");
|
|
return(options::sp_after_assign());
|
|
}
|
|
// Add or remove space around assignment operator '=', '+=', etc.
|
|
log_rule("sp_assign");
|
|
return(options::sp_assign());
|
|
}
|
|
|
|
if (first->Is(CT_ENUM_COLON)) // Issue #4040
|
|
{
|
|
// Add or remove space around assignment ':' in enum.
|
|
log_rule("sp_enum_colon");
|
|
return(options::sp_enum_colon());
|
|
}
|
|
|
|
if (second->Is(CT_ENUM_COLON)) // Issue #4040
|
|
{
|
|
// Add or remove space around assignment ':' in enum.
|
|
log_rule("sp_enum_colon");
|
|
return(options::sp_enum_colon());
|
|
}
|
|
|
|
if (first->Is(CT_BIT_COLON)) // Issue #4040
|
|
{
|
|
// Add or remove space after a bit colon ':'.
|
|
log_rule("sp_after_bit_colon");
|
|
return(options::sp_after_bit_colon());
|
|
}
|
|
|
|
if (second->Is(CT_BIT_COLON)) // Issue #4040
|
|
{
|
|
// Add or remove space before a bit colon ':'.
|
|
log_rule("sp_before_bit_colon");
|
|
return(options::sp_before_bit_colon());
|
|
}
|
|
|
|
if ( first->Is(CT_OC_AVAILABLE_VALUE)
|
|
|| second->Is(CT_OC_AVAILABLE_VALUE))
|
|
{
|
|
log_rule("IGNORE");
|
|
return(IARF_IGNORE);
|
|
}
|
|
|
|
if (language_is_set(LANG_OC))
|
|
{
|
|
if (second->Is(CT_OC_BLOCK_CARET))
|
|
{
|
|
// (OC) Add or remove space before a block pointer caret,
|
|
// i.e. '^int (int arg){...}' vs. ' ^int (int arg){...}'.
|
|
log_rule("sp_before_oc_block_caret");
|
|
return(options::sp_before_oc_block_caret());
|
|
}
|
|
|
|
if (first->Is(CT_OC_BLOCK_CARET))
|
|
{
|
|
// (OC) Add or remove space after a block pointer caret,
|
|
// i.e. '^int (int arg){...}' vs. '^ int (int arg){...}'.
|
|
log_rule("sp_after_oc_block_caret");
|
|
return(options::sp_after_oc_block_caret());
|
|
}
|
|
|
|
if (second->Is(CT_OC_MSG_FUNC))
|
|
{
|
|
if ( (options::sp_after_oc_msg_receiver() == IARF_REMOVE)
|
|
&& ( first->IsNot(CT_SQUARE_CLOSE)
|
|
&& first->IsNot(CT_FPAREN_CLOSE)
|
|
&& first->IsNot(CT_PAREN_CLOSE)))
|
|
{
|
|
log_rule("FORCE");
|
|
return(IARF_FORCE);
|
|
}
|
|
// (OC) Add or remove space between the receiver and selector in a message,
|
|
// as in '[receiver selector ...]'.
|
|
log_rule("sp_after_oc_msg_receiver");
|
|
return(options::sp_after_oc_msg_receiver());
|
|
}
|
|
}
|
|
|
|
// c++17 structured bindings e.g., "auto [x, y, z]" vs. a[x, y, z]" or "auto const [x, y, z]" vs. "auto const[x, y, z]"
|
|
if ( language_is_set(LANG_CPP)
|
|
&& ( first->Is(CT_BYREF)
|
|
|| first->Is(CT_QUALIFIER)
|
|
|| first->Is(CT_TYPE))
|
|
&& second->Is(CT_SQUARE_OPEN)
|
|
&& second->GetParentType() != CT_OC_MSG
|
|
&& second->GetParentType() != CT_CS_SQ_STMT)
|
|
{
|
|
// Add or remove space before C++17 structured bindings.
|
|
log_rule("sp_cpp_before_struct_binding");
|
|
return(options::sp_cpp_before_struct_binding());
|
|
}
|
|
|
|
// "a [x]" vs. "a[x]"
|
|
if ( second->Is(CT_SQUARE_OPEN)
|
|
&& ( second->GetParentType() != CT_OC_MSG
|
|
&& second->GetParentType() != CT_CS_SQ_STMT
|
|
&& second->GetParentType() != CT_CPP_LAMBDA))
|
|
{
|
|
if ( second->TestFlags(PCF_IN_SPAREN)
|
|
&& (first->Is(CT_IN)))
|
|
{
|
|
log_rule("FORCE");
|
|
return(IARF_FORCE);
|
|
}
|
|
|
|
if (first->Is(CT_ASM_COLON))
|
|
{
|
|
// Add or remove space before '[' for asm block.
|
|
log_rule("sp_before_square_asm_block");
|
|
return(options::sp_before_square_asm_block());
|
|
}
|
|
|
|
if (first->TestFlags(PCF_VAR_DEF))
|
|
{
|
|
// Add or remove space before '[' for a variable definition.
|
|
log_rule("sp_before_vardef_square");
|
|
return(options::sp_before_vardef_square());
|
|
}
|
|
// Add or remove space before '[' (except '[]').
|
|
log_rule("sp_before_square");
|
|
return(options::sp_before_square());
|
|
}
|
|
|
|
// "byte[]" vs. "byte []"
|
|
if (second->Is(CT_TSQUARE))
|
|
{
|
|
// Add or remove space before '[]'.
|
|
log_rule("sp_before_squares");
|
|
return(options::sp_before_squares());
|
|
}
|
|
|
|
if ( (options::sp_angle_shift() != IARF_IGNORE)
|
|
&& first->Is(CT_ANGLE_CLOSE)
|
|
&& second->Is(CT_ANGLE_CLOSE))
|
|
{
|
|
// Add or remove space between '>' and '>' in '>>' (template stuff).
|
|
log_rule("sp_angle_shift");
|
|
return(options::sp_angle_shift());
|
|
}
|
|
|
|
// Issue #4094-01
|
|
// spacing around template < > stuff
|
|
if ( first->Is(CT_ANGLE_OPEN)
|
|
|| second->Is(CT_ANGLE_CLOSE))
|
|
{
|
|
if ( first->Is(CT_ANGLE_OPEN)
|
|
&& second->Is(CT_ANGLE_CLOSE))
|
|
{
|
|
// Add or remove space inside '<>'.
|
|
// if empty.
|
|
log_rule("sp_inside_angle_empty");
|
|
return(options::sp_inside_angle_empty());
|
|
}
|
|
// Add or remove space inside '<' and '>'.
|
|
log_rule("sp_inside_angle");
|
|
iarf_e op = options::sp_inside_angle();
|
|
|
|
// special: if we're not supporting digraphs, then we shouldn't create them!
|
|
if ( (op == IARF_REMOVE)
|
|
&& !options::enable_digraphs()
|
|
&& first->Is(CT_ANGLE_OPEN)
|
|
&& second->Is(CT_DC_MEMBER))
|
|
{
|
|
op = IARF_IGNORE;
|
|
}
|
|
return(op);
|
|
}
|
|
|
|
if (second->Is(CT_ANGLE_OPEN))
|
|
{
|
|
if ( first->Is(CT_TEMPLATE)
|
|
&& (options::sp_template_angle() != IARF_IGNORE))
|
|
{
|
|
// Add or remove space between 'template' and '<'.
|
|
// If set to ignore, sp_before_angle is used.
|
|
log_rule("sp_template_angle");
|
|
return(options::sp_template_angle());
|
|
}
|
|
|
|
if (first->IsNot(CT_QUALIFIER))
|
|
{
|
|
// Add or remove space before '<'.
|
|
log_rule("sp_before_angle");
|
|
return(options::sp_before_angle());
|
|
}
|
|
}
|
|
|
|
if (first->Is(CT_ANGLE_CLOSE))
|
|
{
|
|
if ( second->Is(CT_WORD)
|
|
|| CharTable::IsKw1(second->GetStr()[0]))
|
|
{
|
|
// Add or remove space between '>' and a word as in 'List<byte> m;' or
|
|
// 'template <typename T> static ...'.
|
|
log_rule("sp_angle_word");
|
|
return(options::sp_angle_word());
|
|
}
|
|
|
|
// Issue #4094-02
|
|
if ( second->Is(CT_FPAREN_OPEN)
|
|
|| second->Is(CT_PAREN_OPEN))
|
|
{
|
|
Chunk *next = second->GetNextNcNnl();
|
|
|
|
if (next->Is(CT_FPAREN_CLOSE))
|
|
{
|
|
// Add or remove space between '>' and '()' as found in 'new List<byte>();'.
|
|
log_rule("sp_angle_paren_empty");
|
|
return(options::sp_angle_paren_empty());
|
|
}
|
|
// Add or remove space between '>' and '(' as found in 'new List<byte>(foo);'.
|
|
log_rule("sp_angle_paren");
|
|
return(options::sp_angle_paren());
|
|
}
|
|
|
|
if (second->Is(CT_DC_MEMBER))
|
|
{
|
|
// Add or remove space before the '::' operator.
|
|
log_rule("sp_before_dc");
|
|
return(options::sp_before_dc());
|
|
}
|
|
|
|
if ( second->IsNot(CT_BYREF)
|
|
&& second->IsNot(CT_PTR_TYPE)
|
|
&& second->IsNot(CT_BRACE_OPEN)
|
|
&& second->IsNot(CT_PAREN_CLOSE))
|
|
{
|
|
if ( second->Is(CT_CLASS_COLON)
|
|
&& options::sp_angle_colon() != IARF_IGNORE)
|
|
{
|
|
// Add or remove space between '>' and ':'.
|
|
log_rule("sp_angle_colon");
|
|
return(options::sp_angle_colon());
|
|
}
|
|
|
|
// Whether sp_after_angle takes precedence over sp_inside_fparen. This was the
|
|
// historic behavior, but is probably not the desired behavior, so this is off
|
|
// by default.
|
|
if ( second->Is(CT_FPAREN_CLOSE)
|
|
&& options::sp_inside_fparen() != IARF_IGNORE
|
|
&& !options::use_sp_after_angle_always())
|
|
{
|
|
// Add or remove space between '>' and ')'.
|
|
log_rule("sp_inside_fparen");
|
|
return(options::sp_inside_fparen());
|
|
}
|
|
// Add or remove space after '>'.
|
|
log_rule("sp_after_angle");
|
|
return(options::sp_after_angle());
|
|
}
|
|
}
|
|
|
|
if (first->Is(CT_BYREF)) // see the tests cpp:34509-34512
|
|
{
|
|
if (second->Is(CT_PAREN_OPEN))
|
|
{
|
|
// Add or remove space after a reference sign '&', if followed by an open
|
|
// parenthesis, as in 'char& (*)()'.
|
|
log_rule("sp_byref_paren");
|
|
return(options::sp_byref_paren());
|
|
}
|
|
else if ( first->GetParentType() == CT_FUNC_DEF // Issue #3197, #3210
|
|
|| first->GetParentType() == CT_FUNC_PROTO)
|
|
{
|
|
// Add or remove space after a reference sign '&', if followed by a function
|
|
// prototype or function definition.
|
|
log_rule("sp_after_byref_func"); // byref 2
|
|
return(options::sp_after_byref_func());
|
|
}
|
|
else if ( CharTable::IsKw1(second->GetStr()[0])
|
|
&& ( options::sp_after_byref() != IARF_IGNORE
|
|
|| ( !second->Is(CT_FUNC_PROTO)
|
|
&& !second->Is(CT_FUNC_DEF))))
|
|
{
|
|
// Add or remove space after reference sign '&', if followed by a word.
|
|
log_rule("sp_after_byref"); // byref 1
|
|
return(options::sp_after_byref());
|
|
}
|
|
}
|
|
|
|
if ( second->Is(CT_BYREF)
|
|
&& !first->Is(CT_PAREN_OPEN)) // Issue #1804
|
|
{
|
|
if ( second->GetParentType() == CT_FUNC_DEF // Issue #3197, #3210
|
|
|| second->GetParentType() == CT_FUNC_PROTO)
|
|
{
|
|
// Add or remove space before a reference sign '&', if followed by a function
|
|
// prototype or function definition.
|
|
log_rule("sp_before_byref_func"); // byref 4
|
|
return(options::sp_before_byref_func());
|
|
}
|
|
Chunk *next = second->GetNext();
|
|
|
|
if ( next->IsNotNullChunk()
|
|
&& ( next->Is(CT_COMMA)
|
|
|| next->Is(CT_PAREN_CLOSE) // Issue #3691
|
|
|| next->Is(CT_FPAREN_CLOSE)
|
|
|| next->Is(CT_SEMICOLON)))
|
|
{
|
|
if (options::sp_before_unnamed_byref() != IARF_IGNORE) // Issue #3691
|
|
{
|
|
// Add or remove space before a reference sign '&' that isn't followed by a
|
|
// variable name. If set to 'ignore', sp_before_byref is used instead.
|
|
log_rule("sp_before_unnamed_byref"); // byref 5
|
|
return(options::sp_before_unnamed_byref());
|
|
}
|
|
else
|
|
{
|
|
// Add or remove space before a reference sign '&'.
|
|
log_rule("sp_before_byref"); // byref 3
|
|
return(options::sp_before_byref());
|
|
}
|
|
}
|
|
|
|
if (first->Is(CT_PTR_TYPE))
|
|
{
|
|
// Add or remove space between pointer and Ref.
|
|
// as in 'int *& a'.
|
|
log_rule("sp_between_ptr_ref"); // ptr_ref 1
|
|
return(options::sp_between_ptr_ref());
|
|
}
|
|
// Add or remove space before a reference sign '&'.
|
|
log_rule("sp_before_byref"); // byref 3
|
|
return(options::sp_before_byref());
|
|
}
|
|
|
|
if (first->Is(CT_SPAREN_CLOSE))
|
|
{
|
|
if (second->Is(CT_BRACE_OPEN))
|
|
{
|
|
if (second->GetParentType() == CT_CATCH)
|
|
{
|
|
if ( language_is_set(LANG_OC)
|
|
&& (options::sp_oc_catch_brace() != IARF_IGNORE))
|
|
{
|
|
// (OC) Add or remove space before the '{' of a '@catch' statement, if the '{'
|
|
// and '@catch' are on the same line, as in '@catch (decl) <here> {'.
|
|
// If set to ignore, sp_catch_brace is used.
|
|
// only to help the vim command }}
|
|
log_rule("sp_oc_catch_brace");
|
|
return(options::sp_oc_catch_brace());
|
|
}
|
|
|
|
if (options::sp_catch_brace() != IARF_IGNORE)
|
|
{
|
|
// Add or remove space before the '{' of a 'catch' statement, if the '{' and
|
|
// 'catch' are on the same line, as in 'catch (decl) <here> {'.
|
|
log_rule("sp_catch_brace");
|
|
return(options::sp_catch_brace());
|
|
}
|
|
}
|
|
|
|
if (options::sp_sparen_brace() != IARF_IGNORE)
|
|
{
|
|
// Add or remove space between ')' and '{' of control statements.
|
|
log_rule("sp_sparen_brace");
|
|
return(options::sp_sparen_brace());
|
|
}
|
|
}
|
|
}
|
|
|
|
// Issue #4094-07
|
|
if ( second->Is(CT_FPAREN_OPEN)
|
|
&& first->GetParentType() == CT_OPERATOR
|
|
&& (options::sp_after_operator_sym() != IARF_IGNORE))
|
|
{
|
|
if ( (options::sp_after_operator_sym_empty() != IARF_IGNORE)
|
|
&& second->Is(CT_FPAREN_OPEN))
|
|
{
|
|
Chunk *next = second->GetNextNcNnl();
|
|
|
|
if (next->Is(CT_FPAREN_CLOSE))
|
|
{
|
|
// Overrides sp_after_operator_sym when the operator has no arguments, as in
|
|
// 'operator *()'.
|
|
log_rule("sp_after_operator_sym_empty");
|
|
return(options::sp_after_operator_sym_empty());
|
|
}
|
|
}
|
|
// Add or remove space between the operator symbol and the open parenthesis, as
|
|
// in 'operator ++('.
|
|
log_rule("sp_after_operator_sym");
|
|
return(options::sp_after_operator_sym());
|
|
}
|
|
|
|
// Issue #2270
|
|
// Translations under vala
|
|
if ( language_is_set(LANG_VALA)
|
|
&& first->Is(CT_FUNC_CALL))
|
|
{
|
|
if ( first->IsString("_")
|
|
&& second->Is(CT_FPAREN_OPEN)
|
|
&& (options::sp_vala_after_translation() != IARF_IGNORE))
|
|
{
|
|
// Add or remove space after '_'.
|
|
log_rule("sp_vala_after_translation");
|
|
return(options::sp_vala_after_translation());
|
|
}
|
|
}
|
|
|
|
if ( first->Is(CT_MACRO_OPEN)
|
|
|| first->Is(CT_MACRO_CLOSE)
|
|
|| first->Is(CT_MACRO_ELSE))
|
|
{
|
|
if (second->Is(CT_FPAREN_OPEN))
|
|
{
|
|
// TODO: provide some test data to check this block
|
|
// Add or remove space between function name and '(' on function calls.
|
|
log_rule("sp_func_call_paren");
|
|
return(options::sp_func_call_paren());
|
|
}
|
|
log_rule("IGNORE");
|
|
return(IARF_IGNORE);
|
|
}
|
|
|
|
// Issue #4094-11
|
|
// spaces between function and open paren
|
|
if ( first->Is(CT_FUNC_CALL)
|
|
|| first->Is(CT_FUNCTION) // Issue #2665
|
|
|| first->Is(CT_FUNC_CTOR_VAR)
|
|
|| first->Is(CT_CNG_HASINC)
|
|
|| first->Is(CT_CNG_HASINCN)
|
|
|| ( first->Is(CT_BRACE_CLOSE)
|
|
&& first->GetParentType() == CT_BRACED_INIT_LIST
|
|
&& second->Is(CT_FPAREN_OPEN))
|
|
|| ( first->Is(CT_FUNC_VAR) // Issue #3852
|
|
&& second->Is(CT_PAREN_OPEN)))
|
|
{
|
|
if ( (options::sp_func_call_paren_empty() != IARF_IGNORE)
|
|
&& second->Is(CT_FPAREN_OPEN))
|
|
{
|
|
Chunk *next = second->GetNextNcNnl();
|
|
|
|
if (next->Is(CT_FPAREN_CLOSE))
|
|
{
|
|
// Add or remove space between function name and '()' on function calls without
|
|
// parameters. If set to 'ignore' (the default), sp_func_call_paren is used.
|
|
log_rule("sp_func_call_paren_empty");
|
|
return(options::sp_func_call_paren_empty());
|
|
}
|
|
}
|
|
// Add or remove space between function name and '(' on function calls.
|
|
log_rule("sp_func_call_paren");
|
|
return(options::sp_func_call_paren());
|
|
}
|
|
|
|
if (first->Is(CT_FUNC_CALL_USER))
|
|
{
|
|
// Add or remove space between the user function name and '(' on function
|
|
// calls. You need to set a keyword to be a user function in the config file,
|
|
// like:
|
|
// set func_call_user tr _ i18n
|
|
log_rule("sp_func_call_user_paren");
|
|
return(options::sp_func_call_user_paren());
|
|
}
|
|
|
|
if ( first->Is(CT_ATTRIBUTE)
|
|
&& second->IsParenOpen())
|
|
{
|
|
// Add or remove space between '__attribute__' and '('.
|
|
log_rule("sp_attribute_paren");
|
|
return(options::sp_attribute_paren());
|
|
}
|
|
|
|
// Issue #4094-10
|
|
if (first->Is(CT_FUNC_DEF))
|
|
{
|
|
if ( (options::sp_func_def_paren_empty() != IARF_IGNORE)
|
|
&& second->Is(CT_FPAREN_OPEN))
|
|
{
|
|
Chunk *next = second->GetNextNcNnl();
|
|
|
|
if (next->Is(CT_FPAREN_CLOSE))
|
|
{
|
|
// Add or remove space between function name and '()' on function definition
|
|
// if empty.
|
|
log_rule("sp_func_def_paren_empty");
|
|
return(options::sp_func_def_paren_empty());
|
|
}
|
|
}
|
|
// Add or remove space between function name and '(' on function definition.
|
|
log_rule("sp_func_def_paren");
|
|
return(options::sp_func_def_paren());
|
|
}
|
|
|
|
if ( first->Is(CT_CPP_CAST)
|
|
|| first->Is(CT_TYPE_WRAP))
|
|
{
|
|
// Add or remove space between the type and open parenthesis in a C++ cast,
|
|
// i.e. 'int(exp)' vs. 'int (exp)'.
|
|
log_rule("sp_cpp_cast_paren");
|
|
return(options::sp_cpp_cast_paren());
|
|
}
|
|
|
|
if ( first->Is(CT_SPAREN_CLOSE)
|
|
&& second->Is(CT_WHEN))
|
|
{
|
|
// TODO: provide some test data to check this block
|
|
log_rule("FORCE");
|
|
return(IARF_FORCE); // TODO: make this configurable?
|
|
}
|
|
|
|
if ( first->Is(CT_PAREN_CLOSE)
|
|
&& ( second->Is(CT_PAREN_OPEN)
|
|
|| second->Is(CT_FPAREN_OPEN)))
|
|
{
|
|
// "(int)a" vs. "(int) a" or "cast(int)a" vs. "cast(int) a"
|
|
if ( first->GetParentType() == CT_C_CAST
|
|
|| first->GetParentType() == CT_D_CAST)
|
|
{
|
|
// Add or remove space after C/D cast, i.e. 'cast(int)a' vs. 'cast(int) a' or
|
|
// '(int)a' vs. '(int) a'.
|
|
log_rule("sp_after_cast");
|
|
return(options::sp_after_cast());
|
|
}
|
|
// Probably a parenthesized indirect function call or similar (issue #3260)
|
|
log_rule("sp_cparen_oparen");
|
|
return(options::sp_cparen_oparen());
|
|
}
|
|
|
|
// handle the space between parens in fcn type 'void (*f)(void)'
|
|
if (first->Is(CT_TPAREN_CLOSE))
|
|
{
|
|
// Add or remove space between the ')' and '(' in a function type, as in
|
|
// 'void (*x)(...)'.
|
|
log_rule("sp_after_tparen_close");
|
|
return(options::sp_after_tparen_close());
|
|
}
|
|
|
|
// ")(" vs. ") ("
|
|
if ( ( first->IsString(")")
|
|
&& second->IsString("("))
|
|
|| ( first->IsParenClose()
|
|
&& second->IsParenOpen()))
|
|
{
|
|
// Add or remove space between back-to-back parentheses, i.e. ')(' vs. ') ('.
|
|
log_rule("sp_cparen_oparen");
|
|
return(options::sp_cparen_oparen());
|
|
}
|
|
|
|
// Issue #4094-09
|
|
if ( first->Is(CT_FUNC_PROTO)
|
|
|| ( second->Is(CT_FPAREN_OPEN)
|
|
&& second->GetParentType() == CT_FUNC_PROTO))
|
|
{
|
|
if ( (options::sp_func_proto_paren_empty() != IARF_IGNORE)
|
|
&& second->Is(CT_FPAREN_OPEN))
|
|
{
|
|
Chunk *next = second->GetNextNcNnl();
|
|
|
|
if (next->Is(CT_FPAREN_CLOSE))
|
|
{
|
|
// Add or remove space between function name and '()' on function declaration
|
|
// if empty.
|
|
log_rule("sp_func_proto_paren_empty");
|
|
return(options::sp_func_proto_paren_empty());
|
|
}
|
|
}
|
|
// Add or remove space between function name and '(' on function declaration.
|
|
log_rule("sp_func_proto_paren");
|
|
return(options::sp_func_proto_paren());
|
|
}
|
|
|
|
// Issue #2437
|
|
if ( first->Is(CT_FUNC_TYPE)
|
|
&& second->Is(CT_FPAREN_OPEN))
|
|
{
|
|
// Add or remove space between function name and '(' with a typedef specifier.
|
|
log_rule("sp_func_type_paren");
|
|
return(options::sp_func_type_paren());
|
|
}
|
|
|
|
// Issue #4094-12
|
|
if ( first->Is(CT_FUNC_CLASS_DEF)
|
|
|| first->Is(CT_FUNC_CLASS_PROTO))
|
|
{
|
|
if ( (options::sp_func_class_paren_empty() != IARF_IGNORE)
|
|
&& second->Is(CT_FPAREN_OPEN))
|
|
{
|
|
Chunk *next = second->GetNextNcNnl();
|
|
|
|
if (next->Is(CT_FPAREN_CLOSE))
|
|
{
|
|
// Add or remove space between a constructor without parameters or destructor
|
|
// and '()'.
|
|
log_rule("sp_func_class_paren_empty");
|
|
return(options::sp_func_class_paren_empty());
|
|
}
|
|
}
|
|
// Add or remove space between a constructor/destructor and the open
|
|
// parenthesis.
|
|
log_rule("sp_func_class_paren");
|
|
return(options::sp_func_class_paren());
|
|
}
|
|
|
|
if ( first->Is(CT_CLASS)
|
|
&& !first->TestFlags(PCF_IN_OC_MSG))
|
|
{
|
|
log_rule("FORCE");
|
|
return(IARF_FORCE);
|
|
}
|
|
|
|
// Issue #4094-08
|
|
if ( first->Is(CT_BRACE_OPEN)
|
|
&& second->Is(CT_BRACE_CLOSE))
|
|
{
|
|
// Add or remove space inside '{}'.
|
|
// if empty.
|
|
log_rule("sp_inside_braces_empty");
|
|
return(options::sp_inside_braces_empty());
|
|
}
|
|
|
|
if ( ( first->Is(CT_TYPE) // Issue #2428
|
|
|| first->Is(CT_ANGLE_CLOSE))
|
|
&& second->Is(CT_BRACE_OPEN)
|
|
&& second->GetParentType() == CT_BRACED_INIT_LIST)
|
|
{
|
|
iarf_flags_t arg = iarf_flags_t{ options::sp_type_brace_init_lst() };
|
|
|
|
if ( arg != IARF_IGNORE
|
|
|| first->GetParentType() != CT_DECLTYPE)
|
|
{
|
|
// 'int{9}' vs. 'int {9}'
|
|
// Add or remove space between type and open brace of an unnamed temporary
|
|
// direct-list-initialization.
|
|
log_rule("sp_type_brace_init_lst");
|
|
return(arg);
|
|
}
|
|
}
|
|
|
|
if ( ( first->Is(CT_WORD) // Issue #2428
|
|
|| first->Is(CT_SQUARE_CLOSE)
|
|
|| first->Is(CT_TSQUARE))
|
|
&& second->Is(CT_BRACE_OPEN)
|
|
&& second->GetParentType() == CT_BRACED_INIT_LIST)
|
|
{
|
|
// Add or remove space between a variable and '{' for C++ uniform
|
|
// initialization.
|
|
auto arg = iarf_flags_t{ options::sp_word_brace_init_lst() };
|
|
|
|
if ( arg != IARF_IGNORE
|
|
|| first->GetParentType() != CT_DECLTYPE)
|
|
{
|
|
// 'a{9}' vs. 'a {9}'
|
|
// Add or remove space between variable/word and open brace of an unnamed
|
|
// temporary direct-list-initialization.
|
|
log_rule("sp_word_brace_init_lst");
|
|
return(arg);
|
|
}
|
|
}
|
|
|
|
if (second->Is(CT_BRACE_CLOSE))
|
|
{
|
|
if (second->GetParentType() == CT_ENUM)
|
|
{
|
|
// Add or remove space inside enum '{' and '}'.
|
|
log_rule("sp_inside_braces_enum");
|
|
return(options::sp_inside_braces_enum());
|
|
}
|
|
|
|
if ( second->GetParentType() == CT_STRUCT
|
|
|| second->GetParentType() == CT_UNION)
|
|
{
|
|
// Fix for issue #1240 adding space in struct initializers
|
|
Chunk *tmp = second->GetOpeningParen()->GetPrevNcNnl();
|
|
|
|
if (tmp->Is(CT_ASSIGN))
|
|
{
|
|
// TODO: provide some test data to check this block
|
|
log_rule("IGNORE");
|
|
return(IARF_IGNORE);
|
|
}
|
|
// Add or remove space inside struct/union '{' and '}'.
|
|
log_rule("sp_inside_braces_struct");
|
|
return(options::sp_inside_braces_struct());
|
|
}
|
|
else if ( language_is_set(LANG_OC)
|
|
&& second->GetParentType() == CT_OC_AT
|
|
&& options::sp_inside_braces_oc_dict() != IARF_IGNORE)
|
|
{
|
|
// (OC) Add or remove space inside Objective-C boxed dictionary '{' and '}'
|
|
log_rule("sp_inside_braces_oc_dict");
|
|
return(options::sp_inside_braces_oc_dict());
|
|
}
|
|
|
|
if (second->GetParentType() == CT_BRACED_INIT_LIST)
|
|
{
|
|
// Add or remove space between nested braces, i.e. '{{' vs. '{ {'.
|
|
// only to help the vim command }}}}
|
|
if ( options::sp_brace_brace() != IARF_IGNORE
|
|
&& first->Is(CT_BRACE_CLOSE)
|
|
&& first->GetParentType() == CT_BRACED_INIT_LIST)
|
|
{
|
|
log_rule("sp_brace_brace");
|
|
return(options::sp_brace_brace());
|
|
}
|
|
|
|
if (options::sp_before_type_brace_init_lst_close() != IARF_IGNORE)
|
|
{
|
|
// Add or remove space before close brace in an unnamed temporary
|
|
// direct-list-initialization
|
|
// if statement is a brace_init_lst
|
|
// works only if sp_brace_brace is set to ignore.
|
|
log_rule("sp_before_type_brace_init_lst_close");
|
|
return(options::sp_before_type_brace_init_lst_close());
|
|
}
|
|
|
|
if (options::sp_inside_type_brace_init_lst() != IARF_IGNORE)
|
|
{
|
|
// Add or remove space inside an unnamed temporary direct-list-initialization.
|
|
// if statement is a brace_init_lst
|
|
// works only if sp_brace_brace is set to ignore
|
|
// works only if sp_before_type_brace_init_lst_close is set to ignore.
|
|
log_rule("sp_inside_type_brace_init_lst");
|
|
return(options::sp_inside_type_brace_init_lst());
|
|
}
|
|
}
|
|
// Add or remove space inside '{' and '}'.
|
|
log_rule("sp_inside_braces");
|
|
return(options::sp_inside_braces());
|
|
}
|
|
|
|
if (first->Is(CT_D_CAST))
|
|
{
|
|
log_rule("REMOVE");
|
|
return(IARF_REMOVE);
|
|
}
|
|
|
|
if ( first->Is(CT_PP_DEFINED)
|
|
&& second->Is(CT_PAREN_OPEN))
|
|
{
|
|
// Add or remove space between 'defined' and '(' in '#if defined (FOO)'.
|
|
log_rule("sp_defined_paren");
|
|
return(options::sp_defined_paren());
|
|
}
|
|
|
|
if (first->Is(CT_THROW))
|
|
{
|
|
if (second->Is(CT_PAREN_OPEN))
|
|
{
|
|
// Add or remove space between 'throw' and '(' in 'throw (something)'.
|
|
log_rule("sp_throw_paren");
|
|
return(options::sp_throw_paren());
|
|
}
|
|
// Add or remove space between 'throw' and anything other than '(' as in
|
|
// '@throw [...];'.
|
|
log_rule("sp_after_throw");
|
|
return(options::sp_after_throw());
|
|
}
|
|
|
|
if ( first->Is(CT_THIS)
|
|
&& second->Is(CT_PAREN_OPEN))
|
|
{
|
|
// Add or remove space between 'this' and '(' in 'this (something)'.
|
|
log_rule("sp_this_paren");
|
|
return(options::sp_this_paren());
|
|
}
|
|
|
|
if ( first->Is(CT_STATE)
|
|
&& second->Is(CT_PAREN_OPEN))
|
|
{
|
|
log_rule("ADD");
|
|
return(IARF_ADD);
|
|
}
|
|
|
|
if ( first->Is(CT_DELEGATE)
|
|
&& second->Is(CT_PAREN_OPEN))
|
|
{
|
|
log_rule("REMOVE");
|
|
return(IARF_REMOVE);
|
|
}
|
|
|
|
if ( first->Is(CT_MEMBER)
|
|
|| second->Is(CT_MEMBER))
|
|
{
|
|
// Add or remove space around the '.' or '->' operators.
|
|
log_rule("sp_member");
|
|
return(options::sp_member());
|
|
}
|
|
|
|
if (first->Is(CT_C99_MEMBER))
|
|
{
|
|
// always remove space(s) after then '.' of a C99-member
|
|
log_rule("REMOVE");
|
|
return(IARF_REMOVE);
|
|
}
|
|
|
|
if ( first->Is(CT_SUPER)
|
|
&& second->Is(CT_PAREN_OPEN))
|
|
{
|
|
// Add or remove space between 'super' and '(' in 'super (something)'.
|
|
log_rule("sp_super_paren");
|
|
return(options::sp_super_paren());
|
|
}
|
|
|
|
if ( first->Is(CT_FPAREN_CLOSE)
|
|
&& second->Is(CT_BRACE_OPEN))
|
|
{
|
|
if ( language_is_set(LANG_JAVA)
|
|
&& second->GetParentType() == CT_DOUBLE_BRACE)
|
|
{
|
|
// (Java) Add or remove space between ')' and '{{' of double brace initializer.
|
|
// only to help the vim command }}
|
|
log_rule("sp_fparen_dbrace");
|
|
return(options::sp_fparen_dbrace());
|
|
}
|
|
|
|
// To fix issue #1234
|
|
// check for initializers and add space or ignore based on the option.
|
|
if (first->GetParentType() == CT_FUNC_CALL)
|
|
{
|
|
Chunk *tmp = first->GetPrevType(first->GetParentType(), first->GetLevel());
|
|
tmp = tmp->GetPrevNcNnl();
|
|
|
|
if (tmp->Is(CT_NEW))
|
|
{
|
|
// Add or remove space between ')' and '{' of s function call in object
|
|
// initialization.
|
|
// Overrides sp_fparen_brace.
|
|
log_rule("sp_fparen_brace_initializer");
|
|
return(options::sp_fparen_brace_initializer());
|
|
}
|
|
}
|
|
// Add or remove space between ')' and '{' of function.
|
|
log_rule("sp_fparen_brace");
|
|
return(options::sp_fparen_brace());
|
|
}
|
|
|
|
if ( first->Is(CT_D_TEMPLATE)
|
|
|| second->Is(CT_D_TEMPLATE))
|
|
{
|
|
log_rule("REMOVE");
|
|
return(IARF_REMOVE);
|
|
}
|
|
|
|
if ( first->Is(CT_ELSE)
|
|
&& second->Is(CT_BRACE_OPEN))
|
|
{
|
|
// Add or remove space between 'else' and '{' if on the same line.
|
|
log_rule("sp_else_brace");
|
|
return(options::sp_else_brace());
|
|
}
|
|
|
|
if ( first->Is(CT_ELSE)
|
|
&& second->Is(CT_ELSEIF))
|
|
{
|
|
log_rule("FORCE");
|
|
return(IARF_FORCE);
|
|
}
|
|
|
|
if ( first->Is(CT_FINALLY)
|
|
&& second->Is(CT_BRACE_OPEN))
|
|
{
|
|
// Add or remove space between 'finally' and '{' if on the same line.
|
|
log_rule("sp_finally_brace");
|
|
return(options::sp_finally_brace());
|
|
}
|
|
|
|
if ( first->Is(CT_TRY)
|
|
&& second->Is(CT_BRACE_OPEN))
|
|
{
|
|
// Add or remove space between 'try' and '{' if on the same line.
|
|
log_rule("sp_try_brace");
|
|
return(options::sp_try_brace());
|
|
}
|
|
|
|
if ( first->Is(CT_GETSET)
|
|
&& second->Is(CT_BRACE_OPEN))
|
|
{
|
|
// Add or remove space between get/set and '{' if on the same line.
|
|
log_rule("sp_getset_brace");
|
|
return(options::sp_getset_brace());
|
|
}
|
|
|
|
if ( first->Is(CT_WORD)
|
|
&& second->Is(CT_BRACE_OPEN))
|
|
{
|
|
if (first->GetParentType() == CT_NAMESPACE)
|
|
{
|
|
// Add or remove space between a variable and '{' for a namespace.
|
|
log_rule("sp_word_brace_ns");
|
|
return(options::sp_word_brace_ns());
|
|
}
|
|
}
|
|
|
|
if ( language_is_set(LANG_D)
|
|
&& second->Is(CT_PAREN_OPEN)
|
|
&& second->GetParentType() == CT_INVARIANT)
|
|
{
|
|
// (D) Add or remove space between 'invariant' and '('.
|
|
log_rule("sp_invariant_paren");
|
|
return(options::sp_invariant_paren());
|
|
}
|
|
|
|
if ( first->Is(CT_PAREN_CLOSE)
|
|
&& first->GetParentType() != CT_DECLTYPE)
|
|
{
|
|
if ( language_is_set(LANG_D)
|
|
&& first->GetParentType() == CT_INVARIANT)
|
|
{
|
|
// (D) Add or remove space after the ')' in 'invariant (C) c'.
|
|
log_rule("sp_after_invariant_paren");
|
|
return(options::sp_after_invariant_paren());
|
|
}
|
|
|
|
// "(struct foo) {...}" vs. "(struct foo){...}"
|
|
if (second->Is(CT_BRACE_OPEN))
|
|
{
|
|
// Add or remove space between ')' and '{'.
|
|
log_rule("sp_paren_brace");
|
|
return(options::sp_paren_brace());
|
|
}
|
|
|
|
// D-specific: "delegate(some thing) dg
|
|
if (first->GetParentType() == CT_DELEGATE)
|
|
{
|
|
log_rule("ADD");
|
|
return(IARF_ADD);
|
|
}
|
|
|
|
// PAWN-specific: "state (condition) next"
|
|
if (first->GetParentType() == CT_STATE)
|
|
{
|
|
log_rule("ADD");
|
|
return(IARF_ADD);
|
|
}
|
|
|
|
/* C++ new operator: new(bar) Foo */
|
|
if (first->GetParentType() == CT_NEW)
|
|
{
|
|
// Add or remove space between ')' and type in 'new(foo) BAR'.
|
|
log_rule("sp_after_newop_paren");
|
|
return(options::sp_after_newop_paren());
|
|
}
|
|
}
|
|
|
|
/* "((" vs. "( (" or "))" vs. ") )" */
|
|
// Issue #1342
|
|
if ( ( first->IsString("(")
|
|
&& second->IsString("("))
|
|
|| ( first->IsString(")")
|
|
&& second->IsString(")")))
|
|
{
|
|
if (second->GetParentType() == CT_FUNC_CALL_USER)
|
|
{
|
|
// Add or remove space between nested parentheses with user functions,
|
|
// i.e. '((' vs. '( ('.
|
|
log_rule("sp_func_call_user_paren_paren");
|
|
return(options::sp_func_call_user_paren_paren());
|
|
}
|
|
|
|
if ( options::sp_sparen_paren() != IARF_IGNORE
|
|
&& ( first->Is(CT_SPAREN_OPEN)
|
|
|| second->Is(CT_SPAREN_CLOSE)))
|
|
{
|
|
// Add or remove space between nested parentheses with control
|
|
// statements, i.e. 'if ((' vs. 'if ( ('. Issue #3209
|
|
log_rule("sp_sparen_paren");
|
|
return(options::sp_sparen_paren());
|
|
}
|
|
// Add or remove space between nested parentheses, i.e. '((' vs. ') )'.
|
|
log_rule("sp_paren_paren");
|
|
return(options::sp_paren_paren());
|
|
}
|
|
|
|
// "foo(...)" vs. "foo( ... )"
|
|
if ( first->Is(CT_FPAREN_OPEN)
|
|
|| second->Is(CT_FPAREN_CLOSE))
|
|
{
|
|
if ( (first->GetParentType() == CT_FUNC_CALL_USER)
|
|
|| ( (second->GetParentType() == CT_FUNC_CALL_USER)
|
|
&& ( (first->Is(CT_WORD))
|
|
|| (first->Is(CT_SQUARE_CLOSE)))))
|
|
{
|
|
// Add or remove space inside user function '(' and ')'.
|
|
log_rule("sp_func_call_user_inside_fparen");
|
|
return(options::sp_func_call_user_inside_fparen());
|
|
}
|
|
|
|
if ( first->Is(CT_FPAREN_OPEN)
|
|
&& second->Is(CT_FPAREN_CLOSE))
|
|
{
|
|
// Add or remove space inside empty function '()'.
|
|
log_rule("sp_inside_fparens");
|
|
return(options::sp_inside_fparens());
|
|
}
|
|
// Add or remove space inside function '(' and ')'.
|
|
log_rule("sp_inside_fparen");
|
|
return(options::sp_inside_fparen());
|
|
}
|
|
|
|
// functor "foo(...)" vs. "foo( ... )"
|
|
if ( first->Is(CT_RPAREN_OPEN)
|
|
|| second->Is(CT_RPAREN_CLOSE)) // Issue #3914
|
|
{
|
|
if ( (first->GetParentType() == CT_FUNC_CALL_USER)
|
|
|| ( (second->GetParentType() == CT_FUNC_CALL_USER)
|
|
&& ( (first->Is(CT_WORD))
|
|
|| (first->Is(CT_SQUARE_CLOSE)))))
|
|
{
|
|
// Add or remove space inside user function '(' and ')'.
|
|
log_rule("sp_func_call_user_inside_rparen");
|
|
return(options::sp_func_call_user_inside_rparen());
|
|
}
|
|
|
|
if ( first->Is(CT_RPAREN_OPEN)
|
|
&& second->Is(CT_RPAREN_CLOSE)) // Issue #3914
|
|
{
|
|
// Add or remove space inside empty function '()'.
|
|
log_rule("sp_inside_rparens");
|
|
return(options::sp_inside_rparens());
|
|
}
|
|
// Add or remove space inside function '(' and ')'.
|
|
log_rule("sp_inside_rparen");
|
|
return(options::sp_inside_rparen());
|
|
}
|
|
|
|
// "foo(...)" vs. "foo( ... )"
|
|
if ( first->Is(CT_TPAREN_OPEN)
|
|
|| second->Is(CT_TPAREN_CLOSE))
|
|
{
|
|
// Add or remove space inside the first parentheses in a function type, as in
|
|
// 'void (*x)(...)'.
|
|
log_rule("sp_inside_tparen");
|
|
return(options::sp_inside_tparen());
|
|
}
|
|
|
|
if ( language_is_set(LANG_OC)
|
|
&& first->Is(CT_PAREN_CLOSE))
|
|
{
|
|
if ( first->TestFlags(PCF_OC_RTYPE) // == CT_OC_RTYPE)
|
|
&& ( first->GetParentType() == CT_OC_MSG_DECL
|
|
|| first->GetParentType() == CT_OC_MSG_SPEC))
|
|
{
|
|
// (OC) Add or remove space after the first (type) in message specs,
|
|
// i.e. '-(int) f:(int)x;' vs. '-(int)f:(int)x;'.
|
|
log_rule("sp_after_oc_return_type");
|
|
return(options::sp_after_oc_return_type());
|
|
}
|
|
|
|
if ( first->GetParentType() == CT_OC_MSG_SPEC
|
|
|| first->GetParentType() == CT_OC_MSG_DECL)
|
|
{
|
|
// (OC) Add or remove space after the (type) in message specs,
|
|
// i.e. '-(int)f: (int) x;' vs. '-(int)f: (int)x;'.
|
|
log_rule("sp_after_oc_type");
|
|
return(options::sp_after_oc_type());
|
|
}
|
|
|
|
if ( first->GetParentType() == CT_OC_SEL
|
|
&& second->IsNot(CT_SQUARE_CLOSE))
|
|
{
|
|
// (OC) Add or remove space between '@selector(x)' and the following word,
|
|
// i.e. '@selector(foo) a:' vs. '@selector(foo)a:'.
|
|
log_rule("sp_after_oc_at_sel_parens");
|
|
return(options::sp_after_oc_at_sel_parens());
|
|
}
|
|
}
|
|
|
|
if ( language_is_set(LANG_OC)
|
|
&& options::sp_inside_oc_at_sel_parens() != IARF_IGNORE)
|
|
{
|
|
if ( ( first->Is(CT_PAREN_OPEN)
|
|
&& ( first->GetParentType() == CT_OC_SEL
|
|
|| first->GetParentType() == CT_OC_PROTOCOL))
|
|
|| ( second->Is(CT_PAREN_CLOSE)
|
|
&& ( second->GetParentType() == CT_OC_SEL
|
|
|| second->GetParentType() == CT_OC_PROTOCOL)))
|
|
{
|
|
// (OC) Add or remove space inside '@selector' parentheses,
|
|
// i.e. '@selector(foo)' vs. '@selector( foo )'.
|
|
// Also applies to '@protocol()' constructs.
|
|
log_rule("sp_inside_oc_at_sel_parens");
|
|
return(options::sp_inside_oc_at_sel_parens());
|
|
}
|
|
}
|
|
|
|
if ( second->Is(CT_PAREN_OPEN)
|
|
&& ( first->Is(CT_OC_SEL)
|
|
|| first->Is(CT_OC_PROTOCOL)))
|
|
{
|
|
// (OC) Add or remove space between '@selector' and '(',
|
|
// i.e. '@selector(msgName)' vs. '@selector (msgName)'.
|
|
// Also applies to '@protocol()' constructs.
|
|
log_rule("sp_after_oc_at_sel");
|
|
return(options::sp_after_oc_at_sel());
|
|
}
|
|
|
|
/*
|
|
* C cast: "(int)" vs. "( int )"
|
|
* D cast: "cast(int)" vs. "cast( int )"
|
|
* CPP cast: "int(a + 3)" vs. "int( a + 3 )"
|
|
*/
|
|
if (first->Is(CT_PAREN_OPEN))
|
|
{
|
|
if ( first->GetParentType() == CT_C_CAST
|
|
|| first->GetParentType() == CT_CPP_CAST
|
|
|| first->GetParentType() == CT_D_CAST)
|
|
{
|
|
// Add or remove spaces inside cast parentheses.
|
|
log_rule("sp_inside_paren_cast");
|
|
return(options::sp_inside_paren_cast());
|
|
}
|
|
|
|
if (first->GetParentType() == CT_NEW)
|
|
{
|
|
if (options::sp_inside_newop_paren_open() != IARF_IGNORE)
|
|
{
|
|
// Add or remove space after the open parenthesis of the new operator,
|
|
// as in 'new(foo) BAR'.
|
|
// Overrides sp_inside_newop_paren.
|
|
log_rule("sp_inside_newop_paren_open");
|
|
return(options::sp_inside_newop_paren_open());
|
|
}
|
|
|
|
if (options::sp_inside_newop_paren() != IARF_IGNORE)
|
|
{
|
|
// Add or remove space inside parentheses of the new operator
|
|
// as in 'new(foo) BAR'.
|
|
log_rule("sp_inside_newop_paren");
|
|
return(options::sp_inside_newop_paren());
|
|
}
|
|
}
|
|
log_rule("sp_inside_paren");
|
|
return(options::sp_inside_paren());
|
|
}
|
|
|
|
if (second->Is(CT_PAREN_CLOSE))
|
|
{
|
|
if ( second->GetParentType() == CT_C_CAST
|
|
|| second->GetParentType() == CT_CPP_CAST
|
|
|| second->GetParentType() == CT_D_CAST)
|
|
{
|
|
// Add or remove spaces inside cast parentheses.
|
|
log_rule("sp_inside_paren_cast");
|
|
return(options::sp_inside_paren_cast());
|
|
}
|
|
|
|
if (second->GetParentType() == CT_NEW)
|
|
{
|
|
if (options::sp_inside_newop_paren_close() != IARF_IGNORE)
|
|
{
|
|
// Add or remove space before the close parenthesis of the new operator,
|
|
// as in 'new(foo) BAR'.
|
|
// Overrides sp_inside_newop_paren.
|
|
log_rule("sp_inside_newop_paren_close");
|
|
return(options::sp_inside_newop_paren_close());
|
|
}
|
|
|
|
if (options::sp_inside_newop_paren() != IARF_IGNORE)
|
|
{
|
|
// Add or remove space inside parentheses of the new operator
|
|
// as in 'new(foo) BAR'.
|
|
log_rule("sp_inside_newop_paren");
|
|
return(options::sp_inside_newop_paren());
|
|
}
|
|
}
|
|
// Add or remove space inside '(' and ')'.
|
|
log_rule("sp_inside_paren");
|
|
return(options::sp_inside_paren());
|
|
}
|
|
|
|
// Issue #4094-06
|
|
if ( first->Is(CT_SQUARE_OPEN)
|
|
&& second->Is(CT_SQUARE_CLOSE))
|
|
{
|
|
// Add or remove space inside '[]'.
|
|
// if empty.
|
|
log_rule("sp_inside_square_empty");
|
|
return(options::sp_inside_square_empty());
|
|
}
|
|
|
|
// "[3]" vs. "[ 3 ]" or for objective-c "@[@3]" vs. "@[ @3 ]"
|
|
if ( first->Is(CT_SQUARE_OPEN)
|
|
|| second->Is(CT_SQUARE_CLOSE))
|
|
{
|
|
if ( language_is_set(LANG_OC)
|
|
&& ( ( first->GetParentType() == CT_OC_AT
|
|
&& first->Is(CT_SQUARE_OPEN))
|
|
|| ( second->GetParentType() == CT_OC_AT
|
|
&& second->Is(CT_SQUARE_CLOSE)))
|
|
&& (options::sp_inside_square_oc_array() != IARF_IGNORE))
|
|
{
|
|
// (OC) Add or remove space inside a non-empty Objective-C boxed array '@[' and
|
|
// ']'. If set to ignore, sp_inside_square is used.
|
|
log_rule("sp_inside_square_oc_array");
|
|
return(options::sp_inside_square_oc_array());
|
|
}
|
|
// Add or remove space inside a non-empty '[' and ']'.
|
|
log_rule("sp_inside_square");
|
|
return(options::sp_inside_square());
|
|
}
|
|
|
|
if ( first->Is(CT_SQUARE_CLOSE)
|
|
&& second->Is(CT_FPAREN_OPEN))
|
|
{
|
|
// Add or remove space between ']' and '(' when part of a function call.
|
|
log_rule("sp_square_fparen");
|
|
return(options::sp_square_fparen());
|
|
}
|
|
|
|
// "if(...)" vs. "if( ... )" etc.
|
|
if (second->Is(CT_SPAREN_CLOSE))
|
|
{
|
|
if ( second->GetParentType() == CT_FOR
|
|
&& options::sp_inside_for_open() != IARF_IGNORE)
|
|
{
|
|
// Add or remove space before ')' of 'for' statements.
|
|
// Overrides sp_inside_for.
|
|
log_rule("sp_inside_for_close");
|
|
return(options::sp_inside_for_close());
|
|
}
|
|
else if (options::sp_inside_sparen_open() != IARF_IGNORE)
|
|
{
|
|
// Add or remove space before ')' of other control statements.
|
|
// Overrides sp_inside_sparen.
|
|
log_rule("sp_inside_sparen_close");
|
|
return(options::sp_inside_sparen_close());
|
|
}
|
|
}
|
|
|
|
if (first->Is(CT_SPAREN_OPEN))
|
|
{
|
|
if ( first->GetParentType() == CT_FOR
|
|
&& options::sp_inside_for_open() != IARF_IGNORE)
|
|
{
|
|
// Add or remove space before ')' of 'for' statements.
|
|
// Overrides sp_inside_for.
|
|
log_rule("sp_inside_for_close");
|
|
return(options::sp_inside_for_close());
|
|
}
|
|
else if (options::sp_inside_sparen_open() != IARF_IGNORE)
|
|
{
|
|
// Add or remove space after '(' of other control statements.
|
|
// Overrides sp_inside_sparen.
|
|
log_rule("sp_inside_sparen_open");
|
|
return(options::sp_inside_sparen_open());
|
|
}
|
|
}
|
|
|
|
if (first->Is(CT_SPAREN_OPEN))
|
|
{
|
|
if (first->GetParentType() == CT_FOR)
|
|
{
|
|
// Add or remove space inside '(' and ')' of 'for' statements.
|
|
log_rule("sp_inside_for");
|
|
return(options::sp_inside_for());
|
|
}
|
|
else
|
|
{
|
|
// Add or remove space inside '(' and ')' of other control statements.
|
|
log_rule("sp_inside_sparen");
|
|
return(options::sp_inside_sparen());
|
|
}
|
|
}
|
|
|
|
if (second->Is(CT_SPAREN_CLOSE))
|
|
{
|
|
if (second->GetParentType() == CT_FOR)
|
|
{
|
|
// Add or remove space inside '(' and ')' of 'for' statements.
|
|
log_rule("sp_inside_for");
|
|
return(options::sp_inside_for());
|
|
}
|
|
else
|
|
{
|
|
// Add or remove space inside '(' and ')' of other control statements.
|
|
log_rule("sp_inside_sparen");
|
|
return(options::sp_inside_sparen());
|
|
}
|
|
}
|
|
|
|
if (first->Is(CT_CLASS_COLON))
|
|
{
|
|
if ( first->GetParentType() == CT_OC_CLASS
|
|
&& ( first->GetPrevType(CT_OC_INTF, first->GetLevel(), E_Scope::ALL)->IsNullChunk()
|
|
&& first->GetPrevType(CT_OC_IMPL, first->GetLevel(), E_Scope::ALL)->IsNullChunk()))
|
|
{
|
|
if (options::sp_after_oc_colon() != IARF_IGNORE)
|
|
{
|
|
// TODO: provide some test data to check this block
|
|
// (OC) Add or remove space after the colon in message specs,
|
|
// i.e. '-(int) f:(int) x;' vs. '-(int) f: (int) x;'.
|
|
log_rule("sp_after_oc_colon");
|
|
return(options::sp_after_oc_colon());
|
|
}
|
|
}
|
|
|
|
if (options::sp_after_class_colon() != IARF_IGNORE)
|
|
{
|
|
// Add or remove space after class ':'.
|
|
log_rule("sp_after_class_colon");
|
|
return(options::sp_after_class_colon());
|
|
}
|
|
}
|
|
|
|
if (second->Is(CT_CLASS_COLON))
|
|
{
|
|
if ( language_is_set(LANG_OC)
|
|
&& second->GetParentType() == CT_OC_CLASS
|
|
&& ( second->GetPrevType(CT_OC_INTF, second->GetLevel(), E_Scope::ALL)->IsNullChunk()
|
|
&& second->GetPrevType(CT_OC_IMPL, second->GetLevel(), E_Scope::ALL)->IsNullChunk()))
|
|
{
|
|
if ( second->GetParentType() == CT_OC_CLASS
|
|
&& second->GetPrevType(CT_OC_INTF, second->GetLevel(), E_Scope::ALL)->IsNullChunk())
|
|
{
|
|
if (options::sp_before_oc_colon() != IARF_IGNORE)
|
|
{
|
|
// TODO: provide some test data to check this block
|
|
// (OC) Add or remove space before the colon in message specs,
|
|
// i.e. '-(int) f: (int) x;' vs. '-(int) f : (int) x;'.
|
|
log_rule("sp_before_oc_colon");
|
|
return(options::sp_before_oc_colon());
|
|
}
|
|
}
|
|
}
|
|
|
|
if (options::sp_before_class_colon() != IARF_IGNORE)
|
|
{
|
|
// Add or remove space before class ':'.
|
|
log_rule("sp_before_class_colon");
|
|
return(options::sp_before_class_colon());
|
|
}
|
|
}
|
|
|
|
if (first->Is(CT_CONSTR_COLON))
|
|
{
|
|
min_sp = options::indent_ctor_init_leading() - 1; // default indent is 1 space
|
|
// Add or remove space after class constructor ':'.
|
|
log_rule("sp_after_constr_colon");
|
|
return(options::sp_after_constr_colon());
|
|
}
|
|
|
|
if (second->Is(CT_CONSTR_COLON))
|
|
{
|
|
// Add or remove space before class constructor ':'.
|
|
log_rule("sp_before_constr_colon");
|
|
return(options::sp_before_constr_colon());
|
|
}
|
|
|
|
if (second->Is(CT_CASE_COLON))
|
|
{
|
|
// Add or remove space before case ':'.
|
|
log_rule("sp_before_case_colon");
|
|
return(options::sp_before_case_colon());
|
|
}
|
|
|
|
if (first->Is(CT_DOT))
|
|
{
|
|
log_rule("REMOVE");
|
|
return(IARF_REMOVE);
|
|
}
|
|
|
|
if (second->Is(CT_DOT))
|
|
{
|
|
log_rule("ADD");
|
|
return(IARF_ADD);
|
|
}
|
|
|
|
if ( first->Is(CT_NULLCOND)
|
|
|| second->Is(CT_NULLCOND))
|
|
{
|
|
// TODO: provide some test data to check this block
|
|
// LANG_CS null conditional operator
|
|
// Add or remove space around the '.' or '->' operators.
|
|
log_rule("sp_member");
|
|
return(options::sp_member());
|
|
}
|
|
|
|
if ( first->Is(CT_ARITH)
|
|
|| first->Is(CT_SHIFT)
|
|
|| first->Is(CT_CARET)
|
|
|| second->Is(CT_ARITH)
|
|
|| second->Is(CT_SHIFT)
|
|
|| second->Is(CT_CARET))
|
|
{
|
|
// Add or remove space around arithmetic operators '+' and '-'.
|
|
// Overrides sp_arith.
|
|
if (options::sp_arith_additive() != IARF_IGNORE)
|
|
{
|
|
auto arith_char = ( first->Is(CT_ARITH)
|
|
|| first->Is(CT_SHIFT)
|
|
|| first->Is(CT_CARET))
|
|
? first->GetStr()[0] : second->GetStr()[0];
|
|
|
|
if ( arith_char == '+'
|
|
|| arith_char == '-')
|
|
{
|
|
log_rule("sp_arith_additive");
|
|
return(options::sp_arith_additive());
|
|
}
|
|
}
|
|
// Add or remove space around non-assignment symbolic operators ('+', '/', '%',
|
|
// '<<', and so forth).
|
|
log_rule("sp_arith");
|
|
return(options::sp_arith());
|
|
}
|
|
|
|
if ( first->Is(CT_BOOL)
|
|
|| second->Is(CT_BOOL))
|
|
{
|
|
// Add or remove space around boolean operators '&&' and '||'.
|
|
iarf_e arg = options::sp_bool();
|
|
|
|
if ( (options::pos_bool() != TP_IGNORE)
|
|
&& first->GetOrigLine() != second->GetOrigLine())
|
|
{
|
|
arg = arg | IARF_ADD;
|
|
}
|
|
log_rule("sp_bool");
|
|
return(arg);
|
|
}
|
|
|
|
if ( first->Is(CT_COMPARE)
|
|
|| second->Is(CT_COMPARE))
|
|
{
|
|
// Add or remove space around compare operator '<', '>', '==', etc.
|
|
log_rule("sp_compare");
|
|
return(options::sp_compare());
|
|
}
|
|
|
|
if ( first->Is(CT_PAREN_OPEN)
|
|
&& second->Is(CT_PTR_TYPE))
|
|
{
|
|
// TODO: provide some test data to check this block
|
|
log_rule("REMOVE");
|
|
return(IARF_REMOVE);
|
|
}
|
|
|
|
if (first->Is(CT_PTR_TYPE)) // see the tests cpp:34505-34508
|
|
{
|
|
if ( second->Is(CT_FPAREN_OPEN)
|
|
|| second->Is(CT_TPAREN_OPEN))
|
|
{
|
|
// Add or remove space after a pointer star '*', if followed by an open
|
|
// parenthesis, as in 'void* (*)()'.
|
|
log_rule("sp_ptr_star_paren"); // ptr_star 10
|
|
return(options::sp_ptr_star_paren());
|
|
}
|
|
else if (second->Is(CT_PTR_TYPE))
|
|
{
|
|
// Add or remove space between pointer stars '*'.
|
|
// as in 'int ***a;'.
|
|
log_rule("sp_between_ptr_star"); // ptr_star 9
|
|
return(options::sp_between_ptr_star());
|
|
}
|
|
else if (second->Is(CT_BYREF))
|
|
{
|
|
// Add or remove space between pointer and Ref.
|
|
// as in 'int *& a'.
|
|
log_rule("sp_between_ptr_ref"); // ptr_ref 1
|
|
return(options::sp_between_ptr_ref());
|
|
}
|
|
else if (second->Is(CT_FUNC_VAR))
|
|
{
|
|
// Add or remove space between the pointer star '*' and the name of the
|
|
// variable in a function pointer definition.
|
|
log_rule("sp_ptr_star_func_var");
|
|
return(options::sp_ptr_star_func_var());
|
|
}
|
|
else if (second->Is(CT_FUNC_TYPE))
|
|
{
|
|
// Add or remove space between the pointer star '*' and the name of the
|
|
// type in a function pointer type definition.
|
|
log_rule("sp_ptr_star_func_type");
|
|
return(options::sp_ptr_star_func_type());
|
|
}
|
|
else if ( first->GetParentType() == CT_FUNC_DEF
|
|
|| first->GetParentType() == CT_FUNC_PROTO
|
|
|| first->GetParentType() == CT_FUNC_VAR)
|
|
{
|
|
if (token_is_within_trailing_return(first))
|
|
{
|
|
// Add or remove space after a pointer star '*', in the trailing return
|
|
// a function prototype or function definition.
|
|
log_rule("sp_after_ptr_star_trailing"); // ptr_star 3
|
|
return(options::sp_after_ptr_star_trailing());
|
|
}
|
|
else
|
|
{
|
|
// Add or remove space after a pointer star '*', if followed by a function
|
|
// prototype or function definition.
|
|
log_rule("sp_after_ptr_star_func"); // ptr_star 2
|
|
return(options::sp_after_ptr_star_func());
|
|
}
|
|
}
|
|
else if (CharTable::IsKw1(second->GetStr()[0]))
|
|
{
|
|
Chunk *prev = first->GetPrev();
|
|
|
|
if (prev->Is(CT_IN))
|
|
{
|
|
// Add or remove space after the '*' (dereference) unary operator. This does
|
|
// not affect the spacing after a '*' that is part of a type.
|
|
log_rule("sp_deref");
|
|
return(options::sp_deref());
|
|
}
|
|
else if ( first->GetParentType() == CT_FUNC_VAR
|
|
|| first->GetParentType() == CT_FUNC_TYPE)
|
|
{
|
|
// Add or remove space after pointer caret '^', if followed by a word.
|
|
log_rule("sp_after_ptr_block_caret");
|
|
return(options::sp_after_ptr_block_caret());
|
|
}
|
|
else if (second->Is(CT_QUALIFIER))
|
|
{
|
|
// Add or remove space after pointer star '*', if followed by a qualifier.
|
|
log_rule("sp_after_ptr_star_qualifier"); // ptr_star 4
|
|
return(options::sp_after_ptr_star_qualifier());
|
|
}
|
|
// Add or remove space after pointer star '*', if followed by a word.
|
|
log_rule("sp_after_ptr_star"); // ptr_star 1
|
|
return(options::sp_after_ptr_star());
|
|
}
|
|
else if (second->Is(CT_PAREN_OPEN))
|
|
{
|
|
// Add or remove space after pointer star '*', if followed by a word.
|
|
log_rule("sp_after_ptr_star"); // ptr_star 1
|
|
return(options::sp_after_ptr_star());
|
|
}
|
|
|
|
// must be placed at the end of the block
|
|
// look back for '->' type is TRAILING_RET
|
|
if (token_is_within_trailing_return(first))
|
|
{
|
|
log_rule("sp_after_ptr_star_trailing"); // ptr_star 3
|
|
return(options::sp_after_ptr_star_trailing());
|
|
}
|
|
}
|
|
|
|
if ( second->Is(CT_PTR_TYPE)
|
|
&& first->IsNot(CT_IN))
|
|
{
|
|
// look back for '->' type is TRAILING_RET
|
|
if (token_is_within_trailing_return(second))
|
|
{
|
|
if (first->Is(CT_QUALIFIER))
|
|
{
|
|
log_rule("sp_qualifier_ptr_star_trailing");
|
|
return(options::sp_qualifier_ptr_star_trailing());
|
|
}
|
|
else
|
|
{
|
|
log_rule("sp_before_ptr_star_trailing"); // ptr_star 7
|
|
return(options::sp_before_ptr_star_trailing());
|
|
}
|
|
}
|
|
// Find the next non-'*' chunk
|
|
Chunk *next = second;
|
|
|
|
do
|
|
{
|
|
next = next->GetNext();
|
|
} while (next->Is(CT_PTR_TYPE));
|
|
|
|
if ( next->Is(CT_FUNC_DEF)
|
|
|| next->Is(CT_FUNC_PROTO))
|
|
{
|
|
// Add or remove space before a pointer star '*', if followed by a function
|
|
// prototype or function definition. If set to ignore, sp_before_ptr_star is
|
|
// used instead.
|
|
|
|
if (first->Is(CT_QUALIFIER))
|
|
{
|
|
if (options::sp_qualifier_ptr_star_func() != IARF_IGNORE)
|
|
{
|
|
log_rule("sp_qualifier_ptr_star_func");
|
|
return(options::sp_qualifier_ptr_star_func());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (options::sp_before_ptr_star_func() != IARF_IGNORE)
|
|
{
|
|
log_rule("sp_before_ptr_star_func"); // ptr_star 6
|
|
return(options::sp_before_ptr_star_func());
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Add or remove space before pointer star '*' that isn't followed by a
|
|
// variable name. If set to 'ignore', sp_before_ptr_star is used instead.
|
|
|
|
next = second->GetNextNc();
|
|
|
|
while (next->Is(CT_PTR_TYPE))
|
|
{
|
|
next = next->GetNextNc();
|
|
}
|
|
|
|
if ( next->IsNotNullChunk()
|
|
&& next->IsNot(CT_WORD))
|
|
{
|
|
if (first->Is(CT_QUALIFIER))
|
|
{
|
|
if (options::sp_qualifier_unnamed_ptr_star() != IARF_IGNORE)
|
|
{
|
|
log_rule("sp_qualifier_unnamed_ptr_star");
|
|
return(options::sp_qualifier_unnamed_ptr_star());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (next->Is(CT_QUALIFIER))
|
|
{
|
|
if (options::sp_before_qualifier_ptr_star() != IARF_IGNORE)
|
|
{
|
|
log_rule("sp_before_qualifier_ptr_star"); // ptr_star 11
|
|
return(options::sp_before_qualifier_ptr_star());
|
|
}
|
|
}
|
|
else if (next->Is(CT_OPERATOR))
|
|
{
|
|
if (options::sp_before_operator_ptr_star() != IARF_IGNORE)
|
|
{
|
|
log_rule("sp_before_operator_ptr_star"); // ptr_star 14
|
|
return(options::sp_before_operator_ptr_star());
|
|
}
|
|
}
|
|
else if (next->Is(CT_DC_MEMBER))
|
|
{
|
|
if (options::sp_before_global_scope_ptr_star() != IARF_IGNORE)
|
|
{
|
|
log_rule("sp_before_global_scope_ptr_star"); // ptr_star 13
|
|
return(options::sp_before_global_scope_ptr_star());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Chunk *next_next = next->GetNextNc();
|
|
|
|
if (next_next->IsNotNullChunk() && next_next->Is(CT_DC_MEMBER))
|
|
{
|
|
if (options::sp_before_scope_ptr_star() != IARF_IGNORE)
|
|
{
|
|
log_rule("sp_before_scope_ptr_star"); // ptr_star 12
|
|
return(options::sp_before_scope_ptr_star());
|
|
}
|
|
}
|
|
}
|
|
|
|
if (options::sp_before_unnamed_ptr_star() != IARF_IGNORE)
|
|
{
|
|
log_rule("sp_before_unnamed_ptr_star"); // ptr_star 8
|
|
return(options::sp_before_unnamed_ptr_star());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add or remove space before pointer star '*'.
|
|
if (options::sp_before_ptr_star() != IARF_IGNORE)
|
|
{
|
|
log_rule("sp_before_ptr_star"); // ptr_star 5
|
|
return(options::sp_before_ptr_star());
|
|
}
|
|
}
|
|
|
|
if (first->Is(CT_OPERATOR))
|
|
{
|
|
// Add or remove space between 'operator' and operator sign.
|
|
log_rule("sp_after_operator");
|
|
return(options::sp_after_operator());
|
|
}
|
|
|
|
if ( second->Is(CT_FUNC_PROTO)
|
|
|| second->Is(CT_FUNC_DEF))
|
|
{
|
|
if ( first->IsNot(CT_PTR_TYPE)
|
|
&& first->IsNot(CT_BYREF))
|
|
{
|
|
// Add or remove space between return type and function name. A
|
|
// minimum of 1 is forced except for pointer/reference return types.
|
|
log_rule("sp_type_func | ADD");
|
|
return(options::sp_type_func() | IARF_ADD);
|
|
}
|
|
// Add or remove space between return type and function name. A
|
|
// minimum of 1 is forced except for pointer/reference return types.
|
|
log_rule("sp_type_func");
|
|
return(options::sp_type_func());
|
|
}
|
|
|
|
// "(int)a" vs. "(int) a" or "cast(int)a" vs. "cast(int) a"
|
|
if ( ( first->GetParentType() == CT_C_CAST
|
|
|| first->GetParentType() == CT_D_CAST)
|
|
&& first->Is(CT_PAREN_CLOSE))
|
|
{
|
|
log_rule("sp_after_cast");
|
|
return(options::sp_after_cast());
|
|
}
|
|
|
|
if (first->Is(CT_BRACE_CLOSE))
|
|
{
|
|
if (second->Is(CT_ELSE))
|
|
{
|
|
// Add or remove space between '}' and 'else' if on the same line.
|
|
log_rule("sp_brace_else");
|
|
return(options::sp_brace_else());
|
|
}
|
|
|
|
if ( language_is_set(LANG_OC)
|
|
&& second->Is(CT_CATCH)
|
|
&& (options::sp_oc_brace_catch() != IARF_IGNORE))
|
|
{
|
|
// TODO: provide some test data to check this block
|
|
// (OC) Add or remove space between '}' and '@catch' if on the same line.
|
|
// If set to ignore, sp_brace_catch is used.
|
|
log_rule("sp_oc_brace_catch");
|
|
return(options::sp_oc_brace_catch());
|
|
}
|
|
|
|
if (second->Is(CT_CATCH))
|
|
{
|
|
// TODO: provide some test data to check this block
|
|
// Add or remove space between '}' and 'catch' if on the same line.
|
|
log_rule("sp_brace_catch");
|
|
return(options::sp_brace_catch());
|
|
}
|
|
|
|
if (second->Is(CT_FINALLY))
|
|
{
|
|
// Add or remove space between '}' and 'finally' if on the same line.
|
|
log_rule("sp_brace_finally");
|
|
return(options::sp_brace_finally());
|
|
}
|
|
}
|
|
|
|
if (first->Is(CT_BRACE_OPEN))
|
|
{
|
|
if (first->GetParentType() == CT_ENUM)
|
|
{
|
|
// Add or remove space inside enum '{' and '}'.
|
|
log_rule("sp_inside_braces_enum");
|
|
return(options::sp_inside_braces_enum());
|
|
}
|
|
|
|
if ( first->GetParentType() == CT_STRUCT
|
|
|| first->GetParentType() == CT_UNION)
|
|
{
|
|
// Fix for issue #1240 adding space in struct initializers
|
|
Chunk *tmp = first->GetPrevNcNnl();
|
|
|
|
if (tmp->Is(CT_ASSIGN))
|
|
{
|
|
// TODO: provide some test data to check this block
|
|
log_rule("IGNORE");
|
|
return(IARF_IGNORE);
|
|
}
|
|
// Add or remove space inside struct/union '{' and '}'.
|
|
log_rule("sp_inside_braces_struct");
|
|
return(options::sp_inside_braces_struct());
|
|
}
|
|
else if ( first->GetParentType() == CT_OC_AT
|
|
&& options::sp_inside_braces_oc_dict() != IARF_IGNORE)
|
|
{
|
|
// (OC) Add or remove space inside Objective-C boxed dictionary '{' and '}'
|
|
log_rule("sp_inside_braces_oc_dict");
|
|
return(options::sp_inside_braces_oc_dict());
|
|
}
|
|
|
|
if (first->GetParentType() == CT_BRACED_INIT_LIST)
|
|
{
|
|
// Add or remove space between nested braces, i.e. '{{' vs. '{ {'.
|
|
// only to help the vim command }}}}
|
|
if ( options::sp_brace_brace() != IARF_IGNORE
|
|
&& second->Is(CT_BRACE_OPEN)
|
|
&& second->GetParentType() == CT_BRACED_INIT_LIST)
|
|
{
|
|
log_rule("sp_brace_brace");
|
|
return(options::sp_brace_brace());
|
|
}
|
|
|
|
if (options::sp_after_type_brace_init_lst_open() != IARF_IGNORE)
|
|
{
|
|
// Add or remove space after open brace in an unnamed temporary
|
|
// direct-list-initialization
|
|
// if statement is a brace_init_lst
|
|
// works only if sp_brace_brace is set to ignore.
|
|
log_rule("sp_after_type_brace_init_lst_open");
|
|
return(options::sp_after_type_brace_init_lst_open());
|
|
}
|
|
|
|
if (options::sp_inside_type_brace_init_lst() != IARF_IGNORE)
|
|
{
|
|
// Add or remove space inside an unnamed temporary direct-list-initialization
|
|
// if statement is a brace_init_lst
|
|
// works only if sp_brace_brace is set to ignore
|
|
// works only if sp_after_type_brace_init_lst_close is set to ignore.
|
|
log_rule("sp_inside_type_brace_init_lst");
|
|
return(options::sp_inside_type_brace_init_lst());
|
|
}
|
|
}
|
|
|
|
if (!second->IsComment())
|
|
{
|
|
// Add or remove space inside '{' and '}'.
|
|
log_rule("sp_inside_braces");
|
|
return(options::sp_inside_braces());
|
|
}
|
|
}
|
|
|
|
if ( first->Is(CT_BRACE_CLOSE)
|
|
&& first->TestFlags(PCF_IN_TYPEDEF)
|
|
&& ( first->GetParentType() == CT_ENUM
|
|
|| first->GetParentType() == CT_STRUCT
|
|
|| first->GetParentType() == CT_UNION))
|
|
{
|
|
// Add or remove space between '}' and the name of a typedef on the same line.
|
|
log_rule("sp_brace_typedef");
|
|
return(options::sp_brace_typedef());
|
|
}
|
|
|
|
if ( language_is_set(LANG_D)
|
|
&& second->Is(CT_PAREN_OPEN)
|
|
&& second->GetParentType() == CT_TEMPLATE)
|
|
{
|
|
// (D) Add or remove space before the parenthesis in the D constructs
|
|
// 'template Foo(' and 'class Foo('.
|
|
log_rule("sp_before_template_paren");
|
|
return(options::sp_before_template_paren());
|
|
}
|
|
|
|
// Issue #3080
|
|
if ( first->Is(CT_PAREN_CLOSE)
|
|
&& first->GetParentType() == CT_DECLTYPE
|
|
&& ( second->Is(CT_WORD)
|
|
|| second->Is(CT_BRACE_OPEN)
|
|
|| second->Is(CT_FUNC_CALL)))
|
|
{
|
|
iarf_e arg = options::sp_after_decltype();
|
|
// Add or remove space between 'decltype(...)' and word, brace or function call.
|
|
log_rule("sp_after_decltype");
|
|
return(arg);
|
|
}
|
|
|
|
// Issue #3080
|
|
if ( !language_is_set(LANG_D)
|
|
&& first->Is(CT_PAREN_CLOSE)
|
|
&& second->Is(CT_WORD))
|
|
{
|
|
// Add or remove space between type and word.
|
|
log_rule("sp_after_type");
|
|
return(options::sp_after_type());
|
|
}
|
|
|
|
// see if the D template expression is used as a type
|
|
if ( language_is_set(LANG_D)
|
|
&& first->Is(CT_PAREN_CLOSE)
|
|
&& first->GetParentType() == CT_D_TEMPLATE)
|
|
{
|
|
if (second->GetParentType() == CT_USING_ALIAS)
|
|
{
|
|
log_rule("sp_after_type | ADD");
|
|
return(options::sp_after_type() | IARF_ADD);
|
|
}
|
|
|
|
if (second->Is(CT_WORD))
|
|
{
|
|
Chunk *open_paren = first->GetOpeningParen();
|
|
Chunk *type = open_paren->GetPrev()->GetPrev();
|
|
|
|
if (type->Is(CT_TYPE))
|
|
{
|
|
log_rule("sp_after_type");
|
|
return(options::sp_after_type());
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( first->Is(CT_TYPE) // Issue #3457
|
|
&& second->Is(CT_COLON))
|
|
{
|
|
log_rule("sp_type_colon");
|
|
return(options::sp_type_colon());
|
|
}
|
|
|
|
if ( !second->Is(CT_PTR_TYPE)
|
|
&& ( first->Is(CT_QUALIFIER)
|
|
|| first->Is(CT_TYPE)))
|
|
{
|
|
// Add or remove space between type and word. In cases where total removal of
|
|
// whitespace would be a syntax error, a value of 'remove' is treated the same
|
|
// as 'force'.
|
|
//
|
|
// This also affects some other instances of space following a type that are
|
|
// not covered by other options; for example, between the return type and
|
|
// parenthesis of a function type template argument, between the type and
|
|
// parenthesis of an array parameter, or between 'decltype(...)' and the
|
|
// following word.
|
|
iarf_e arg = options::sp_after_type();
|
|
log_rule("sp_after_type");
|
|
return(arg);
|
|
}
|
|
|
|
if ( first->Is(CT_PTR_TYPE)
|
|
&& second->Is(CT_ELLIPSIS))
|
|
{
|
|
log_rule("sp_ptr_type_ellipsis");
|
|
return(options::sp_ptr_type_ellipsis());
|
|
}
|
|
|
|
// If nothing claimed the PTR_TYPE, then return ignore
|
|
if ( first->Is(CT_PTR_TYPE)
|
|
|| second->Is(CT_PTR_TYPE))
|
|
{
|
|
log_rule("IGNORE");
|
|
return(IARF_IGNORE);
|
|
}
|
|
|
|
if (first->Is(CT_NOT))
|
|
{
|
|
if ( second->Is(CT_NOT)
|
|
&& (options::sp_not_not() != IARF_IGNORE))
|
|
{
|
|
log_rule("sp_not_not");
|
|
return(options::sp_not_not());
|
|
}
|
|
// Add or remove space after the '!' (not) unary operator.
|
|
log_rule("sp_not");
|
|
return(options::sp_not());
|
|
}
|
|
|
|
if (first->Is(CT_INV))
|
|
{
|
|
// Add or remove space after the '~' (invert) unary operator.
|
|
log_rule("sp_inv");
|
|
return(options::sp_inv());
|
|
}
|
|
|
|
if (first->Is(CT_ADDR))
|
|
{
|
|
// Add or remove space after the '&' (address-of) unary operator. This does not
|
|
// affect the spacing after a '&' that is part of a type.
|
|
log_rule("sp_addr");
|
|
return(options::sp_addr());
|
|
}
|
|
|
|
if (first->Is(CT_DEREF))
|
|
{
|
|
// Add or remove space after the '*' (dereference) unary operator. This does
|
|
// not affect the spacing after a '*' that is part of a type.
|
|
log_rule("sp_deref");
|
|
return(options::sp_deref());
|
|
}
|
|
|
|
if ( first->Is(CT_POS)
|
|
|| first->Is(CT_NEG))
|
|
{
|
|
// Add or remove space after '+' or '-', as in 'x = -5' or 'y = +7'.
|
|
log_rule("sp_sign");
|
|
return(options::sp_sign());
|
|
}
|
|
|
|
if ( first->Is(CT_INCDEC_BEFORE)
|
|
|| second->Is(CT_INCDEC_AFTER))
|
|
{
|
|
// Add or remove space between '++' and '--' the word to which it is being
|
|
// applied, as in '(--x)' or 'y++;'.
|
|
log_rule("sp_incdec");
|
|
return(options::sp_incdec());
|
|
}
|
|
|
|
if (second->Is(CT_CS_SQ_COLON))
|
|
{
|
|
log_rule("REMOVE");
|
|
return(IARF_REMOVE);
|
|
}
|
|
|
|
if (first->Is(CT_CS_SQ_COLON))
|
|
{
|
|
log_rule("FORCE");
|
|
return(IARF_FORCE);
|
|
}
|
|
|
|
if ( language_is_set(LANG_OC)
|
|
&& first->Is(CT_OC_SCOPE))
|
|
{
|
|
// (OC) Add or remove space after the scope '+' or '-', as in '-(void) foo;'
|
|
// or '+(int) bar;'.
|
|
log_rule("sp_after_oc_scope");
|
|
return(options::sp_after_oc_scope());
|
|
}
|
|
|
|
if ( language_is_set(LANG_OC)
|
|
&& first->Is(CT_OC_DICT_COLON))
|
|
{
|
|
// (OC) Add or remove space after the colon in immutable dictionary expression
|
|
// 'NSDictionary *test = @{@"foo" :@"bar"};'.
|
|
log_rule("sp_after_oc_dict_colon");
|
|
return(options::sp_after_oc_dict_colon());
|
|
}
|
|
|
|
if ( language_is_set(LANG_OC)
|
|
&& second->Is(CT_OC_DICT_COLON))
|
|
{
|
|
// (OC) Add or remove space before the colon in immutable dictionary expression
|
|
// 'NSDictionary *test = @{@"foo" :@"bar"};'.
|
|
log_rule("sp_before_oc_dict_colon");
|
|
return(options::sp_before_oc_dict_colon());
|
|
}
|
|
|
|
if ( language_is_set(LANG_OC)
|
|
&& first->Is(CT_OC_COLON))
|
|
{
|
|
if (first->TestFlags(PCF_IN_OC_MSG))
|
|
{
|
|
// (OC) Add or remove space after the colon in message specs,
|
|
// i.e. '[object setValue:1];' vs. '[object setValue: 1];'.
|
|
log_rule("sp_after_send_oc_colon");
|
|
return(options::sp_after_send_oc_colon());
|
|
}
|
|
// (OC) Add or remove space after the colon in message specs,
|
|
// i.e. '-(int) f:(int) x;' vs. '-(int) f: (int) x;'.
|
|
log_rule("sp_after_oc_colon");
|
|
return(options::sp_after_oc_colon());
|
|
}
|
|
|
|
if ( language_is_set(LANG_OC)
|
|
&& second->Is(CT_OC_COLON))
|
|
{
|
|
if ( first->TestFlags(PCF_IN_OC_MSG)
|
|
&& ( first->Is(CT_OC_MSG_FUNC)
|
|
|| first->Is(CT_OC_MSG_NAME)))
|
|
{
|
|
// (OC) Add or remove space before the colon in message specs,
|
|
// i.e. '[object setValue:1];' vs. '[object setValue :1];'.
|
|
log_rule("sp_before_send_oc_colon");
|
|
return(options::sp_before_send_oc_colon());
|
|
}
|
|
// (OC) Add or remove space before the colon in message specs,
|
|
// i.e. '-(int) f: (int) x;' vs. '-(int) f : (int) x;'.
|
|
log_rule("sp_before_oc_colon");
|
|
return(options::sp_before_oc_colon());
|
|
}
|
|
|
|
if ( second->Is(CT_COMMENT)
|
|
&& second->GetParentType() == CT_COMMENT_EMBED)
|
|
{
|
|
// Add or remove space before an embedded comment.
|
|
// Number of spaces before an embedded comment.
|
|
log_rule("sp_before_emb_cmt");
|
|
min_sp = options::sp_num_before_emb_cmt();
|
|
return(options::sp_before_emb_cmt());
|
|
}
|
|
|
|
if (first->Is(CT_COMMENT))
|
|
{
|
|
// Add or remove space after an embedded comment.
|
|
// Number of spaces after an embedded comment.
|
|
log_rule("sp_after_emb_cmt");
|
|
min_sp = options::sp_num_after_emb_cmt();
|
|
return(options::sp_after_emb_cmt());
|
|
}
|
|
|
|
if ( first->Is(CT_NEW)
|
|
&& second->Is(CT_PAREN_OPEN))
|
|
{
|
|
// c# new Constraint, c++ new operator
|
|
// Add or remove space between 'new' and '(' in 'new()'.
|
|
log_rule("sp_between_new_paren");
|
|
return(options::sp_between_new_paren());
|
|
}
|
|
|
|
if ( first->Is(CT_NEW)
|
|
|| first->Is(CT_DELETE)
|
|
|| ( first->Is(CT_TSQUARE)
|
|
&& first->GetParentType() == CT_DELETE))
|
|
{
|
|
// Add or remove space after 'new', 'delete' and 'delete[]'.
|
|
log_rule("sp_after_new");
|
|
return(options::sp_after_new());
|
|
}
|
|
|
|
if ( language_is_set(LANG_JAVA)
|
|
&& first->Is(CT_ANNOTATION)
|
|
&& second->IsParenOpen())
|
|
{
|
|
// (Java) Add or remove space between an annotation and the open parenthesis.
|
|
log_rule("sp_annotation_paren");
|
|
return(options::sp_annotation_paren());
|
|
}
|
|
|
|
if ( language_is_set(LANG_OC)
|
|
&& first->Is(CT_OC_PROPERTY))
|
|
{
|
|
// (OC) Add or remove space after '@property'.
|
|
log_rule("sp_after_oc_property");
|
|
return(options::sp_after_oc_property());
|
|
}
|
|
|
|
if ( language_is_set(LANG_D)
|
|
&& first->Is(CT_EXTERN)
|
|
&& second->Is(CT_PAREN_OPEN))
|
|
{
|
|
// (D) Add or remove space between 'extern' and '(' as in 'extern (C)'.
|
|
log_rule("sp_extern_paren");
|
|
return(options::sp_extern_paren());
|
|
}
|
|
|
|
if ( second->Is(CT_TYPE)
|
|
&& ( ( first->Is(CT_STRING)
|
|
&& first->GetParentType() == CT_EXTERN)
|
|
|| ( first->Is(CT_FPAREN_CLOSE)
|
|
&& first->GetParentType() == CT_ATTRIBUTE)))
|
|
{
|
|
log_rule("FORCE");
|
|
return(IARF_FORCE); /* TODO: make this configurable? */
|
|
}
|
|
|
|
if (first->Is(CT_NOEXCEPT))
|
|
{
|
|
// Add or remove space after 'noexcept'.
|
|
log_rule("sp_after_noexcept");
|
|
return(options::sp_after_noexcept());
|
|
}
|
|
|
|
// Issue #2138
|
|
if (first->Is(CT_FPAREN_CLOSE))
|
|
{
|
|
if (second->Is(CT_QUALIFIER))
|
|
{
|
|
// Add or remove space between ')' and a qualifier such as 'const'.
|
|
log_rule("sp_paren_qualifier");
|
|
return(options::sp_paren_qualifier());
|
|
}
|
|
else if (second->Is(CT_NOEXCEPT))
|
|
{
|
|
// Add or remove space between ')' and 'noexcept'.
|
|
log_rule("sp_paren_noexcept");
|
|
return(options::sp_paren_noexcept());
|
|
}
|
|
}
|
|
|
|
// Issue #2098
|
|
if ( first->Is(CT_PP_PRAGMA)
|
|
&& second->Is(CT_PREPROC_BODY))
|
|
{
|
|
log_rule("REMOVE");
|
|
return(IARF_REMOVE);
|
|
}
|
|
|
|
// Issue #1733
|
|
if ( first->Is(CT_OPERATOR_VAL)
|
|
&& second->Is(CT_TYPE))
|
|
{
|
|
log_rule("IGNORE");
|
|
return(IARF_IGNORE);
|
|
}
|
|
|
|
// Issue #995
|
|
if ( first->Is(CT_DO)
|
|
&& second->Is(CT_BRACE_OPEN))
|
|
{
|
|
// Add or remove space between 'do' and '{'.
|
|
log_rule("sp_do_brace_open");
|
|
return(options::sp_do_brace_open());
|
|
}
|
|
|
|
// Issue #995
|
|
if ( first->Is(CT_BRACE_CLOSE)
|
|
&& second->Is(CT_WHILE_OF_DO))
|
|
{
|
|
// Add or remove space between '}' and 'while.
|
|
log_rule("sp_brace_close_while");
|
|
return(options::sp_brace_close_while());
|
|
}
|
|
|
|
// TODO: have a look to Issue #2186, why NEWLINE?
|
|
// Issue #2524
|
|
if ( first->Is(CT_NEWLINE)
|
|
&& second->Is(CT_BRACE_OPEN))
|
|
{
|
|
log_rule("IGNORE");
|
|
return(IARF_IGNORE);
|
|
}
|
|
|
|
// =============================================================
|
|
// category 0
|
|
// this table lists out all combos where nothing is to do
|
|
// CT_UNKNOWN is a wildcard.
|
|
for (auto it : IGNORE_space_table)
|
|
{
|
|
if ( ( it.first == CT_UNKNOWN
|
|
|| it.first == first->GetType())
|
|
&& ( it.second == CT_UNKNOWN
|
|
|| it.second == second->GetType()))
|
|
{
|
|
log_rule("IGNORE from IGNORE_space_table");
|
|
return(IARF_IGNORE);
|
|
}
|
|
}
|
|
|
|
// =============================================================
|
|
// category 1
|
|
// this table lists out all combos where a space should NOT be present
|
|
// CT_UNKNOWN is a wildcard.
|
|
size_t number = 0;
|
|
|
|
for (auto it : no_space_table)
|
|
{
|
|
if ( ( it.first == CT_UNKNOWN
|
|
|| it.first == first->GetType())
|
|
&& ( it.second == CT_UNKNOWN
|
|
|| it.second == second->GetType()))
|
|
{
|
|
char text[80];
|
|
sprintf(text, "REMOVE from no_space_table @ %zu.", number);
|
|
log_rule(text);
|
|
return(IARF_REMOVE);
|
|
}
|
|
number++;
|
|
}
|
|
|
|
// =============================================================
|
|
// category 2
|
|
// this table lists out all combos where a space MUST be present
|
|
number = 0;
|
|
|
|
for (auto it : add_space_table)
|
|
{
|
|
if ( it.first == first->GetType()
|
|
&& it.second == second->GetType())
|
|
{
|
|
char text[80];
|
|
sprintf(text, "ADD from add_space_table @ %zu.", number);
|
|
log_rule(text);
|
|
return(IARF_ADD);
|
|
}
|
|
number++;
|
|
}
|
|
|
|
// Issue #2386
|
|
if ( first->Is(CT_FORM_FEED)
|
|
|| second->Is(CT_FORM_FEED))
|
|
{
|
|
log_rule("IGNORE");
|
|
return(IARF_IGNORE);
|
|
}
|
|
|
|
// TODO: if necessary create a new option
|
|
if ( first->Is(CT_MACRO_FUNC_CALL)
|
|
&& second->Is(CT_FPAREN_OPEN))
|
|
{
|
|
log_rule("IGNORE");
|
|
return(IARF_IGNORE);
|
|
}
|
|
//// TODO: if necessary create a new option
|
|
//if ( first->Is(CT_RPAREN_OPEN)
|
|
// && second->Is(CT_RPAREN_CLOSE))
|
|
//{
|
|
// log_rule("IGNORE");
|
|
// return(IARF_IGNORE);
|
|
//}
|
|
|
|
//// TODO: if necessary create a new option
|
|
//if ( first->Is(CT_RPAREN_OPEN)
|
|
// && second->Is(CT_UNKNOWN))
|
|
//{
|
|
// log_rule("IGNORE");
|
|
// return(IARF_IGNORE);
|
|
//}
|
|
|
|
//// TODO: if necessary create a new option
|
|
//if ( first->Is(CT_UNKNOWN)
|
|
// && second->Is(CT_RPAREN_CLOSE))
|
|
//{
|
|
// log_rule("IGNORE");
|
|
// return(IARF_IGNORE);
|
|
//}
|
|
|
|
if ( first->Is(CT_CASE_ELLIPSIS)
|
|
&& second->Is(CT_NUMBER))
|
|
{
|
|
// Add or remove space after the variadic '...' when preceded by a
|
|
// non-punctuator.
|
|
// The value REMOVE will be overridden with FORCE
|
|
if (options::sp_after_ellipsis() == IARF_REMOVE)
|
|
{
|
|
log_rule("sp_after_ellipsis/FORCE");
|
|
return(IARF_FORCE);
|
|
}
|
|
else
|
|
{
|
|
log_rule("sp_after_ellipsis");
|
|
return(options::sp_after_ellipsis());
|
|
}
|
|
}
|
|
|
|
if ( first->Is(CT_NUMBER)
|
|
&& second->Is(CT_CASE_ELLIPSIS))
|
|
{
|
|
// Add or remove space before the variadic '...' when preceded by a
|
|
// non-punctuator.
|
|
// The value REMOVE will be overridden with FORCE
|
|
if (options::sp_before_ellipsis() == IARF_REMOVE)
|
|
{
|
|
log_rule("sp_before_ellipsis/FORCE");
|
|
return(IARF_FORCE);
|
|
}
|
|
else
|
|
{
|
|
log_rule("sp_before_ellipsis");
|
|
return(options::sp_before_ellipsis());
|
|
}
|
|
}
|
|
// =============================================================
|
|
// category 3
|
|
// these lines are only useful for debugging uncrustify itself
|
|
LOG_FMT(LSPACE, "\n\n%s(%d): WARNING: unrecognize do_space:\n",
|
|
__func__, __LINE__);
|
|
LOG_FMT(LSPACE, " first orig line is %zu, orig col is %zu, Text() '%s', GetType() is %s\n",
|
|
first->GetOrigLine(), first->GetOrigCol(), first->Text(), get_token_name(first->GetType()));
|
|
LOG_FMT(LSPACE, " second orig line is %zu, orig col is %zu, Text() '%s', GetType() is %s\n",
|
|
second->GetOrigLine(), second->GetOrigCol(), second->Text(), get_token_name(second->GetType()));
|
|
LOG_FMT(LSPACE, " Please make a call at https://github.com/uncrustify/uncrustify/issues/new\n");
|
|
LOG_FMT(LSPACE, " or merge the line:\n");
|
|
LOG_FMT(LSPACE, " { CT_%s, CT_%s},\n",
|
|
get_token_name(first->GetType()), get_token_name(second->GetType()));
|
|
LOG_FMT(LSPACE, " in the file <Path_to_uncrustify>/src/add_space_table.h\n");
|
|
|
|
log_rule("ADD as default value");
|
|
return(IARF_ADD);
|
|
} // do_space
|
|
|
|
|
|
static iarf_e ensure_force_space(Chunk *first, Chunk *second, iarf_e av)
|
|
{
|
|
if (first->TestFlags(PCF_FORCE_SPACE))
|
|
{
|
|
LOG_FMT(LSPACE, "%s(%d): force between '%s' and '%s'\n",
|
|
__func__, __LINE__, first->Text(), second->Text());
|
|
return(av | IARF_ADD);
|
|
}
|
|
return(av);
|
|
}
|
|
|
|
|
|
static iarf_e do_space_ensured(Chunk *first, Chunk *second, int &min_sp)
|
|
{
|
|
return(ensure_force_space(first, second, do_space(first, second, min_sp)));
|
|
}
|
|
|
|
|
|
void space_text()
|
|
{
|
|
LOG_FUNC_ENTRY();
|
|
|
|
Chunk *pc = Chunk::GetHead();
|
|
Chunk *next;
|
|
size_t prev_column;
|
|
size_t column = pc->GetColumn();
|
|
|
|
while (pc->IsNotNullChunk())
|
|
{
|
|
if (pc->Is(CT_NEWLINE))
|
|
{
|
|
LOG_FMT(LSPACE, "%s(%d): orig line is %zu, orig col is %zu, <Newline>, nl is %zu\n",
|
|
__func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->GetNlCount());
|
|
}
|
|
else
|
|
{
|
|
char copy[1000];
|
|
LOG_FMT(LSPACE, "%s(%d): orig line is %zu, orig col is %zu, '%s' type is %s\n",
|
|
__func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->ElidedText(copy), get_token_name(pc->GetType()));
|
|
}
|
|
|
|
if ( (options::use_options_overriding_for_qt_macros())
|
|
&& ( (strcmp(pc->Text(), "SIGNAL") == 0)
|
|
|| (strcmp(pc->Text(), "SLOT") == 0)))
|
|
{
|
|
LOG_FMT(LSPACE, "%s(%d): orig col is %zu, type is %s SIGNAL/SLOT found\n",
|
|
__func__, __LINE__, pc->GetOrigLine(), get_token_name(pc->GetType()));
|
|
pc->SetFlagBits(PCF_IN_QT_MACRO); // flag the chunk for a second processing
|
|
|
|
// save the values
|
|
save_set_options_for_QT(pc->GetLevel());
|
|
}
|
|
|
|
// Bug # 637
|
|
// If true, vbrace tokens are dropped to the previous token and skipped.
|
|
if (options::sp_skip_vbrace_tokens())
|
|
{
|
|
next = pc->GetNext();
|
|
|
|
while ( next->IsEmptyText()
|
|
&& !next->IsNewline()
|
|
&& next->IsVBrace())
|
|
{
|
|
LOG_FMT(LSPACE, "%s(%d): orig line is %zu, orig col is %zu, Skip %s (%zu+%zu)\n",
|
|
__func__, __LINE__, next->GetOrigLine(), next->GetOrigCol(), get_token_name(next->GetType()),
|
|
pc->GetColumn(), pc->GetStr().size());
|
|
next->SetColumn(pc->GetColumn() + pc->GetStr().size());
|
|
next = next->GetNext();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
next = pc->GetNext();
|
|
}
|
|
|
|
if (next->IsNullChunk())
|
|
{
|
|
break;
|
|
}
|
|
|
|
// Issue # 481
|
|
// Whether to balance spaces inside nested parentheses.
|
|
if ( QT_SIGNAL_SLOT_found
|
|
&& options::sp_balance_nested_parens())
|
|
{
|
|
Chunk *nn = next->GetNext(); // Issue #2734
|
|
|
|
if ( nn->IsNotNullChunk()
|
|
&& nn->Is(CT_SPACE))
|
|
{
|
|
Chunk::Delete(nn); // remove the space
|
|
}
|
|
}
|
|
|
|
/*
|
|
* If the current chunk contains a newline, do not change the column
|
|
* of the next item
|
|
*/
|
|
if ( pc->IsNewline()
|
|
|| pc->Is(CT_COMMENT_MULTI))
|
|
{
|
|
column = next->GetColumn();
|
|
}
|
|
else
|
|
{
|
|
// Set to the minimum allowed column
|
|
if (pc->GetNlCount() == 0)
|
|
{
|
|
column += pc->Len();
|
|
}
|
|
else
|
|
{
|
|
column = pc->GetOrigColEnd();
|
|
}
|
|
prev_column = column;
|
|
|
|
/*
|
|
* Apply a general safety check
|
|
* If the two chunks combined will tokenize differently, then we
|
|
* must force a space.
|
|
* Two chunks -- "()" and "[]" will always tokenize differently.
|
|
* They are always safe to not have a space after them.
|
|
*/
|
|
pc->ResetFlagBits(PCF_FORCE_SPACE);
|
|
|
|
if ( (pc->Len() > 0)
|
|
&& !pc->IsString("[]")
|
|
&& !pc->IsString("{{")
|
|
&& !pc->IsString("}}")
|
|
&& !pc->IsString("()")
|
|
&& !pc->GetStr().startswith("@\""))
|
|
{
|
|
// Find the next non-empty chunk on this line
|
|
Chunk *tmp = next;
|
|
|
|
while ( tmp->IsNotNullChunk()
|
|
&& (tmp->Len() == 0)
|
|
&& !tmp->IsNewline())
|
|
{
|
|
tmp = tmp->GetNext();
|
|
}
|
|
|
|
if ( tmp->IsNotNullChunk()
|
|
&& tmp->Len() > 0)
|
|
{
|
|
bool kw1 = CharTable::IsKw2(pc->GetStr()[pc->Len() - 1]);
|
|
bool kw2 = CharTable::IsKw1(next->GetStr()[0]);
|
|
|
|
if ( kw1
|
|
&& kw2)
|
|
{
|
|
// back-to-back words need a space
|
|
LOG_FMT(LSPACE, "%s(%d): back-to-back words need a space: pc->Text() '%s', next->Text() '%s'\n",
|
|
__func__, __LINE__, pc->Text(), next->Text());
|
|
pc->SetFlagBits(PCF_FORCE_SPACE);
|
|
}
|
|
// TODO: what is the meaning of 4
|
|
else if ( !kw1
|
|
&& !kw2
|
|
&& (pc->Len() < 4)
|
|
&& (next->Len() < 4))
|
|
{
|
|
// We aren't dealing with keywords. concat and try punctuators
|
|
char buf[9];
|
|
memcpy(buf, pc->Text(), pc->Len());
|
|
memcpy(buf + pc->Len(), next->Text(), next->Len());
|
|
buf[pc->Len() + next->Len()] = 0;
|
|
|
|
const chunk_tag_t *ct;
|
|
ct = find_punctuator(buf, cpd.lang_flags);
|
|
|
|
if ( ct != nullptr
|
|
&& (strlen(ct->tag) != pc->Len()))
|
|
{
|
|
// punctuator parsed to a different size..
|
|
|
|
/*
|
|
* C++11 allows '>>' to mean '> >' in templates:
|
|
* some_func<vector<string>>();
|
|
*/
|
|
// (C++11) Permit removal of the space between '>>' in 'foo<bar<int> >'. Note
|
|
// that sp_angle_shift cannot remove the space without this option.
|
|
if ( ( ( language_is_set(LANG_CPP)
|
|
&& options::sp_permit_cpp11_shift())
|
|
|| (language_is_set(LANG_JAVA | LANG_CS | LANG_VALA | LANG_OC)))
|
|
&& pc->Is(CT_ANGLE_CLOSE)
|
|
&& next->Is(CT_ANGLE_CLOSE))
|
|
{
|
|
// allow '>' and '>' to become '>>'
|
|
}
|
|
else if (strcmp(ct->tag, "[]") == 0)
|
|
{
|
|
// this is OK
|
|
}
|
|
else
|
|
{
|
|
LOG_FMT(LSPACE, "%s(%d): : pc->Text() is %s, next->Text() is %s\n",
|
|
__func__, __LINE__, pc->Text(), next->Text());
|
|
pc->SetFlagBits(PCF_FORCE_SPACE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
int min_sp;
|
|
LOG_FMT(LSPACE, "%s(%d): orig line is %zu, orig col is %zu, pc-Text() '%s', type is %s\n",
|
|
__func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
|
|
iarf_e av = do_space_ensured(pc, next, min_sp);
|
|
min_sp = max(1, min_sp);
|
|
|
|
switch (av)
|
|
{
|
|
case IARF_FORCE:
|
|
column += min_sp; // add exactly the specified number of spaces
|
|
break;
|
|
|
|
case IARF_ADD:
|
|
{
|
|
int delta = min_sp;
|
|
|
|
// Handle the condition of a CT_VBRACE_OPEN with more complicated spacing mechanics.
|
|
if ( pc->Is(CT_VBRACE_OPEN)
|
|
&& next->GetOrigCol() >= pc->GetPrev()->GetOrigCol())
|
|
{
|
|
delta = next->GetOrigCol() - pc->GetPrev()->GetOrigCol();
|
|
|
|
if ((delta - 1) < min_sp)
|
|
{
|
|
column += min_sp;
|
|
break;
|
|
}
|
|
column += (delta - 1);
|
|
break;
|
|
}
|
|
|
|
if ( next->GetOrigCol() >= pc->GetOrigColEnd()
|
|
&& pc->GetOrigColEnd() != 0)
|
|
{
|
|
// Keep the same relative spacing, minimum 1
|
|
delta = next->GetOrigCol() - pc->GetOrigColEnd();
|
|
|
|
if (delta < min_sp)
|
|
{
|
|
delta = min_sp;
|
|
}
|
|
}
|
|
column += delta;
|
|
break;
|
|
}
|
|
|
|
case IARF_REMOVE:
|
|
// the symbols will be back-to-back "a+3"
|
|
break;
|
|
|
|
case IARF_IGNORE:
|
|
|
|
// Keep the same relative spacing, if possible
|
|
if ( next->GetOrigCol() >= pc->GetOrigColEnd()
|
|
&& pc->GetOrigColEnd() != 0)
|
|
{
|
|
column += next->GetOrigCol() - pc->GetOrigColEnd();
|
|
}
|
|
else
|
|
{
|
|
// preserve the position if virtual brace
|
|
// Issue #1854
|
|
if (pc->Is(CT_VBRACE_OPEN))
|
|
{
|
|
column = next->GetOrigCol();
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
// If we got here, something is wrong...
|
|
break;
|
|
} // switch
|
|
|
|
if ( next->IsComment()
|
|
&& next->GetNext()->IsNewline()
|
|
&& column < next->GetOrigCol())
|
|
{
|
|
/*
|
|
* do some comment adjustments if sp_before_tr_cmt and sp_endif_cmt
|
|
* did not apply.
|
|
*/
|
|
// Add or remove space between #else or #endif and a trailing comment.
|
|
if ( ( options::sp_before_tr_cmt() == IARF_IGNORE
|
|
|| next->GetParentType() != CT_COMMENT_END)
|
|
&& ( options::sp_endif_cmt() == IARF_IGNORE
|
|
|| ( pc->IsNot(CT_PP_ELSE)
|
|
&& pc->IsNot(CT_PP_ENDIF))))
|
|
{
|
|
if (options::indent_relative_single_line_comments())
|
|
{
|
|
// Try to keep relative spacing between tokens
|
|
LOG_FMT(LSPACE, "%s(%d): <relative adj>", __func__, __LINE__);
|
|
LOG_FMT(LSPACE, "%s(%d): pc is '%s', orig col is %zu, next orig col is %zu, pc orig col end is %zu\n",
|
|
__func__, __LINE__, pc->Text(),
|
|
pc->GetOrigCol(), next->GetOrigCol(), pc->GetOrigColEnd());
|
|
column = pc->GetColumn() + (next->GetOrigCol() - pc->GetOrigColEnd());
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* If there was a space, we need to force one, otherwise
|
|
* try to keep the comment in the same column.
|
|
*/
|
|
size_t col_min = pc->GetColumn() + pc->Len() + ((next->GetOrigPrevSp() > 0) ? 1 : 0);
|
|
column = next->GetOrigCol();
|
|
|
|
if (column < col_min)
|
|
{
|
|
column = col_min;
|
|
}
|
|
LOG_FMT(LSPACE, "%s(%d): <relative set>", __func__, __LINE__);
|
|
}
|
|
}
|
|
}
|
|
next->SetColumn(column);
|
|
LOG_FMT(LSPACE, "%s(%d): orig line is %zu, orig col is %zu, pc-Text() '%s', type is %s\n",
|
|
__func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
|
|
LOG_FMT(LSPACE, "%s(%d): ",
|
|
__func__, __LINE__);
|
|
LOG_FMT(LSPACE, " rule = %s @ %zu => %zu\n",
|
|
(av == IARF_IGNORE) ? "IGNORE" :
|
|
(av == IARF_ADD) ? "ADD" :
|
|
(av == IARF_REMOVE) ? "REMOVE" : "FORCE",
|
|
column - prev_column, next->GetColumn());
|
|
|
|
if (restoreValues) // guy 2015-09-22
|
|
{
|
|
restore_options_for_QT();
|
|
}
|
|
}
|
|
pc = next;
|
|
|
|
if (QT_SIGNAL_SLOT_found)
|
|
{
|
|
// flag the chunk for a second processing
|
|
pc->SetFlagBits(PCF_IN_QT_MACRO);
|
|
}
|
|
}
|
|
} // space_text
|
|
|
|
|
|
void space_text_balance_nested_parens()
|
|
{
|
|
LOG_FUNC_ENTRY();
|
|
|
|
Chunk *first = Chunk::GetHead();
|
|
|
|
while (first->IsNotNullChunk())
|
|
{
|
|
Chunk *next = first->GetNext();
|
|
|
|
if (next->IsNullChunk())
|
|
{
|
|
break;
|
|
}
|
|
|
|
// if there are two successive opening parenthesis
|
|
if ( first->IsString("(")
|
|
&& next->IsString("("))
|
|
{
|
|
// insert a space between them
|
|
space_add_after(first, 1);
|
|
|
|
// test after the closing parens Issue #1703
|
|
Chunk *closing = first->GetNextType((E_Token)(first->GetType() + 1), first->GetLevel());
|
|
|
|
if (closing->GetOrigCol() == closing->GetPrev()->GetOrigColEnd())
|
|
{
|
|
space_add_after(closing->GetPrev(), 1);
|
|
}
|
|
}
|
|
else if ( first->IsString(")")
|
|
&& next->IsString(")"))
|
|
{
|
|
// insert a space between the two closing parens
|
|
space_add_after(first, 1);
|
|
|
|
// test after the opening parens Issue #1703
|
|
Chunk *opening = next->GetPrevType((E_Token)(next->GetType() - 1), next->GetLevel());
|
|
|
|
if (opening->GetOrigColEnd() == opening->GetNext()->GetOrigCol())
|
|
{
|
|
space_add_after(opening, 1);
|
|
}
|
|
}
|
|
first = next;
|
|
}
|
|
} // space_text_balance_nested_parens
|
|
|
|
|
|
size_t space_needed(Chunk *first, Chunk *second)
|
|
{
|
|
LOG_FUNC_ENTRY();
|
|
LOG_FMT(LSPACE, "%s(%d)\n", __func__, __LINE__);
|
|
|
|
int min_sp;
|
|
|
|
switch (do_space_ensured(first, second, min_sp))
|
|
{
|
|
case IARF_ADD:
|
|
case IARF_FORCE:
|
|
return(max(1, min_sp));
|
|
|
|
case IARF_REMOVE:
|
|
return(0);
|
|
|
|
case IARF_IGNORE:
|
|
default:
|
|
return(second->GetOrigCol() > (first->GetOrigCol() + first->Len()));
|
|
}
|
|
}
|
|
|
|
|
|
size_t space_col_align(Chunk *first, Chunk *second)
|
|
{
|
|
LOG_FUNC_ENTRY();
|
|
|
|
LOG_FMT(LSPACE, "%s(%d): 1st orig line %zu, orig col %zu, [%s/%s], text '%s' <==>\n",
|
|
__func__, __LINE__, first->GetOrigLine(), first->GetOrigCol(),
|
|
get_token_name(first->GetType()), get_token_name(first->GetParentType()),
|
|
first->Text());
|
|
LOG_FMT(LSPACE, "%s(%d): 2nd orig line %zu, orig col %zu, [%s/%s], text '%s'\n",
|
|
__func__, __LINE__, second->GetOrigLine(), second->GetOrigCol(),
|
|
get_token_name(second->GetType()), get_token_name(second->GetParentType()),
|
|
second->Text());
|
|
log_func_stack_inline(LSPACE);
|
|
|
|
int min_sp;
|
|
iarf_e av = do_space_ensured(first, second, min_sp);
|
|
|
|
LOG_FMT(LSPACE, "%s(%d): av is %s\n", __func__, __LINE__, to_string(av));
|
|
size_t coldiff;
|
|
|
|
if (first->GetNlCount() > 0)
|
|
{
|
|
LOG_FMT(LSPACE, "%s(%d): new line count %zu, orig col end %zu\n",
|
|
__func__, __LINE__, first->GetNlCount(), first->GetOrigColEnd());
|
|
coldiff = first->GetOrigColEnd() - 1;
|
|
}
|
|
else
|
|
{
|
|
LOG_FMT(LSPACE, "%s(%d): '1st' len is %zu\n", __func__, __LINE__, first->Len());
|
|
coldiff = first->Len();
|
|
}
|
|
LOG_FMT(LSPACE, "%s(%d): => coldiff is %zu\n", __func__, __LINE__, coldiff);
|
|
|
|
LOG_FMT(LSPACE, "%s(%d): => av is %s\n", __func__, __LINE__,
|
|
(av == IARF_IGNORE) ? "IGNORE" :
|
|
(av == IARF_ADD) ? "ADD" :
|
|
(av == IARF_REMOVE) ? "REMOVE" : "FORCE");
|
|
|
|
switch (av)
|
|
{
|
|
case IARF_ADD:
|
|
case IARF_FORCE:
|
|
coldiff++;
|
|
break;
|
|
|
|
case IARF_REMOVE:
|
|
break;
|
|
|
|
case IARF_IGNORE: // Issue #2064
|
|
LOG_FMT(LSPACE, "%s(%d): => first orig line is %zu\n", __func__, __LINE__, first->GetOrigLine());
|
|
LOG_FMT(LSPACE, "%s(%d): => second orig line is %zu\n", __func__, __LINE__, second->GetOrigLine());
|
|
LOG_FMT(LSPACE, "%s(%d): => first text is '%s'\n", __func__, __LINE__, first->Text());
|
|
LOG_FMT(LSPACE, "%s(%d): => second text is '%s'\n", __func__, __LINE__, second->Text());
|
|
LOG_FMT(LSPACE, "%s(%d): => first orig col is %zu\n", __func__, __LINE__, first->GetOrigCol());
|
|
LOG_FMT(LSPACE, "%s(%d): => second orig col is %zu\n", __func__, __LINE__, second->GetOrigCol());
|
|
LOG_FMT(LSPACE, "%s(%d): => first len is %zu\n", __func__, __LINE__, first->Len());
|
|
|
|
if ( first->GetOrigLine() == second->GetOrigLine()
|
|
&& second->GetOrigCol() > (first->GetOrigCol() + first->Len()))
|
|
{
|
|
coldiff++;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
// If we got here, something is wrong...
|
|
break;
|
|
}
|
|
LOG_FMT(LSPACE, "%s(%d): => coldiff is %zu\n", __func__, __LINE__, coldiff);
|
|
return(coldiff);
|
|
} // space_col_align
|
|
|
|
|
|
void space_add_after(Chunk *pc, size_t count)
|
|
{
|
|
LOG_FUNC_ENTRY();
|
|
|
|
Chunk *next = pc->GetNext();
|
|
|
|
// don't add at the end of the file or before a newline
|
|
if ( next->IsNullChunk()
|
|
|| next->IsNewline())
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Limit to 16 spaces
|
|
if (count > 16)
|
|
{
|
|
count = 16;
|
|
}
|
|
|
|
// Two CT_SPACE in a row -- use the max of the two
|
|
if (next->Is(CT_SPACE))
|
|
{
|
|
if (next->Len() < count)
|
|
{
|
|
while (next->Len() < count)
|
|
{
|
|
next->Str().append(' ');
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
Chunk sp;
|
|
|
|
sp.SetType(CT_SPACE);
|
|
sp.SetFlags(pc->GetFlags() & PCF_COPY_FLAGS);
|
|
sp.Str() = " "; // 16 spaces
|
|
sp.Str().resize(count);
|
|
sp.SetLevel(pc->GetLevel());
|
|
sp.SetBraceLevel(pc->GetBraceLevel());
|
|
sp.SetPpLevel(pc->GetPpLevel());
|
|
sp.SetColumn(pc->GetColumn() + pc->Len());
|
|
sp.SetOrigLine(pc->GetOrigLine());
|
|
sp.SetOrigCol(pc->GetOrigCol());
|
|
|
|
sp.CopyAndAddAfter(pc);
|
|
} // space_add_after
|