ConfigurableHit (@NotNull List<? extends ConfigurableGroup> groups, DocumentEvent.EventType type, @Nullable Set<? extends Configurable> previouslyFiltered, @NotNull String option, @Nullable Project project) { if (previouslyFiltered == null || previouslyFiltered.isEmpty()) { previouslyFiltered = null; } String optionToCheck = Strings.toLowerCase(option.trim()); ConfigurableHit foundByPath = findGroupsByPath(groups, optionToCheck); if (foundByPath != null) { return foundByPath; } Set<Configurable> effectiveConfigurables = new LinkedHashSet<>(); if (previouslyFiltered == null) { Consumer<Configurable> consumer = new CollectConsumer<>(effectiveConfigurables); for (ConfigurableGroup group : groups) { SearchUtil.processExpandedGroups(group, consumer); } } else { effectiveConfigurables.addAll(previouslyFiltered); } Set<Configurable> nameHits = new LinkedHashSet<>(); Set<Configurable> nameFullHits = new LinkedHashSet<>(); Set<String> options = getProcessedWordsWithoutStemming(optionToCheck); if (options.isEmpty()) { for (Configurable each : effectiveConfigurables) { if (each.getDisplayName() != null) { nameHits.add(each); nameFullHits.add(each); } } } else { for (Configurable each : effectiveConfigurables) { if (each.getDisplayName() == null) { continue; } final String displayName = Strings.toLowerCase(each.getDisplayName()); if (displayName.contains(optionToCheck)) { nameFullHits.add(each); nameHits.add(each); } } } // operate with substring Set<String> descriptionOptions = new HashSet<>(); if (options.isEmpty()) { String[] components = WORD_SEPARATOR_CHARS.split(optionToCheck); if (components.length > 0) { Collections.addAll(descriptionOptions, components); } else { descriptionOptions.add(option); } } else { descriptionOptions.addAll(options); } Set<String> foundIds = findConfigurablesByDescriptions(descriptionOptions); if (foundIds == null) { return new ConfigurableHit(nameHits, nameFullHits, Collections.emptySet(), option); } List<Configurable> contentHits = filterById(effectiveConfigurables, foundIds); if (type == DocumentEvent.EventType.CHANGE && previouslyFiltered != null && effectiveConfigurables.size() == contentHits.size()) { return getConfigurables(groups, DocumentEvent.EventType.CHANGE, null, option, project); } return new ConfigurableHit(nameHits, nameFullHits, new LinkedHashSet<>(contentHits), option); }