https://bugs.kde.org/show_bug.cgi?id=442903

Igor Kushnir <igor...@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
         Resolution|---                         |FIXED
      Latest Commit|                            |https://invent.kde.org/kdev
                   |                            |elop/kdevelop/-/commit/1b60
                   |                            |b1dd18fb8f26c451c4ede77011e
                   |                            |13aa7fcac
             Status|ASSIGNED                    |RESOLVED
   Version Fixed In|                            |5.13.231200

--- Comment #3 from Igor Kushnir <igor...@gmail.com> ---
Git commit 1b60b1dd18fb8f26c451c4ede77011e13aa7fcac by Igor Kushnir.
Committed on 15/09/2023 at 11:57.
Pushed by igorkushnir into branch 'master'.

Overhaul SourceFormatterSelectionEdit

Don't select the first style automatically. The first style in the list
is not likely to match the user's preferred style. Let the user select a
style for each language [s]he cares about. Leave the other languages
with no selected style. Delete config entries of MIME types that belong
to languages with no selected style when settings are saved.

There were several issues with the old behavior replaced in this commit:
1. If the user didn't explicitly select a formatter or a style for a
   language, the first formatter in the list and its first style were
   preselected and stored in config for that language when settings were
   saved. Worse still, the GNU_indent_GNU style was stored for Python
   and Python 3 languages, even though this style does not support the
   Python languages and cannot be selected in the UI (Bug 442903).
2. It was possible to unselect a style in the UI via Ctrl+Click on the
   selected style. But SourceFormatterSelectionEdit completely ignored
   such deselection. The last deselected style was considered selected
   because QListWidget::currentItem() returned it. Now there is a
   well-defined no-style-selected state because:
   * QItemSelectionModel::selectedIndexes() is used instead of
     QListWidget::currentItem();
   * &QListWidget::itemSelectionChanged signal is connected to instead
     of &QListWidget::currentRowChanged.
3. The Apply button became enabled when language selection changed, even
   though merely selecting a different language does not modify
   formatting configuration. This behavior could reinforce possible user
   misunderstanding of the configuration: that selecting a language
   assigns it to an open project (Bug 358798).
4. The order of plugins in the Formatter combobox was not fixed, because
   LanguageSettings::formatters was an unordered QSet. So each time the
   Configure KDevelop... dialog was opened, the first (and preselected)
   item was unpredictably Artistic Style or Custom Script Formatter.

Invisible bugs fixed in this commit:
1. QMap::iterator::value() was called on the iterator already erased
   from QMap SourceFormatterSelectionEditPrivate::formatters in
   SourceFormatterSelectionEdit::removeSourceFormatter(). This was
   undefined behavior, which hasn't revealed itself yet.
2. SourceFormatterSelectionEdit::deleteStyle() erased the current style
   from StyleMap SourceFormatter::styles, but failed to destroy the
   SourceFormatterStyle object. This was a memory leak.

Error-prone manual memory management was eliminated:
1. SourceFormatter struct contained a QMap with mapped_type = owning raw
   SourceFormatterStyle pointer, which had to be deleted manually. Now
   FormatterData class contains a std::map with mapped_type =
   SourceFormatterStyle value.
2. Similarly, SourceFormatterSelectionEditPrivate::formatters was a
   QMap<QString, SourceFormatter*> with owning raw pointers. Now it is a
   std::vector<std::unique_ptr<FormatterData>>.

Optimizations:
1. LanguageSettings::mimetypes contained many duplicates because every
   MIME type of each supporting style was unconditionally appended to
   this list. SourceFormatterSelectionEdit::loadSettings() read and
   SourceFormatterSelectionEdit::saveSettings() wrote a config entry for
   each MIME type in this list. Now duplicate MIME types are not added
   to LanguageSettings::m_mimeTypes.
2. Most styles return the same built-in list from
   SourceFormatterStyle::mimeTypes(). Cache already encountered MIME
   lists and don't process duplicates. This optimization requires newly
   implemented operator== for SourceFormatterStyle::MimeHighlightPair.
3. Widgets' signals weren't blocked consistently. So the same code often
   run repeatedly and redundantly. For example, when
   SourceFormatterSelectionEdit::selectStyle() called
   QListWidget::setCurrentRow(), and the row actually changed,
   selectStyle() was called again. Infinite recursion was prevented by
   an early return when the current index did not change inside
   QItemSelectionModel::setCurrentIndex().
4. updatePreview(), enableStyleButtons() and changed() were often called
   repeatedly and redundantly when SourceFormatterSelectionEdit's public
   member functions invoked other public member functions.
5. Store addresses rather than names of formatters and styles as user
   data in QComboBox and QListWidget. The pointer stability of these
   FormatterData and SourceFormatterStyle objects is already necessary
   and guaranteed to prevent invalidating selected formatter and style
   pointers. Storing pointers replaces name lookup (search) with direct
   object access.
6. Use std::vector instead of QMap, QSet and QList to store small (< 10)
   numbers of elements. The impact of this container choice on code
   complexity is ambiguous (it has both pros and cons), but it is surely
   more efficient.

Other improvements:
1. Hide ui.descriptionLabel if the selected style's description is empty
   (which is the case for most styles). This leaves more vertical space
   to the style preview widget.
2. Don't disable Language and Formatter comboboxes and the Styles list
   widget when they are empty. The user cannot do anything with these
   empty widgets anyway. The code is shorter and less error-prone
   without the disabling and enabling.
3. Cache the currently selected language in
   SourceFormatterSelectionEditPrivate::currentLanguagePtr. The current
   language rarely changes, so the cache requires little supporting
   code. This data member cache allows to call currentLanguage()
   whenever needed instead of caching in a local variable as before:
   LanguageSettings& l = d->languages[d->ui.cbLanguages->currentText()];
4. Extract reading {MIME type => selected formatter and style} config
   entries into a new class SourceFormatter::ConfigForMimeType and use
   it in SourceFormatterController and SourceFormatterSelectionEdit
   instead of duplicating the parsing code. ConfigForMimeType's extra
   validation made the parsing stricter than it was in
   SourceFormatterSelectionEdit, which should be fine: better to ignore
   broken config entries than try to use them somehow.
5. If the style stored in the config for a language does not support
   this language, don't select it and print a warning.
6. qCDebug => qCWarning when a config entry is broken. Make these
   messages more informative.
7. Add assertions to help detect bugs sooner.
8. Add code documentation and comments.
FIXED-IN: 5.13.231200

M  +8    -0    kdevplatform/interfaces/isourceformatter.h
M  +1    -0    kdevplatform/shell/CMakeLists.txt
A  +106  -0    kdevplatform/shell/sourceformatterconfig.h     [License:
LGPL(v2.0+)]
M  +37   -32   kdevplatform/shell/sourceformattercontroller.cpp
M  +9    -22   kdevplatform/shell/sourceformattercontroller.h
M  +775  -369  kdevplatform/shell/sourceformatterselectionedit.cpp
M  +2    -7    kdevplatform/shell/sourceformatterselectionedit.h
M  +1    -1    kdevplatform/shell/sourceformatterselectionedit.ui

https://invent.kde.org/kdevelop/kdevelop/-/commit/1b60b1dd18fb8f26c451c4ede77011e13aa7fcac

-- 
You are receiving this mail because:
You are watching all bug changes.

Reply via email to