Ejemplo n.º 1
0
 def __reindent_line_comments_after_keyword(self, args: List[str]) -> list:
     verifier = KeywordVerifier(self.__settings)
     for i in reversed(range(len(args))):
         if verifier.is_keyword(args[i]) and re.match(
                 Tokens.get_reindent_regex(), args[i]):
             self.__try_reindent_all_previous_comments(args, i)
     return args
Ejemplo n.º 2
0
 def test_is_command_keyword(self):
     self.assertTrue(KeywordVerifier.is_command_keyword('COMMAND'))
     self.assertTrue(
         KeywordVerifier.is_command_keyword(Tokens.reindent(1) + 'COMMAND'))
     self.assertTrue(
         KeywordVerifier.is_command_keyword(Tokens.reindent(1) + 'ARGS'))
     self.assertFalse(KeywordVerifier.is_command_keyword('CMD'))
     self.assertFalse(
         KeywordVerifier.is_command_keyword(Tokens.reindent(2) + 'COMMAND'))
Ejemplo n.º 3
0
    def test_unquoted_arguments_with_uppercase_letters_only_are_keywords(self):
        self.settings['unquoted_uppercase_as_keyword'] = True
        self.verify = KeywordVerifier(self.settings)

        self.assertTrue(self.verify.is_keyword('OTHER'))
        self.assertTrue(self.verify.is_keyword(Tokens.reindent(1) + 'OTHER'))
        self.assertTrue(self.verify.is_keyword('WITH_SEPARATION'))

        self.assertFalse(self.verify.is_keyword('"$OTHER"'))
        self.assertFalse(self.verify.is_keyword('SOMeARG'))
        self.assertFalse(self.verify.is_keyword('a_ARGUMENT'))
        self.assertFalse(self.verify.is_keyword('NOT_'))
        self.assertFalse(self.verify.is_keyword('_SOME'))
Ejemplo n.º 4
0
 def __realign_property_in_set_function(self, args: List[str]) -> list:
     for i in range(len(args)):
         if KeywordVerifier.is_first_class_keyword(args[i]):
             args, position = self.__reindent_property_name(args, i)
             if self.__is_possible_to_realign_keyword_values(args) and self.__is_value_realignable(args, position):
                 args[position + 1] = ' '
     return args
Ejemplo n.º 5
0
 def __update_indent_state(self, function_name: str) -> None:
     if not self.__is_start_of_special_command(function_name):
         self.__state['indent'] -= 1
     if self.__state['has_first_class_keyword']:
         self.__state['indent'] -= 1
     if self.__is_end_of_special_command(function_name):
         self.__state['indent'] -= 1
     if KeywordVerifier.is_conditional_invocation(function_name):
         self.__state['indent'] -= 1
Ejemplo n.º 6
0
class KeywordStateUpdater:
    def __init__(self, state: dict, settings: dict):
        self.__state = state
        self.__verifier = KeywordVerifier(settings)

    def update_state(self, argument: str) -> None:
        if self.__verifier.is_first_class_keyword(argument):
            self.__state['has_first_class_keyword'] = True
            self.__state['indent'] += 1
        elif self.__verifier.is_keyword(
                argument) or self.__should_indent_property(argument):
            if not self.__state['keyword_argument']:
                self.__state['indent'] += 1
            self.__state['keyword_argument'] = True

    def __should_indent_property(self, argument) -> bool:
        return self.__state[
            'has_first_class_keyword'] and self.__verifier.is_property(
                argument)
Ejemplo n.º 7
0
 def __realign_commands(self, args: List[str]) -> list:
     diff = 0 if self.__settings.get('keyword_and_single_value_in_one_line') else CommandRealignModifier.__DIFF_BETWEEN_KEYWORD_AND_VALUE
     for i in range(len(args)):
         if KeywordVerifier.is_command_keyword(args[i]):
             for j in range(i + diff, len(args) - 1):
                 if self.__verifier.is_keyword(args[j + 1]):
                     break
                 if Tokens.is_spacing_token(args[j]):
                     args[j] = ' '
     return args
