Git commit e4328a41f90d5c619e329fa15a5923791d537a8f by Christoph Cullmann, on 
behalf of Waqar Ahmed.
Committed on 12/11/2022 at 18:56.
Pushed by cullmann into branch 'master'.

lsp: Add format on save

M  +6    -18   addons/lspclient/lspclientconfigpage.cpp
M  +3    -0    addons/lspclient/lspclientplugin.cpp
M  +1    -0    addons/lspclient/lspclientplugin.h
M  +23   -2    addons/lspclient/lspclientpluginview.cpp
M  +29   -23   addons/lspclient/lspconfigwidget.ui
M  +9    -0    doc/kate/plugins.docbook

https://invent.kde.org/utilities/kate/commit/e4328a41f90d5c619e329fa15a5923791d537a8f

diff --git a/addons/lspclient/lspclientconfigpage.cpp 
b/addons/lspclient/lspclientconfigpage.cpp
index 08005cde8..0ecbbe01f 100644
--- a/addons/lspclient/lspclientconfigpage.cpp
+++ b/addons/lspclient/lspclientconfigpage.cpp
@@ -48,24 +48,10 @@ LSPClientConfigPage::LSPClientConfigPage(QWidget *parent, 
LSPClientPlugin *plugi
     reset();
 
     for (const auto &cb : {
-             ui->chkSymbolDetails,
-             ui->chkSymbolExpand,
-             ui->chkSymbolSort,
-             ui->chkSymbolTree,
-             ui->chkComplDoc,
-             ui->chkRefDeclaration,
-             ui->chkComplParens,
-             ui->chkDiagnostics,
-             ui->chkDiagnosticsMark,
-             ui->chkDiagnosticsHover,
-             ui->chkMessages,
-             ui->chkOnTypeFormatting,
-             ui->chkIncrementalSync,
-             ui->chkHighlightGoto,
-             ui->chkSemanticHighlighting,
-             ui->chkAutoHover,
-             ui->chkSignatureHelp,
-             ui->chkAutoImport,
+             ui->chkSymbolDetails,  ui->chkSymbolExpand,     
ui->chkSymbolSort,      ui->chkSymbolTree,      ui->chkComplDoc,
+             ui->chkRefDeclaration, ui->chkComplParens,      
ui->chkDiagnostics,     ui->chkDiagnosticsMark, ui->chkDiagnosticsHover,
+             ui->chkMessages,       ui->chkOnTypeFormatting, 
ui->chkIncrementalSync, ui->chkHighlightGoto,   ui->chkSemanticHighlighting,
+             ui->chkAutoHover,      ui->chkSignatureHelp,    
ui->chkAutoImport,      ui->chkFmtOnSave,
          }) {
         connect(cb, &QCheckBox::toggled, this, &LSPClientConfigPage::changed);
     }
@@ -149,6 +135,7 @@ void LSPClientConfigPage::apply()
     m_plugin->m_semanticHighlighting = 
ui->chkSemanticHighlighting->isChecked();
     m_plugin->m_signatureHelp = ui->chkSignatureHelp->isChecked();
     m_plugin->m_autoImport = ui->chkAutoImport->isChecked();
+    m_plugin->m_fmtOnSave = ui->chkFmtOnSave->isChecked();
 
     m_plugin->m_messages = ui->chkMessages->isChecked();
 
@@ -196,6 +183,7 @@ void LSPClientConfigPage::reset()
     ui->chkSemanticHighlighting->setChecked(m_plugin->m_semanticHighlighting);
     ui->chkSignatureHelp->setChecked(m_plugin->m_signatureHelp);
     ui->chkAutoImport->setChecked(m_plugin->m_autoImport);
+    ui->chkFmtOnSave->setChecked(m_plugin->m_fmtOnSave);
 
     ui->chkMessages->setChecked(m_plugin->m_messages);
 
diff --git a/addons/lspclient/lspclientplugin.cpp 
b/addons/lspclient/lspclientplugin.cpp
index 85e073a16..f00723e88 100644
--- a/addons/lspclient/lspclientplugin.cpp
+++ b/addons/lspclient/lspclientplugin.cpp
@@ -45,6 +45,7 @@ static const QString 
CONFIG_SIGNATURE_HELP{QStringLiteral("SignatureHelp")};
 static const QString CONFIG_AUTO_IMPORT{QStringLiteral("AutoImport")};
 static const QString 
CONFIG_ALLOWED_COMMANDS{QStringLiteral("AllowedServerCommandLines")};
 static const QString 
CONFIG_BLOCKED_COMMANDS{QStringLiteral("BlockedServerCommandLines")};
+static const QString CONFIG_FORMAT_ON_SAVE{QStringLiteral("FormatOnSave")};
 
 K_PLUGIN_FACTORY_WITH_JSON(LSPClientPluginFactory, "lspclientplugin.json", 
registerPlugin<LSPClientPlugin>();)
 
@@ -132,6 +133,7 @@ void LSPClientPlugin::readConfig()
     m_semanticHighlighting = config.readEntry(CONFIG_SEMANTIC_HIGHLIGHTING, 
true);
     m_signatureHelp = config.readEntry(CONFIG_SIGNATURE_HELP, true);
     m_autoImport = config.readEntry(CONFIG_AUTO_IMPORT, true);
+    m_fmtOnSave = config.readEntry(CONFIG_FORMAT_ON_SAVE, false);
 
     // read allow + block lists as two separate keys, let block always win
     const auto allowed = config.readEntry(CONFIG_ALLOWED_COMMANDS, 
QStringList());
@@ -171,6 +173,7 @@ void LSPClientPlugin::writeConfig() const
     config.writeEntry(CONFIG_SEMANTIC_HIGHLIGHTING, m_semanticHighlighting);
     config.writeEntry(CONFIG_SIGNATURE_HELP, m_signatureHelp);
     config.writeEntry(CONFIG_AUTO_IMPORT, m_autoImport);
+    config.writeEntry(CONFIG_FORMAT_ON_SAVE, m_fmtOnSave);
 
     // write allow + block lists as two separate keys
     QStringList allowed, blocked;
diff --git a/addons/lspclient/lspclientplugin.h 
b/addons/lspclient/lspclientplugin.h
index 3df99a83f..d54a3a5cc 100644
--- a/addons/lspclient/lspclientplugin.h
+++ b/addons/lspclient/lspclientplugin.h
@@ -62,6 +62,7 @@ public:
     bool m_semanticHighlighting = false;
     bool m_signatureHelp = true;
     bool m_autoImport = true;
+    bool m_fmtOnSave = false;
 
     // debug mode?
     const bool m_debugMode;
diff --git a/addons/lspclient/lspclientpluginview.cpp 
b/addons/lspclient/lspclientpluginview.cpp
index 23cad2a71..5543800e5 100644
--- a/addons/lspclient/lspclientpluginview.cpp
+++ b/addons/lspclient/lspclientpluginview.cpp
@@ -2167,7 +2167,7 @@ public:
         });
     }
 
