From 8362b9b2054a38f81bdb021a86c3ffd3e112785b Mon Sep 17 00:00:00 2001
From: Akshit jain <akshjain.jain74@gmail.com>
Date: Sun, 17 Mar 2019 00:58:27 +0530
Subject: [PATCH] Bears: Remove leading blank line option

Implemented a feature for spaceconsistencyBear
that control the removal of blank lines.

Closes https://github.com/coala/coala-bears/issues/2207
---
 bears/general/SpaceConsistencyBear.py     | 46 ++++++++++++++++++++++-
 tests/general/SpaceConsistencyBearTest.py | 24 ++++++++++++
 tests/go/GoImportsBearTest.py             |  1 -
 3 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/bears/general/SpaceConsistencyBear.py b/bears/general/SpaceConsistencyBear.py
index 6853c7dfff..f52330b82a 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_leading_blanklines: bool = False,
             indent_size: int = SpacingHelper.DEFAULT_TAB_WIDTH,
             enforce_newline_at_EOF: bool = True,
             ):
@@ -34,12 +35,55 @@ def run(self,
             Number of spaces per indentation level.
         :param enforce_newline_at_EOF:
             Whether to enforce a newline at the End Of File.
+        :param allow_leading_blanklines:
+            Whether to allow leading blank lines at the start
+            of file or not.
         '''
         spacing_helper = SpacingHelper(indent_size)
         result_texts = []
         additional_info_texts = []
 
-        for line_number, line in enumerate(file, start=1):
+        def end_blanklines():
+            end_line = False
+            enumerated_zip_obj = zip(range(1, len(file) + 1), file)
+            enumerated_tuple = tuple(enumerated_zip_obj)
+
+            for line_number, line in enumerated_tuple:
+                replacement = line
+                if replacement.strip() == '':
+                    end_line = line_number
+                else:
+                    break
+            return end_line
+
+        if allow_leading_blanklines:
+            start_line_of_file = 1
+        else:
+            end_blanklines = end_blanklines()
+            start_line_of_file = 1
+            if end_blanklines:
+                start_line_of_file = end_blanklines + 1
+                result_texts.append('Leading blank lines.')
+                additional_info_texts.append(
+                    'Your source code contains leading blank lines.'
+                    'Those usually have no meaning. Please consider '
+                    'removing them.')
+                diff = Diff(file)
+                diff.delete_lines(1, end_blanklines)
+                inconsistencies = ''.join('\n- ' + string
+                                          for string in result_texts)
+                yield Result.from_values(
+                    self,
+                    'Line contains following spacing inconsistencies:'
+                    + inconsistencies,
+                    diffs={filename: diff},
+                    file=filename,
+                    additional_info='\n\n'.join(additional_info_texts))
+                result_texts = []
+                additional_info_texts = []
+
+        for line_number, line in enumerate(file[start_line_of_file - 1:],
+                                           start=start_line_of_file):
             replacement = line
 
             if enforce_newline_at_EOF:
diff --git a/tests/general/SpaceConsistencyBearTest.py b/tests/general/SpaceConsistencyBearTest.py
index c2019b3957..4e3d420285 100644
--- a/tests/general/SpaceConsistencyBearTest.py
+++ b/tests/general/SpaceConsistencyBearTest.py
@@ -44,21 +44,28 @@ 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_leading_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_leading_blanklines', 'true'))
 
         self.check_validity(self.uut,
                             ['hello world  \n'],
                             force_linebreaks=False)
         self.check_validity(self.uut,
                             ['def somecode():\n',
+                            [' \n',
+                             '\n',
+                             '     \n',
+                             'def somecode():\n',
                              "    print('funny')\n",
                              "    print('funny end.')\n"],
                             force_linebreaks=False)
@@ -70,3 +77,20 @@ def test_enforce_newline_at_eof(self):
                                "    print('funny')\n",
                                "    print('the result is not funny...')"],
                               force_linebreaks=False)
+
+    def test_leading_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_leading_blanklines', 'false'))
+
+        self.check_invalidity(self.uut,
+                              ['\n',
+                               '  \n',
+                               'def code():\n',
+                               "  print('Am I coding?')\n"],
+                              force_linebreaks=False)
+        self.check_validity(self.uut,
+                            ['def code():\n',
+                             "  print('Am I coding?')\n"],
+                            force_linebreaks=False)
diff --git a/tests/go/GoImportsBearTest.py b/tests/go/GoImportsBearTest.py
index 1a95e7ab6a..0e4a7e673c 100644
--- a/tests/go/GoImportsBearTest.py
+++ b/tests/go/GoImportsBearTest.py
@@ -1,4 +1,3 @@
-
 from bears.go.GoImportsBear import GoImportsBear
 from coalib.testing.LocalBearTestHelper import verify_local_bear