Ejemplo n.º 8
0
class FormatUnquotedArgument:
    def __init__(self, state: dict, settings: dict):
        self.__verifier = KeywordVerifier(settings)
        self.__state_updater = KeywordStateUpdater(state, settings)
        self.__state = state
        self.__keyword_argument_already_found = False

    def __call__(self, data: str) -> str:
        self.__keyword_argument_already_found = self.__state[
            'keyword_argument']
        self.__state_updater.update_state(data)
        return self.__format_data(data)

    def __format_data(self, data: str) -> str:
        if self.__keyword_argument_already_found and self.__is_reindent_needed(
                data):
            return Tokens.reindent(1) + data
        return data

    def __is_reindent_needed(self, data):
        return self.__verifier.is_keyword(data) or self.__verifier.is_property(
            data)
Ejemplo n.º 9
0
 def test_recognition_of_conditional_invocation(self):
     self.assertTrue(KeywordVerifier.is_conditional_invocation('If('))
     self.assertTrue(KeywordVerifier.is_conditional_invocation('while('))
     self.assertTrue(KeywordVerifier.is_conditional_invocation('while ('))
     self.assertFalse(
         KeywordVerifier.is_conditional_invocation('foreach ('))
     self.assertFalse(KeywordVerifier.is_conditional_invocation('if2('))
     self.assertFalse(KeywordVerifier.is_conditional_invocation('if*'))
Ejemplo n.º 10
0
class CommandSplitter:
    def __init__(self, state: dict, settings: dict):
        self.__prepare_state(state)
        self.__state_updater = KeywordStateUpdater(self.__state, settings)
        self.__verifier = KeywordVerifier(settings)
        self.__settings = settings

    def split(self, invocation: dict) -> list:
        invocation['arguments'] = self.__split_args_to_newlines(
            invocation['arguments'])
        invocation['arguments'] = self.__realign(invocation)
        return invocation[
            'arguments'] + self.__add_closing_parenthesis_separator(invocation)

    def __realign(self, invocation: dict) -> list:
        return CommandRealignModifier(self.__state,
                                      self.__settings).realign(invocation)

    def __split_args_to_newlines(self, args: list) -> list:
        if self.__verifier.is_keyword_or_property(args[0]):
            args = [FormatNewline(self.__state, self.__settings)(1)] + args
        return [self.__handle_argument(arg) for arg in args]

    def __handle_argument(self, arg: str) -> str:
        self.__state_updater.update_state(arg)
        return self.__get_converted_whitespace() if arg == ' ' else arg

    def __add_closing_parenthesis_separator(self, invocation: dict) -> list:
        if self.__settings['closing_parentheses_in_newline_when_split'] and \
                not self.__is_last_element_newline(invocation):
            return [FormatNewline(self.__state, self.__settings)(1)]
        return []

    @staticmethod
    def __is_last_element_newline(invocation: dict) -> bool:
        return Tokens.is_spacing_token(invocation['arguments'][-1]) or \
               Tokens.is_line_comment(invocation['arguments'][-1])

    def __get_converted_whitespace(self) -> str:
        return FormatNewline(self.__state, self.__settings)(1)

    def __prepare_state(self, state: dict) -> None:
        self.__state = state.copy()
        if self.__state['has_first_class_keyword']:
            self.__state['indent'] -= 1
        self.__state['has_first_class_keyword'] = False
        self.__state['keyword_argument'] = False
