Index: src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetSelector.java
===================================================================
--- src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetSelector.java	(revision 18967)
+++ src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetSelector.java	(working copy)
@@ -4,6 +4,7 @@
 import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.BorderLayout;
+import java.awt.Color;
 import java.awt.Component;
 import java.awt.Dimension;
 import java.awt.event.ActionEvent;
@@ -12,12 +13,15 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.EnumSet;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
+import java.util.function.Predicate;
 import java.util.regex.Pattern;
 
 import javax.swing.AbstractAction;
@@ -40,6 +44,8 @@
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.preferences.BooleanProperty;
 import org.openstreetmap.josm.gui.MainApplication;
+import org.openstreetmap.josm.gui.tagging.presets.items.Check;
+import org.openstreetmap.josm.gui.tagging.presets.items.CheckGroup;
 import org.openstreetmap.josm.gui.tagging.presets.items.ComboMultiSelect;
 import org.openstreetmap.josm.gui.tagging.presets.items.Key;
 import org.openstreetmap.josm.gui.tagging.presets.items.KeyedItem;
@@ -47,6 +53,7 @@
 import org.openstreetmap.josm.gui.tagging.presets.items.Roles.Role;
 import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher;
 import org.openstreetmap.josm.gui.widgets.SearchTextResultListPanel;
+import org.openstreetmap.josm.tools.ColorHelper;
 import org.openstreetmap.josm.tools.Destroyable;
 import org.openstreetmap.josm.tools.Utils;
 
@@ -64,6 +71,7 @@
 
     private static final Pattern PATTERN_PUNCTUATION = Pattern.compile("\\p{Punct}", Pattern.UNICODE_CHARACTER_CLASS);
     private static final Pattern PATTERN_WHITESPACE = Pattern.compile("\\s", Pattern.UNICODE_CHARACTER_CLASS);
+    private static final Pattern PATTERN_GROUP = Pattern.compile("[\\s/]", Pattern.UNICODE_CHARACTER_CLASS);
 
     private static final BooleanProperty SEARCH_IN_TAGS = new BooleanProperty("taggingpreset.dialog.search-in-tags", true);
     private static final BooleanProperty ONLY_APPLICABLE = new BooleanProperty("taggingpreset.dialog.only-applicable-to-selection", true);
@@ -74,16 +82,93 @@
     private boolean typesInSelectionDirty = true;
     private final transient PresetClassifications classifications = new PresetClassifications();
 
