Repository: psf/black
Pull request: Remove newline after code block open
### Description

Fixes #902

Newlines are great. They help us organize our code and leave room for the coders and reviewers to breath.
However, too many newlines can make simple code gigantic and massive. This is unnecessary in a lot of cases.

I want to argue that having a newline right after `def` is redundant and Black should remove it.
**EDIT**: We decided to remove trailing newlines for *all code blocks*, including `def`

Now, the following code:
```python
def f():

    print("No newline above me!")

    print("There is a newline above me, and that's OK!")
```

will be changed by *Black* to:
```python
def f():
    print("No newline above me!")

    print("There is a newline above me, and that's OK!")
```

### Checklist - did you ...

<!-- If any of the following items aren't relevant for your contribution
     please still tick them so we know you've gone through the checklist.

    All user-facing changes should get an entry. Otherwise, signal to us
    this should get the magical label to silence the CHANGELOG entry check.
    Tests are required for bugfixes and new features. Documentation changes
    are necessary for formatting and most enhancement changes. -->

- [x] Add a CHANGELOG entry if necessary?
- [X] Add / update tests if necessary?
- [X] Add new / update outdated documentation?

<!-- Just as a reminder, everyone in all psf/black spaces including PRs
     must follow the PSF Code of Conduct (link below).

     Finally, once again thanks for your time and effort. If you have any
     feedback in regards to your experience contributing here, please
     let us know!

     Helpful links:

      PSF COC: https://www.python.org/psf/conduct/
      Contributing docs: https://black.readthedocs.io/en/latest/contributing/index.html
      Chat on Python Discord: https://discord.gg/RtVdv86PrH -->


Problem statement:
Black should enforce zero empty leading lines in function body 
Operating system: playground
Python version: playground
*Black* version: master

Consider following code snippet:
```python
class X:
    
    
    def f(self, x):
        
        
        return x**2
```

When class definition is formatted, empty lines between `class X:` line and first node of the body is forced to be zero.
When function definition is formatted, empty lines between `def f():` line and first node of the body is normalised to either 0 (if input code had 0 empty lines) or 1 (if input code had 1+ empty lines).

While it's preferable to preserve some of the empty lines of input code, doing this for *leading* empty lines of node body makes no sense, as this empty line cannot have any mental meaning in such context.

Hints from issue discussion:
I would assume this should also apply to classes, and I'd go as far as to say that all blocks should have their leading vertical whitespace removed, for example:

```python
if a:

    b
```

But they could surely be taken care of in separate issues. More like a mental note for now.
That sounds right I can't think of any reason to have blank lines around an increase in indent level, the increase it self is quite visually clear.
It's a bit different with dedents which often end logical blocks.

Commit message: Added more tests

Patch to review:
diff --git a/CHANGES.md b/CHANGES.md
index 566077b1dbc..19b4eef9a8c 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -12,6 +12,7 @@
 
 - Fix unstable formatting involving `# fmt: skip` comments without internal spaces
   (#2970)
+- trailing newlines are removed right after `def` statement (#3035)
 
 ### Preview style
 
diff --git a/src/black/lines.py b/src/black/lines.py
index e455a507539..2dd3ee92fe0 100644
--- a/src/black/lines.py
+++ b/src/black/lines.py
@@ -513,6 +513,12 @@ def _maybe_empty_lines(self, current_line: Line) -> Tuple[int, int]:
         ):
             return before, 1
 
+        if (
+            self.previous_line
+            and self.previous_line.is_def
+            and depth == self.previous_line.depth + 1
+        ):
+            return 0, 0
         return before, 0
 
     def _maybe_empty_lines_for_class_or_def(
diff --git a/tests/data/newline_after_def1.py b/tests/data/newline_after_def1.py
new file mode 100644
index 00000000000..85381b43821
--- /dev/null
+++ b/tests/data/newline_after_def1.py
@@ -0,0 +1,8 @@
+def foo():
+
+    print("The newline above me should be deleted!")
+
+# output
+
+def foo():
+    print("The newline above me should be deleted!")
diff --git a/tests/data/newline_after_def2.py b/tests/data/newline_after_def2.py
new file mode 100644
index 00000000000..2d586583d2a
--- /dev/null
+++ b/tests/data/newline_after_def2.py
@@ -0,0 +1,10 @@
+def foo():
+
+
+
+    print("All the newlines above me should be deleted!")
+
+# output
+
+def foo():
+    print("All the newlines above me should be deleted!")
diff --git a/tests/data/newline_after_def3.py b/tests/data/newline_after_def3.py
new file mode 100644
index 00000000000..92b7480abec
--- /dev/null
+++ b/tests/data/newline_after_def3.py
@@ -0,0 +1,12 @@
+def f():
+
+    print("No newline above me!")
+
+    print("There is a newline above me, and that's OK!")
+
+# output
+
+def f():
+    print("No newline above me!")
+
+    print("There is a newline above me, and that's OK!")
diff --git a/tests/data/newline_after_def4.py b/tests/data/newline_after_def4.py
new file mode 100644
index 00000000000..4d6717261c8
--- /dev/null
+++ b/tests/data/newline_after_def4.py
@@ -0,0 +1,12 @@
+def foo():
+
+    # There is a comment here
+
+    print("The newline above me should not be deleted!")
+
+# output
+
+def foo():
+    # There is a comment here
+
+    print("The newline above me should not be deleted!")
diff --git a/tests/data/newline_after_def5.py b/tests/data/newline_after_def5.py
new file mode 100644
index 00000000000..d6c383ee36a
--- /dev/null
+++ b/tests/data/newline_after_def5.py
@@ -0,0 +1,10 @@
+class Foo:
+    def bar(self):
+
+        print("The newline above me should be deleted!")
+
+# output
+
+class Foo:
+    def bar(self):
+        print("The newline above me should be deleted!")
diff --git a/tests/test_black.py b/tests/test_black.py
index f6663fa5797..aad6b02d680 100644
--- a/tests/test_black.py
+++ b/tests/test_black.py
@@ -1451,7 +1451,6 @@ def test_newline_comment_interaction(self) -> None:
         black.assert_stable(source, output, mode=DEFAULT_MODE)
 
     def test_bpo_2142_workaround(self) -> None:
-
         # https://bugs.python.org/issue2142
 
         source, _ = read_data("missing_final_newline.py")
diff --git a/tests/test_format.py b/tests/test_format.py
index 1916146e84d..87d5a755730 100644
--- a/tests/test_format.py
+++ b/tests/test_format.py
@@ -50,6 +50,11 @@
     "function2",
     "function_trailing_comma",
     "import_spacing",
+    "newline_after_def1",
+    "newline_after_def2",
+    "newline_after_def3",
+    "newline_after_def4",
+    "newline_after_def5",
     "power_op_spacing",
     "remove_parens",
     "slices",


Code review comments:
diff_hunk: @@ -12,6 +12,7 @@
 
 - Fix unstable formatting involving `# fmt: skip` comments without internal spaces
   (#2970)
+- trailing newlines are removed right after `def` statement (#3035)
path: CHANGES.md
text: @user1:
This must go into the preview style first, following our stability policy. You'll have to add a new preview feature too; check the other PRs in the "Preview style" section for examples.

Also, wording suggestion:
```suggestion
- Remove trailing newlines after `def` lines (#3035)
```