Ejemplo n.º 11
0
class CommandRealignModifier:
    __DIFF_BETWEEN_KEYWORD_AND_VALUE = 2

    def __init__(self, state: dict, settings: dict):
        self.__state = state
        self.__verifier = KeywordVerifier(settings)
        self.__settings = settings

    def realign(self, invocation: dict) -> list:
        invocation['arguments'] = self.__realign_properties_if_needed(invocation['arguments'])
        invocation['arguments'] = self.__realign_double_keywords(invocation['arguments'])
        invocation['arguments'] = self.__realign_get_property(invocation)
        invocation['arguments'] = self.__realign_set_property(invocation)
        invocation['arguments'] = self.__realign_commands_if_needed(invocation['arguments'])
        return self.__realign_keyword_values_if_needed(invocation['arguments'])

    def __realign_commands_if_needed(self, args: List[str]) -> list:
        return self.__realign_commands(args) if self.__settings.get('keep_command_in_single_line') else args

    def __realign_commands(self, args: List[str]) -> list:
        diff = 0 if self.__settings.get('keyword_and_single_value_in_one_line') else CommandRealignModifier.__DIFF_BETWEEN_KEYWORD_AND_VALUE
        for i in range(len(args)):
            if KeywordVerifier.is_command_keyword(args[i]):
                for j in range(i + diff, len(args) - 1):
                    if self.__verifier.is_keyword(args[j + 1]):
                        break
                    if Tokens.is_spacing_token(args[j]):
                        args[j] = ' '
        return args

    def __realign_properties_if_needed(self, args: List[str]) -> list:
        return self.__realign_properties(args) if self.__should_realign_properties() else args

    def __should_realign_properties(self) -> bool:
        return self.__settings['keep_property_and_value_in_one_line'] and self.__state['has_first_class_keyword']

    def __realign_properties(self, args: List[str]) -> list:
        for i in range(len(args) - 2):
            if self.__is_property(args[i]) and self.__should_realign_value_after_keyword(args, i):
                args[i + 1] = ' '
        return args

    def __is_property(self, argument: str) -> bool:
        return not self.__verifier.is_first_class_keyword(argument) and self.__verifier.is_keyword_or_property(argument)

    def __realign_double_keywords(self, args: List[str]) -> list:
        for i in range(len(args) - self.__DIFF_BETWEEN_KEYWORD_AND_VALUE):
            if self.__verifier.is_double_keyword(args[i], args[i + self.__DIFF_BETWEEN_KEYWORD_AND_VALUE]):
                args[i + 1] = ' '
        return args

    def __realign_get_property(self, invocation: dict) -> list:
        if invocation['function_name'].startswith('get_property'):
            return self.__replace_newline_with_space_after_property_keyword(invocation['arguments'])
        return invocation['arguments']

    def __realign_set_property(self, invocation: dict) -> list:
        if invocation['function_name'].startswith('set_property'):
            return self.__realign_property_in_set_function(invocation['arguments'])
        return invocation['arguments']

    def __realign_property_in_set_function(self, args: List[str]) -> list:
        for i in range(len(args)):
            if KeywordVerifier.is_first_class_keyword(args[i]):
                args, position = self.__reindent_property_name(args, i)
                if self.__is_possible_to_realign_keyword_values(args) and self.__is_value_realignable(args, position):
                    args[position + 1] = ' '
        return args

    def __is_value_realignable(self, args, position):
        return not Tokens.is_line_comment(args[position + 2]) and \
               self.__get_number_of_arguments(args, position) == 1

    def __get_number_of_arguments(self, args: List[str], start: int) -> int:
        return sum([self.__is_argument(data) for data in args[start + 1:]])

    def __reindent_property_name(self, args: list, start_index: int) -> Tuple[list, int]:
        for i in range(start_index + 1, len(args)):
            if self.__is_argument(args[i]):
                if not args[i].startswith(Tokens.reindent(1)):
                    args[i] = Tokens.reindent(1) + args[i]
                return args, i
        return args, 0

    @staticmethod
    def __is_argument(data: str) -> bool:
        return not (Tokens.is_line_comment(data) or Tokens.is_spacing_token(data))

    def __replace_newline_with_space_after_property_keyword(self, args: List[str]) -> list:
        for i in range(len(args) - CommandRealignModifier.__DIFF_BETWEEN_KEYWORD_AND_VALUE):
            if self.__is_property_followed_by_name(args, i):
                args[i + 1] = ' '
        return args

    def __realign_keyword_values_if_needed(self, args: List[str]) -> list:
        return self.__realign_keyword_values(args) if self.__is_possible_to_realign_keyword_values(args) else args

    def __is_possible_to_realign_keyword_values(self, args: List[str]) -> bool:
        return self.__settings['keyword_and_single_value_in_one_line'] and \
               len(args) > CommandRealignModifier.__DIFF_BETWEEN_KEYWORD_AND_VALUE

    def __realign_keyword_values(self, args: List[str]) -> list:
        for i in range(len(args) - CommandRealignModifier.__DIFF_BETWEEN_KEYWORD_AND_VALUE):
            if self.__should_realign_value_after_keyword(args, i):
                args[i + 1] = ' '
        return args

    def __should_realign_value_after_keyword(self, args: List[str], current_index: int) -> bool:
        return self.__verifier.is_keyword_or_property(args[current_index]) and \
               Tokens.is_spacing_token(args[current_index + 1]) and \
               not self.__verifier.is_keyword_or_property(args[current_index + 2]) and \
               self.__is_single_value(args, current_index)

    def __is_single_value(self, args: List[str], current_index: int) -> bool:
        tokens_diff = 4  # keyword, space, value, space, keyword
        return current_index + tokens_diff >= len(args) or \
               self.__verifier.is_keyword_or_property(args[current_index + tokens_diff])

    @staticmethod
    def __is_property_followed_by_name(args: list, i: int) -> bool:
        return KeywordVerifier.is_first_class_keyword(args[i]) and not Tokens.is_line_comment(args[i + 2])