-    void format(QChar lastChar = QChar())
+    void format(QChar lastChar = QChar(), bool save = false)
     {
         KTextEditor::View *activeView = m_mainWindow->activeView();
         QPointer<KTextEditor::Document> document = activeView->document();
@@ -2186,7 +2186,7 @@ public:
         // sigh, no move initialization capture ...
         // (again) assuming reply ranges wrt revisions submitted at this time
         QSharedPointer<LSPClientRevisionSnapshot> 
snapshot(m_serverManager->snapshot(server.data()));
-        auto h = [this, document, snapshot, lastChar](const QList<LSPTextEdit> 
&edits) {
+        auto h = [this, document, snapshot, lastChar, save](const 
QList<LSPTextEdit> &edits) {
             if (lastChar.isNull()) {
                 checkEditResult(edits);
             }
@@ -2197,6 +2197,11 @@ public:
                 m_onTypeFormattingTriggers.clear();
                 applyEdits(document, snapshot.data(), edits);
                 m_onTypeFormattingTriggers = savedTriggers;
+                if (save) {
+                    disconnect(document, 
&KTextEditor::Document::documentSavedOrUploaded, this, 
&self_type::formatOnSave);
+                    document->documentSave();
+                    connect(document, 
&KTextEditor::Document::documentSavedOrUploaded, this, 
&self_type::formatOnSave);
+                }
             }
         };
 
@@ -2965,6 +2970,15 @@ public:
         }
     }
 
