Repository: spyder-ide/spyder

Issue:
Warning/error on last row not in warning list
<!--- **PLEASE READ:** When submitting here, please ensure you've completed the following checklist and checked the boxes to confirm. Issue reports without it may be closed. Thanks! --->

### Issue Report Checklist

* [x] Searched the [issues page](https://github.com/spyder-ide/spyder/issues?q=is%3Aissue) for similar reports
* [x] Read the relevant sections of the [Spyder Troubleshooting Guide](https://github.com/spyder-ide/spyder/wiki/Troubleshooting-Guide-and-FAQ) and followed its advice
* [x] Reproduced the issue after updating with ``conda update spyder`` (or ``pip``, if not using Anaconda)
* [x] Tried basic troubleshooting (if a bug/error)
    * [x] Restarted Spyder
* [x] Completed the **Problem Description**, **Steps to Reproduce** and **Version** sections below


## Problem Description

If an error/warning is created on the last line of the file, it is shown in the editor, but does not show up in the menu (and therefore not in the pane I'm working on in #9836). Not a major issue (since most files should end with an empty line anyway, but still an issue (and I guess that code quality checks for that issue will not show up either). 

I also noted that the icons used are not the same as for the panel. Not sure if that is a bug or a feature though. (I aim at matching the editor panel icons in the pane).

![lastlinewarning](https://user-images.githubusercontent.com/8114497/62167249-18094a00-b323-11e9-9127-777ac10fd2f1.gif)

I can mention that I tried to sort it out, but simply iterating a few times more (by changing line 2072) didn't do the trick. So I do not expect that I will be able to solve it, hence posting this.
https://github.com/spyder-ide/spyder/blob/c188748789c8b069b5fc383061219f875fe36959/spyder/plugins/editor/widgets/codeeditor.py#L2063-L2079

Finally, can this dict:
https://github.com/spyder-ide/spyder/blob/c188748789c8b069b5fc383061219f875fe36959/spyder/plugins/editor/widgets/codeeditor.py#L1971-L1977
be defined in a single place so that it is possible to not have to redefine it when it should be used? I can move it there (as part of #9836), but may need suggestions where to put it. It is only used twice (second time in the pane), but if there is a well defined general place to put it, it may be better.

(Edit: Todos on the last row works, so no worries there.)

### What steps reproduce the problem?

1. Write something that generates a warning or error on the last line
2. Check the warnings menu/try to go to next/previous warning

### What is the expected output? What do you see instead?
The warning/error should be there.

(Maybe use consistent icon types.)


## Versions
<!--- You can get this information from Help > About Spyder...
or (if Spyder won't launch) the "conda list" command
from the Anaconda Prompt/Terminal/command line. --->

* Spyder version: 4.0.0.dev0
* Python version: 3.7.3 
* Qt version: 5.9.6
* PyQt version: 5.9.2
* Operating System name/version: Windows 10 

### Dependencies
<!--- Please go to the menu entry Help > Dependencies,
press the Copy to clipboard button and paste below --->

```
pygments >=2.0    :  2.4.2 (OK)
qdarkstyle >=2.6.4:  2.7 (OK)
sphinx >=0.6.6    :  2.1.2 (OK)
pyls >=0.27.0     :  0.27.0 (OK)
nbconvert >=4.0   :  5.5.0 (OK)
pandas >=0.13.1   :  0.24.2 (OK)
numpy >=1.7       :  1.16.4 (OK)
sympy >=0.7.3     :  1.4 (OK)
cython >=0.21     :  0.29.12 (OK)
qtconsole >=4.5.0 :  4.5.2 (OK)
IPython >=4.0     :  7.6.1 (OK)
matplotlib >=2.0.0:  3.1.0 (OK)
pylint >=0.25     :  2.3.1 (OK)

```



Discussion:
@dalthviz, please take a look at this one.

Resolving patch:
diff --git a/spyder/plugins/editor/widgets/codeeditor.py b/spyder/plugins/editor/widgets/codeeditor.py
--- a/spyder/plugins/editor/widgets/codeeditor.py
+++ b/spyder/plugins/editor/widgets/codeeditor.py
@@ -2069,12 +2069,13 @@ def get_current_warnings(self):
         line_count = self.document().blockCount()
         warnings = []
         while True:
-            if block.blockNumber() + 1 == line_count:
-                break
             data = block.userData()
             if data and data.code_analysis:
                 for warning in data.code_analysis:
                     warnings.append([warning[-1], block.blockNumber() + 1])
+            # See spyder-ide/spyder#9924
+            if block.blockNumber() + 1 == line_count:
+                break
             block = block.next()
         return warnings
 


Test patch:
diff --git a/spyder/plugins/editor/widgets/tests/test_warnings.py b/spyder/plugins/editor/widgets/tests/test_warnings.py
--- a/spyder/plugins/editor/widgets/tests/test_warnings.py
+++ b/spyder/plugins/editor/widgets/tests/test_warnings.py
@@ -24,7 +24,8 @@
         "    a = 1 # a comment\n"  # E261 two spaces before inline comment
         "\n"
         "    a += s\n"  # Undefined variable s
-        "    return a\n")
+        "    return a\n"
+        "undefined_function()")  # Undefined name 'undefined_function'
 
 
 @pytest.mark.slow
@@ -63,7 +64,11 @@ def test_ignore_warnings(qtbot, lsp_codeeditor):
 
     expected = [['D103: Missing docstring in public function', 1],
                 ['W293 blank line contains whitespace', 2],
-                ["undefined name 's'", 5]]
+                ["undefined name 's'", 5],
+                ["undefined name 'undefined_function'", 7],
+                ["W292 no newline at end of file", 7],
+                ["""E305 expected 2 blank lines after class or """
+                 """function definition, found 0""", 7]]
 
     CONF.set('lsp-server', 'pydocstyle/ignore', '')
     CONF.set('lsp-server', 'pycodestyle/ignore', '')
@@ -101,7 +106,8 @@ def test_adding_warnings(qtbot, lsp_codeeditor):
     expected_warnings = {1: ['D100', 'D103'],
                          2: ['W293'],
                          3: ['E261'],
-                         5: ['undefined name']}
+                         5: ['undefined name'],
+                         7: ['undefined name', 'W292', 'E305']}
     for i, warning in warnings:
         assert any([expected in warning for expected in expected_warnings[i]])
 
@@ -131,12 +137,12 @@ def test_move_warnings(qtbot, lsp_codeeditor):
     assert 2 == editor.get_cursor_line_number()
 
     # Test cycling behaviour
-    editor.go_to_line(5)
+    editor.go_to_line(7)
     editor.go_to_next_warning()
     assert 1 == editor.get_cursor_line_number()
 
     editor.go_to_previous_warning()
-    assert 5 == editor.get_cursor_line_number()
+    assert 7 == editor.get_cursor_line_number()
 
 
 @pytest.mark.slow
@@ -160,7 +166,11 @@ def test_get_warnings(qtbot, lsp_codeeditor):
                 ['D103: Missing docstring in public function', 1],
                 ['W293 blank line contains whitespace', 2],
                 ['E261 at least two spaces before inline comment', 3],
-                ["undefined name 's'", 5]]
+                ["undefined name 's'", 5],
+                ["undefined name 'undefined_function'", 7],
+                ["W292 no newline at end of file", 7],
+                ["""E305 expected 2 blank lines after class or """
+                 """function definition, found 0""", 7]]
 
     assert warnings == expected
 
@@ -193,7 +203,11 @@ def test_update_warnings_after_delete_line(qtbot, lsp_codeeditor):
     expected = [['D100: Missing docstring in public module', 1],
                 ['D103: Missing docstring in public function', 1],
                 ['E261 at least two spaces before inline comment', 2],
-                ["undefined name 's'", 4]]
+                ["undefined name 's'", 4],
+                ["undefined name 'undefined_function'", 6],
+                ["W292 no newline at end of file", 6],
+                ["""E305 expected 2 blank lines after class or """
+                 """function definition, found 0""", 6]]
     assert editor.get_current_warnings() == expected
 
 
@@ -243,7 +257,8 @@ def test_update_warnings_after_closebrackets(qtbot, lsp_codeeditor):
     editor, _ = lsp_codeeditor
     editor.textCursor().insertText("print('test'\n")
 
-    expected = [['unexpected EOF while parsing', 1]]
+    expected = [['unexpected EOF while parsing', 1],
+                ['E901 TokenError: EOF in multi-line statement', 2]]
 
     # Notify changes.
     with qtbot.waitSignal(editor.lsp_response_signal, timeout=30000):