Ejemplo n.º 12
0
 def __init__(self, state: dict, settings: dict):
     self.__prepare_state(state)
     self.__state_updater = KeywordStateUpdater(self.__state, settings)
     self.__verifier = KeywordVerifier(settings)
     self.__settings = settings
Ejemplo n.º 13
0
class TestKeywordVerifier(unittest.TestCase):
    def setUp(self) -> None:
        self.settings = {
            'keywords': ['some'],
            'unquoted_uppercase_as_keyword': False
        }
        self.verify = KeywordVerifier(self.settings)

    @mock.patch('builtins.open')
    def test_ensure_properties_are_read_only_once(self, mock_open: MagicMock):
        self.verify = KeywordVerifier(self.settings)
        self.assertFalse(mock_open.called)

    def test_should_accept_keyword_when_on_the_list(self):
        self.assertTrue(self.verify.is_keyword('some'))
        self.assertTrue(self.verify.is_keyword(Tokens.reindent(1) + 'some'))
        self.assertFalse(self.verify.is_keyword('some2'))
        self.assertFalse(self.verify.is_keyword('${some}'))

    def test_unquoted_arguments_with_uppercase_letters_only_are_keywords(self):
        self.settings['unquoted_uppercase_as_keyword'] = True
        self.verify = KeywordVerifier(self.settings)

        self.assertTrue(self.verify.is_keyword('OTHER'))
        self.assertTrue(self.verify.is_keyword(Tokens.reindent(1) + 'OTHER'))
        self.assertTrue(self.verify.is_keyword('WITH_SEPARATION'))

        self.assertFalse(self.verify.is_keyword('"$OTHER"'))
        self.assertFalse(self.verify.is_keyword('SOMeARG'))
        self.assertFalse(self.verify.is_keyword('a_ARGUMENT'))
        self.assertFalse(self.verify.is_keyword('NOT_'))
        self.assertFalse(self.verify.is_keyword('_SOME'))

    def test_whether_token_is_first_class_keyword(self):
        self.assertTrue(self.verify.is_first_class_keyword('PROPERTY'))
        self.assertTrue(self.verify.is_first_class_keyword('PROPERTIES'))
        self.assertTrue(
            self.verify.is_first_class_keyword(
                Tokens.reindent(1) + 'PROPERTY'))
        self.assertFalse(self.verify.is_first_class_keyword('PROPERTY2'))
        self.assertFalse(self.verify.is_first_class_keyword('proPERTY'))

    def test_available_properties_version(self):
        self.assertEqual('3.18.0', self.verify.get_cmake_properties_version())

    def test_cmake_properties_matching_exactly(self):
        self.assertTrue(self.verify.is_property('LINK_DIRECTORIES'))
        self.assertTrue(
            self.verify.is_property('INSTALL_REMOVE_ENVIRONMENT_RPATH'))
        self.assertFalse(
            self.verify.is_property('1INSTALL_REMOVE_ENVIRONMENT_RPATH'))

    def test_cmake_properties_starting_with(self):
        self.assertTrue(self.verify.is_property('IMPORTED_NO_SONAME'))
        self.assertTrue(self.verify.is_property('IMPORTED_NO_SONAME_123'))
        self.assertFalse(self.verify.is_property('IMPORTED_NO_SONAME123'))
        self.assertFalse(self.verify.is_property('123_IMPORTED_NO_SONAME_123'))
        self.assertFalse(self.verify.is_property('IMPORTED_NO_SONAM'))

    def test_cmake_properties_ending_with(self):
        self.assertTrue(self.verify.is_property('_OUTPUT_NAME'))
        self.assertTrue(self.verify.is_property('VALUE_OUTPUT_NAME'))
        self.assertFalse(self.verify.is_property('_OUTPUT_NAME_VALUE'))

    def test_cmake_properties_with_reindent_token(self):
        self.assertTrue(
            self.verify.is_property(Tokens.reindent(1) + 'LINK_DIRECTORIES'))

    def test_double_keywords(self):
        self.assertTrue(
            self.verify.is_double_keyword(
                Tokens.reindent(1) + 'RUNTIME', 'DESTINATION'))
        self.assertTrue(
            self.verify.is_double_keyword('ARCHIVE',
                                          Tokens.reindent(1) + 'DESTINATION'))
        self.assertTrue(self.verify.is_double_keyword('LIBRARY',
                                                      'DESTINATION'))
        self.assertFalse(self.verify.is_double_keyword('OUTPUT',
                                                       'DESTINATION'))
        self.assertFalse(self.verify.is_double_keyword('LIBRARY', 'OUTPUT'))

    def test_recognition_of_conditional_invocation(self):
        self.assertTrue(KeywordVerifier.is_conditional_invocation('If('))
        self.assertTrue(KeywordVerifier.is_conditional_invocation('while('))
        self.assertTrue(KeywordVerifier.is_conditional_invocation('while ('))
        self.assertFalse(
            KeywordVerifier.is_conditional_invocation('foreach ('))
        self.assertFalse(KeywordVerifier.is_conditional_invocation('if2('))
        self.assertFalse(KeywordVerifier.is_conditional_invocation('if*'))

    def test_is_command_keyword(self):
        self.assertTrue(KeywordVerifier.is_command_keyword('COMMAND'))
        self.assertTrue(
            KeywordVerifier.is_command_keyword(Tokens.reindent(1) + 'COMMAND'))
        self.assertTrue(
            KeywordVerifier.is_command_keyword(Tokens.reindent(1) + 'ARGS'))
        self.assertFalse(KeywordVerifier.is_command_keyword('CMD'))
        self.assertFalse(
            KeywordVerifier.is_command_keyword(Tokens.reindent(2) + 'COMMAND'))