+    void formatOnSave(KTextEditor::Document *doc, bool)
+    {
+        // only trigger for active doc
+        auto activeView = m_mainWindow->activeView();
+        if (activeView && activeView->document() == doc) {
+            format({}, true);
+        }
+    }
+
     void updateState()
     {
         KTextEditor::View *activeView = m_mainWindow->activeView();
@@ -2978,6 +2992,7 @@ public:
         bool selectionRangeEnabled = false;
         bool isClangd = false;
         bool isRustAnalyzer = false;
+        bool formatOnSave = false;
 
         if (server) {
             const auto &caps = server->capabilities();
@@ -2992,6 +3007,7 @@ public:
             renameEnabled = caps.renameProvider;
             codeActionEnabled = caps.codeActionProvider;
             selectionRangeEnabled = caps.selectionRangeProvider;
+            formatOnSave = formatEnabled && m_plugin->m_fmtOnSave;
 
             connect(server.data(), &LSPClientServer::publishDiagnostics, this, 
&self_type::onDiagnostics, Qt::UniqueConnection);
             connect(server.data(), &LSPClientServer::applyEdit, this, 
&self_type::onApplyEdit, Qt::UniqueConnection);
@@ -3092,6 +3108,11 @@ public:
 
         updateMarks(doc);
 
+        if (formatOnSave) {
+            auto t = Qt::ConnectionType(Qt::UniqueConnection | 
Qt::QueuedConnection);
+            connect(activeView->document(), 
&KTextEditor::Document::documentSavedOrUploaded, this, 
&self_type::formatOnSave, t);
+        }
+
         // connect for cleanup stuff
         if (activeView) {
             connect(activeView, &KTextEditor::View::destroyed, this, 
&self_type::viewDestroyed, Qt::UniqueConnection);
diff --git a/addons/lspclient/lspconfigwidget.ui 
b/addons/lspclient/lspconfigwidget.ui
index c6cf6581c..4bdf8be52 100644
--- a/addons/lspclient/lspconfigwidget.ui
+++ b/addons/lspclient/lspconfigwidget.ui
@@ -41,49 +41,49 @@
          <property name="bottomMargin">
           <number>0</number>
          </property>
-         <item row="2" column="0">
+         <item row="3" column="0">
           <widget class="QLabel" name="label_2">
            <property name="text">
             <string>Completions:</string>
            </property>
           </widget>
          </item>
-         <item row="2" column="1">
+         <item row="3" column="1">
           <widget class="QCheckBox" name="chkComplDoc">
            <property name="text">
             <string>Show inline docs for selected completion</string>
            </property>
           </widget>
          </item>
-         <item row="3" column="1">
+         <item row="4" column="1">
           <widget class="QCheckBox" name="chkSignatureHelp">
            <property name="text">
             <string>Show function signature when typing a function 
call</string>
            </property>
           </widget>
          </item>
-         <item row="4" column="1">
+         <item row="5" column="1">
           <widget class="QCheckBox" name="chkComplParens">
            <property name="text">
             <string>Add parentheses upon function completion</string>
            </property>
           </widget>
          </item>
-         <item row="6" column="0">
+         <item row="7" column="0">
           <widget class="QLabel" name="label_4">
            <property name="text">
             <string>Diagnostics:</string>
            </property>
           </widget>
          </item>
-         <item row="6" column="1">
+         <item row="7" column="1">
           <widget class="QCheckBox" name="chkDiagnostics">
            <property name="text">
             <string>Show program diagnostics</string>
            </property>
           </widget>
          </item>
-         <item row="7" column="1">
+         <item row="8" column="1">
           <layout class="QVBoxLayout" name="verticalLayout_7">
            <property name="leftMargin">
             <number>20</number>
@@ -127,70 +127,70 @@
            </item>
           </layout>
          </item>
-         <item row="8" column="0">
+         <item row="9" column="0">
           <widget class="QLabel" name="label_5">
            <property name="text">
             <string>Navigation:</string>
            </property>
           </widget>
          </item>
-         <item row="8" column="1">
+         <item row="9" column="1">
           <widget class="QCheckBox" name="chkRefDeclaration">
            <property name="text">
             <string>Count declarations when searching for references to a 
symbol</string>
            </property>
           </widget>
          </item>
-         <item row="9" column="1">
+         <item row="10" column="1">
           <widget class="QCheckBox" name="chkAutoHover">
            <property name="text">
             <string>Show information about currently hovered symbol</string>
            </property>
           </widget>
          </item>
-         <item row="10" column="1">
+         <item row="11" column="1">
           <widget class="QCheckBox" name="chkHighlightGoto">
            <property name="text">
             <string>Highlight target line when hopping to it</string>
            </property>
           </widget>
          </item>
-         <item row="11" column="0">
+         <item row="12" column="0">
           <widget class="QLabel" name="label_3">
            <property name="text">
             <string>Server:</string>
            </property>
           </widget>
          </item>
-         <item row="11" column="1">
+         <item row="12" column="1">
           <widget class="QCheckBox" name="chkMessages">
            <property name="text">
             <string>Show notifications from the LSP server</string>
            </property>
           </widget>
          </item>
-         <item row="12" column="1">
+         <item row="13" column="1">
           <widget class="QCheckBox" name="chkIncrementalSync">
            <property name="text">
             <string>Incrementally synchronize documents with the LSP 
server</string>
            </property>
           </widget>
          </item>
-         <item row="14" column="1">
+         <item row="15" column="1">
           <widget class="QCheckBox" name="chkSymbolDetails">
            <property name="text">
             <string>Display additional details for symbols</string>
            </property>
           </widget>
          </item>
-         <item row="15" column="1">
+         <item row="16" column="1">
           <widget class="QCheckBox" name="chkSymbolTree">
            <property name="text">
             <string>Present symbols in a hierarchy instead of a flat 
list</string>
            </property>
           </widget>
          </item>
-         <item row="16" column="1">
+         <item row="17" column="1">
           <layout class="QHBoxLayout" name="horizontalLayout_4">
            <property name="leftMargin">
             <number>20</number>
@@ -207,21 +207,21 @@
            </item>
           </layout>
          </item>
-         <item row="13" column="1">
+         <item row="14" column="1">
           <widget class="QCheckBox" name="chkSymbolSort">
            <property name="text">
             <string>Sort symbols alphabetically</string>
            </property>
           </widget>
          </item>
-         <item row="13" column="0">
+         <item row="14" column="0">
           <widget class="QLabel" name="label_6">
            <property name="text">
             <string>Document outline:</string>
            </property>
           </widget>
          </item>
-         <item row="1" column="1">
+         <item row="2" column="1">
           <widget class="QCheckBox" name="chkSemanticHighlighting">
            <property name="text">
             <string>Enable semantic highlighting</string>
@@ -235,13 +235,20 @@
            </property>
           </widget>
          </item>
-         <item row="5" column="1">
+         <item row="6" column="1">
           <widget class="QCheckBox" name="chkAutoImport">
            <property name="text">
             <string>Add imports automatically if needed upon 
completion</string>
            </property>
           </widget>
          </item>
+         <item row="1" column="1">
+          <widget class="QCheckBox" name="chkFmtOnSave">
+           <property name="text">
+            <string>Format on save</string>
+           </property>
+          </widget>
+         </item>
         </layout>
        </item>
        <item>
@@ -293,8 +300,7 @@
         </layout>
        </item>
        <item>
-        <widget class="QPlainTextEdit" name="userConfig">
-        </widget>
+        <widget class="QPlainTextEdit" name="userConfig"/>
        </item>
        <item>
         <widget class="QLabel" name="userConfigError">
diff --git a/doc/kate/plugins.docbook b/doc/kate/plugins.docbook
index ab950b333..590c5335a 100644
--- a/doc/kate/plugins.docbook
+++ b/doc/kate/plugins.docbook
@@ -2797,6 +2797,15 @@ transformed to the &JSON; configuration that is used 
here and outlined above.
 
 </sect3>
 
+<sect3 id="lspclient-format-on-save">
+<title>LSP Server Format On Save</title>
+
+<para>
+You can enable "format on save" from LSP settings in configure dialog.
+</para>
+
+</sect3>
+
 <sect3 id="lspclient-diagnostics-suppression">
 <title>LSP Server Diagnostic Suppression</title>
 

Reply via email to