-    private static class ResultListCellRenderer implements ListCellRenderer<TaggingPreset> {
+    private class ResultListCellRenderer implements ListCellRenderer<TaggingPreset> {
         private final DefaultListCellRenderer def = new DefaultListCellRenderer();
         @Override
         public Component getListCellRendererComponent(JList<? extends TaggingPreset> list, TaggingPreset tp, int index,
                 boolean isSelected, boolean cellHasFocus) {
             JLabel result = (JLabel) def.getListCellRendererComponent(list, tp, index, isSelected, cellHasFocus);
+            result.setToolTipText(null);
             result.setText(tp.getName());
+            if (list.getModel().getSize() < 200 // Maybe this should be configurable?
+                    && TaggingPresetSelector.this.ckSearchInTags != null
+                    && TaggingPresetSelector.this.ckSearchInTags.isSelected()) {
+                final String searchText = getSearchText();
+                final PresetClassification classification = new PresetClassification(tp);
+                final String[] wordSet = PATTERN_WHITESPACE.split(searchText, -1);
+                if (classification.isMatchingTags(wordSet) > 0) {
+                    final String matchingTags = buildMatchingTagText(getSearchableTags(tp), wordSet);
+                    if (matchingTags.length() > 0) {
+                        result.setToolTipText(tr("Matching tags: {0}", matchingTags));
+                        Color complement = ColorHelper.complement(result.getBackground());
+                        // This gray works for light/dark themes
+                        if (result.getBackground().getRGB() == Color.WHITE.getRGB()) {
+                            complement = Color.GRAY;
+                        }
+                        String col = ColorHelper.color2html(complement);
+                        result.setText("<html>" + tp.getName() + "&nbsp;&nbsp;&nbsp;&nbsp;<small style=\"color:" + col + "\">"
+                        + matchingTags + "</small></html>");
+                    }
+                }
+            }
             result.setIcon((Icon) tp.getValue(Action.SMALL_ICON));
             return result;
         }
+
+        /**
+         * Get the text to show a user for tags that match the given search string
+         * @param tagMap The map of searchable tags
+         * @param wordSet The words to filter on
+         * @return The string to show the user
+         */
+        private String buildMatchingTagText(Map<String, List<String>> tagMap, String[] wordSet) {
+            final Predicate<String> matchesWords = word -> {
+                for (String checkWord : wordSet) {
+                    if (word.contains(checkWord)) {
+                        return true;
+                    }
+                }
+                return false;
+            };
+            final StringBuilder sb = new StringBuilder();
+            for (Map.Entry<String, List<String>> entry : tagMap.entrySet()) {
+                if (sb.length() > 0 && sb.lastIndexOf(" ") != sb.length() - 1) {
+                    sb.append(' ');
+                }
+                int length = sb.length();
+                // Add the entry if it matches
+                if (matchesWords.test(entry.getKey())) {
+                    sb.append(entry.getKey());
+                    if (entry.getValue().size() == 1) {
+                        sb.append('=').append(entry.getValue().get(0));
+                    }
+                }
+
+                if (!entry.getValue().isEmpty() && (length == sb.length() || entry.getValue().size() > 1)) {
+                    // Add values if they match
+                    boolean added = false;
+                    for (String value : entry.getValue()) {
+                        if (matchesWords.test(value)) {
+                            // Add the key if it hasn't been added already
+                            if (!added) {
+                                if (length == sb.length()) {
+                                    sb.append(entry.getKey()).append('=');
+                                } else if (length + entry.getKey().length() == sb.length()) {
+                                    sb.append('=');
+                                }
+                            }
+                            if (added) {
+                                sb.append(';');
+                            } else {
+                                added = true;
+                            }
+                            sb.append(value);
+                        }
+                    }
+                }
+            }
+            return sb.toString();
+        }
     }
 
     /**
@@ -112,7 +197,6 @@
             this.preset = preset;
             Set<String> groupSet = new HashSet<>();
             Set<String> nameSet = new HashSet<>();
-            Set<String> tagSet = new HashSet<>();
             TaggingPreset group = preset.group;
             while (group != null) {
                 addLocaleNames(groupSet, group);
@@ -119,24 +203,10 @@
                 group = group.group;
             }
             addLocaleNames(nameSet, preset);
-            for (TaggingPresetItem item: preset.data) {
-                if (item instanceof KeyedItem) {
-                    tagSet.add(((KeyedItem) item).key);
-                    if (item instanceof ComboMultiSelect) {
-                        final ComboMultiSelect cms = (ComboMultiSelect) item;
-                        if (cms.values_searchable) {
-                            tagSet.addAll(cms.getDisplayValues());
-                        }
-                    }
-                    if (item instanceof Key && ((Key) item).value != null) {
-                        tagSet.add(((Key) item).value);
-                    }
-                } else if (item instanceof Roles) {
-                    for (Role role : ((Roles) item).roles) {
-                        tagSet.add(role.key);
-                    }
-                }
-            }
+            Map<String, List<String>> searchableTags = getSearchableTags(preset);
+            Set<String> tagSet = new HashSet<>(searchableTags.keySet());
+            searchableTags.values().forEach(tagSet::addAll);
+
             // These should be "frozen" arrays
             this.groupsSimplified = groupSet.stream().map(PresetClassification::simplifyString)
                     .toArray(String[]::new);
@@ -231,6 +301,45 @@
     }
 
     /**
+     * Get the searchable tag map for a preset
+     * @param preset The preset to parse
+     * @return A map of key to values that are searchable
+     */
+    private static Map<String, List<String>> getSearchableTags(TaggingPreset preset) {
+        final Map<String, List<String>> tagMap = new HashMap<>();
+        for (TaggingPresetItem item: preset.data) {
+            if (item instanceof KeyedItem) {
+                addKeyedItems(tagMap, (KeyedItem) item);
+            } else if (item instanceof Roles) {
+                for (Role role : ((Roles) item).roles) {
+                    tagMap.computeIfAbsent(role.key, k -> new ArrayList<>()); // new list just in case a role is also a tag
+                }
+            } else if (item instanceof CheckGroup) {
+                for (Check check : ((CheckGroup) item).checks) {
+                    addKeyedItems(tagMap, check);
+                }
+            }
+        }
+        return tagMap;
+    }
+
+    private static void addKeyedItems(Map<String, List<String>> tagMap, KeyedItem item) {
+        Collection<String> list = tagMap.computeIfAbsent(item.key, k -> new ArrayList<>());
+        if (item instanceof ComboMultiSelect) {
+            final ComboMultiSelect cms = (ComboMultiSelect) item;
+            if (cms.values_searchable) {
+                list.addAll(cms.getValues());
+                list.addAll(cms.getDisplayValues());
+            }
+        } else if (item instanceof Check) {
+            Check check = (Check) item;
+            list.addAll(check.getValues());
+        } else if (item instanceof Key && ((Key) item).value != null) {
+            list.add(((Key) item).value);
+        }
+    }
+
+    /**
      * Constructs a new {@code TaggingPresetSelector}.
      * @param displayOnlyApplicable if {@code true} display "Show only applicable to selection" checkbox
      * @param displaySearchInTags if {@code true} display "Search in tags" checkbox
@@ -330,7 +439,7 @@
             final String[] nameWords;
 
             if (searchText.contains("/")) {
-                groupWords = searchText.substring(0, searchText.lastIndexOf('/')).split("(?U)[\\s/]", -1);
+                groupWords = PATTERN_GROUP.split(searchText.substring(0, searchText.lastIndexOf('/')), -1);
                 nameWords = PATTERN_WHITESPACE.split(searchText.substring(searchText.indexOf('/') + 1), -1);
             } else {
                 groupWords = null;