Ejemplo n.º 14
0
 def setUp(self) -> None:
     self.settings = {
         'keywords': ['some'],
         'unquoted_uppercase_as_keyword': False
     }
     self.verify = KeywordVerifier(self.settings)
Ejemplo n.º 15
0
 def test_ensure_properties_are_read_only_once(self, mock_open: MagicMock):
     self.verify = KeywordVerifier(self.settings)
     self.assertFalse(mock_open.called)
Ejemplo n.º 16
0
 def __should_add_space_for_conditional(self, formatted: str) -> bool:
     return self.__settings.get('space_after_loop_condition') and \
            KeywordVerifier.is_conditional_invocation(formatted)
Ejemplo n.º 17
0
 def __is_property_followed_by_name(args: list, i: int) -> bool:
     return KeywordVerifier.is_first_class_keyword(args[i]) and not Tokens.is_line_comment(args[i + 2])
Ejemplo n.º 18
0
 def __init__(self, state: dict, settings: dict):
     self.__state = state
     self.__verifier = KeywordVerifier(settings)
     self.__settings = settings
Ejemplo n.º 19
0
 def __init__(self, state: dict, settings: dict):
     self.__verifier = KeywordVerifier(settings)
     self.__state_updater = KeywordStateUpdater(state, settings)
     self.__state = state
     self.__keyword_argument_already_found = False
Ejemplo n.º 20
0
def format_command_invocation(state: dict, settings: dict,
                              invocation: dict) -> str:
    if KeywordVerifier.is_conditional_invocation(invocation['function_name']):
        return ConditionFormatter(state, settings).format(invocation)
    return CommandFormatter(state, settings).format(invocation)
Ejemplo n.º 21
0
 def __update_state(self, data: str):
     if KeywordVerifier.is_conditional_invocation(data):
         self.__state['indent'] += 1
     self.__state['indent'] += 1