Repository: spyder-ide/spyder

Issue:
Analyze Button of Code Pane doesn't respect save before analysis Preference
<!--- **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] Completed the **Problem Description**, **Steps to Reproduce** and **Version** sections below


## Problem Description
With the respective preference chosen,  
starting a Code Analysis by pressing F8 saves the code file beforehand,  
but the Analyze Button of the Code Analysis Pane doesn't respect the preference.

### What steps reproduce the problem?

![Code Analysis](https://user-images.githubusercontent.com/32204163/59719214-30625100-921c-11e9-94a0-09e7d6440411.gif)
1. Set the Preference `Code Analysis -> Save file before analyzing it`
2. Modify some code, but don't save
3. Bring the Code Analysis Pane into the foreground and click the button with the green triangle


## 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.0dev2
* Python version: Python 3.6.8 64-bit
* Qt version: Qt 5.12.3
* PyQt version: PyQt5 5.12.2
* Operating System name/version: Fedora 28 Linux 5.0.16-100.fc28.x86_64 

### 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.1 (OK)
psutil >=0.3       :  5.6.3 (OK)
pyls >=0.19.0;<0.25:  0.24.0 (OK)
nbconvert >=4.0    :  5.5.0 (OK)
pandas >=0.13.1    :  0.22.0 (OK)
numpy >=1.7        :  1.14.5 (OK)
sympy >=0.7.3      :  1.2 (OK)
cython >=0.21      :  0.29.10 (OK)
qtconsole >=4.2.0  :  4.5.1 (OK)
IPython >=4.0      :  7.5.0 (OK)
matplotlib >=2.0.0 :  2.2.3 (OK)
pylint >=0.25      :  2.3.1 (OK)



Discussion:
Thanks for reporting. We'll try to fix this in beta4.

Resolving patch:
diff --git a/spyder/plugins/pylint/plugin.py b/spyder/plugins/pylint/plugin.py
--- a/spyder/plugins/pylint/plugin.py
+++ b/spyder/plugins/pylint/plugin.py
@@ -67,6 +67,10 @@ def __init__(self, parent=None):
         # Follow editorstacks tab change
         self.main.editor.sig_editor_focus_changed.connect(self.set_filename)
 
+        # Used by Analyze button to check if file should be saved and start
+        # analysis
+        self.pylint.start_analysis.connect(self.run_pylint_from_analyze_button)
+
     #------ SpyderPluginWidget API --------------------------------------------
     def get_plugin_title(self):
         """Return widget title"""
@@ -153,3 +157,16 @@ def analyze(self, filename):
         if self.dockwidget:
             self.switch_to_plugin()
         self.pylint.analyze(filename)
+
+    @Slot()
+    def run_pylint_from_analyze_button(self):
+        """
+        See if file should and can be saved and run pylint code analysis.
+
+        Does not check that file name is valid etc, so should only be used for
+        Analyze button.
+        """
+        if (self.get_option('save_before', True)
+                and not self.main.editor.save()):
+            return
+        self.pylint.start()
diff --git a/spyder/plugins/pylint/widgets/pylintgui.py b/spyder/plugins/pylint/widgets/pylintgui.py
--- a/spyder/plugins/pylint/widgets/pylintgui.py
+++ b/spyder/plugins/pylint/widgets/pylintgui.py
@@ -148,6 +148,7 @@ class PylintWidget(QWidget):
     DATAPATH = get_conf_path('pylint.results')
     VERSION = '1.1.0'
     redirect_stdio = Signal(bool)
+    start_analysis = Signal()
 
     def __init__(self, parent, max_entries=100, options_button=None,
                  text_color=None, prevrate_color=None):
@@ -176,7 +177,8 @@ def __init__(self, parent, max_entries=100, options_button=None,
         self.start_button = create_toolbutton(self, icon=ima.icon('run'),
                                     text=_("Analyze"),
                                     tip=_("Run analysis"),
-                                    triggered=self.start, text_beside_icon=True)
+                                    triggered=self.analyze_button_handler,
+                                    text_beside_icon=True)
         self.stop_button = create_toolbutton(self,
                                              icon=ima.icon('stop'),
                                              text=_("Stop"),
@@ -310,8 +312,14 @@ def show_log(self):
             TextEditor(self.output, title=_("Pylint output"),
                        readonly=True, size=(700, 500)).exec_()
 
+    @Slot()
+    def analyze_button_handler(self):
+        """Try to start code analysis when Analyze button pressed."""
+        self.start_analysis.emit()
+
     @Slot()
     def start(self):
+        """Start the code analysis."""
         filename = to_text_string(self.filecombo.currentText())
 
         self.process = QProcess(self)


Test patch: