From 0efd1378f9118147c88f2c00236231dacfb9fb4c Mon Sep 17 00:00:00 2001 From: khanchi97 Date: Sat, 16 Dec 2017 17:19:11 +0530 Subject: [PATCH] SpaceConsistencyBear: Add blanklines_at_EOF option Add allow_trailing_blanklines option for whether to allow trailing blanklines at EOF. Closes https://github.com/coala/coala-bears/issues/1793 --- bears/general/SpaceConsistencyBear.py | 105 +++++++++++++++------- tests/general/SpaceConsistencyBearTest.py | 26 +++++- 2 files changed, 97 insertions(+), 34 deletions(-) diff --git a/bears/general/SpaceConsistencyBear.py b/bears/general/SpaceConsistencyBear.py index 2d929fcefb..5a588023a3 100644 --- a/bears/general/SpaceConsistencyBear.py +++ b/bears/general/SpaceConsistencyBear.py @@ -18,6 +18,7 @@ def run(self, file, use_spaces: bool, allow_trailing_whitespace: bool=False, + allow_trailing_blanklines: bool=False, indent_size: int=SpacingHelper.DEFAULT_TAB_WIDTH, enforce_newline_at_EOF: bool=True): ''' @@ -29,6 +30,8 @@ def run(self, of tabs. :param allow_trailing_whitespace: Whether to allow trailing whitespace or not. + :param allow_trailing_blanklines: Whether to allow trailing blanklines + at the EOF or not. :param indent_size: Number of spaces per indentation level. :param enforce_newline_at_EOF: Whether to enforce a newline at the @@ -38,48 +41,84 @@ def run(self, result_texts = [] additional_info_texts = [] + def get_blanklines_nr_start(): + + if not allow_trailing_blanklines: + rev_enumerated_zip_obj = zip(reversed(range(1, len(file) + 1)), + reversed(file)) + rev_enumerated_tuple = tuple(rev_enumerated_zip_obj) + line_nr_start = -1 + + for line_number, line in rev_enumerated_tuple: + replacement = line + if replacement.strip() == '': + line_nr_start = line_number + else: + break + + return line_nr_start + + blanklines_nr_start = get_blanklines_nr_start() + no_blanklines = True + for line_number, line in enumerate(file, start=1): replacement = line - if enforce_newline_at_EOF: - # Since every line contains at the end at least one \n, only - # the last line could potentially not have one. So we don't - # need to check whether the current line_number is the last - # one. - if replacement[-1] != '\n': - replacement += '\n' - result_texts.append('No newline at EOF.') - additional_info_texts.append( - "A trailing newline character ('\\n') is missing from " - 'your file. ' - ' gives ' - 'more information about why you might need one.') - - if not allow_trailing_whitespace: - replacement = replacement.rstrip(' \t\n') + '\n' - if replacement != line.rstrip('\n') + '\n': - result_texts.append('Trailing whitespaces.') + if not allow_trailing_blanklines: + if blanklines_nr_start == line_number: + + no_blanklines = False + result_texts.append('Trailing blanklines.') additional_info_texts.append( - 'Your source code contains trailing whitespaces. ' - 'Those usually have no meaning. Please consider ' + 'Your source code contains trailing blanklines at EOF.' + 'Those usually have no meaning. Please consider' 'removing them.') + blanklines_nr_start = None + + if no_blanklines: + if enforce_newline_at_EOF: + # Since every line contains at the end at least one \n, + # only the last line could potentially not have one. So we + # don't need to check whether the current line_number is + # the last one. + if replacement[-1] != '\n': + replacement += '\n' + result_texts.append('No newline at EOF.') + additional_info_texts.append( + "A trailing newline character ('\\n') is missing " + 'from your file. ' + ' ' + 'gives more information about why you might need ' + 'one.') + + if not allow_trailing_whitespace: + replacement = replacement.rstrip(' \t\n') + '\n' + if replacement != line.rstrip('\n') + '\n': + result_texts.append('Trailing whitespaces.') + additional_info_texts.append( + 'Your source code contains trailing whitespaces. ' + 'Those usually have no meaning. Please consider ' + 'removing them.') - if use_spaces: - pre_replacement = replacement - replacement = spacing_helper.replace_tabs_with_spaces( - replacement) - if replacement != pre_replacement: - result_texts.append('Tabs used instead of spaces.') - else: - pre_replacement = replacement - replacement = spacing_helper.replace_spaces_with_tabs( - replacement) - if replacement != pre_replacement: - result_texts.append('Spaces used instead of tabs.') + if use_spaces: + pre_replacement = replacement + replacement = spacing_helper.replace_tabs_with_spaces( + replacement) + if replacement != pre_replacement: + result_texts.append('Tabs used instead of spaces.') + else: + pre_replacement = replacement + replacement = spacing_helper.replace_spaces_with_tabs( + replacement) + if replacement != pre_replacement: + result_texts.append('Spaces used instead of tabs.') if len(result_texts) > 0: diff = Diff(file) - diff.change_line(line_number, line, replacement) + if no_blanklines: + diff.change_line(line_number, line, replacement) + else: + diff.delete_lines(line_number, len(file)) inconsistencies = ''.join('\n- ' + string for string in result_texts) yield Result.from_values( diff --git a/tests/general/SpaceConsistencyBearTest.py b/tests/general/SpaceConsistencyBearTest.py index c2019b3957..ef4b8fa592 100644 --- a/tests/general/SpaceConsistencyBearTest.py +++ b/tests/general/SpaceConsistencyBearTest.py @@ -44,15 +44,18 @@ def test_data_sets_tabs(self): self.section.append(Setting('use_spaces', 'false')) self.section.append(Setting('allow_trailing_whitespace', 'true')) self.section.append(Setting('enforce_newline_at_EOF', 'false')) + self.section.append(Setting('allow_trailing_blanklines', 'false')) self.check_invalidity(self.uut, [' t']) self.check_validity(self.uut, ['t \n']) self.check_validity(self.uut, ['\tt\n']) + self.check_validity(self.uut, []) def test_enforce_newline_at_eof(self): self.section.append(Setting('use_spaces', 'true')) self.section.append(Setting('allow_trailing_whitespace', 'true')) self.section.append(Setting('enforce_newline_at_EOF', 'true')) + self.section.append(Setting('allow_trailing_blanklines', 'true')) self.check_validity(self.uut, ['hello world \n'], @@ -60,7 +63,9 @@ def test_enforce_newline_at_eof(self): self.check_validity(self.uut, ['def somecode():\n', " print('funny')\n", - " print('funny end.')\n"], + " print('funny end.')\n", + ' \n', + '\n'], force_linebreaks=False) self.check_invalidity(self.uut, [' no hello world'], @@ -70,3 +75,22 @@ def test_enforce_newline_at_eof(self): " print('funny')\n", " print('the result is not funny...')"], force_linebreaks=False) + + def test_trailing_blanklines(self): + self.section.append(Setting('use_spaces', 'true')) + self.section.append(Setting('allow_trailing_whitespace', 'false')) + self.section.append(Setting('enforce_newline_at_EOF', 'true')) + self.section.append(Setting('allow_trailing_blanklines', 'false')) + + self.check_invalidity(self.uut, + ['def funny_code():\n', + " print('Is it funny?')\n", + " print('Yeah, funny')\n", + ' \n', + '\n'], + force_linebreaks=False) + self.check_validity(self.uut, + ['def funny_code():\n', + " print('Is it funny?')\n", + " print('Yeah, funny')\n"], + force_linebreaks=False)