public static Map<TemplateImpl, String> filterTemplatesByPrefix(@NotNull Collection<? extends TemplateImpl> templates, @NotNull Editor editor,
                                                                  int offset, boolean fullMatch, boolean searchInDescription) {
    if (offset > editor.getDocument().getTextLength()) {
      LOG.error("Cannot filter templates, index out of bounds. Offset: " + offset,
                CoreAttachmentFactory.createAttachment(editor.getDocument()));
    }
    CharSequence documentText = editor.getDocument().getCharsSequence().subSequence(0, offset);

    String prefixWithoutDots = computeDescriptionMatchingPrefix(editor.getDocument(), offset);
    Pattern prefixSearchPattern = Pattern.compile(".*\\b" + prefixWithoutDots + ".*");

    Map<TemplateImpl, String> matchingTemplates = new TreeMap<>(TemplateListPanel.TEMPLATE_COMPARATOR);
    for (TemplateImpl template : templates) {
      ProgressManager.checkCanceled();
      String templateKey = template.getKey();
      if (fullMatch) {
        int startOffset = documentText.length() - templateKey.length();
        if (startOffset <= 0 || !Character.isJavaIdentifierPart(documentText.charAt(startOffset - 1))) {
          // after non-identifier
          if (StringUtil.endsWith(documentText, templateKey)) {
            matchingTemplates.put(template, templateKey);
          }
        }
      }
      else {
        if (!ClientId.isCurrentlyUnderLocalId() && prefixWithoutDots.isEmpty()) {
          matchingTemplates.put(template, prefixWithoutDots);
          continue;
        }

        for (int i = templateKey.length(); i > 0; i--) {
          ProgressManager.checkCanceled();
          String prefix = templateKey.substring(0, i);
          int startOffset = documentText.length() - i;
          if (startOffset > 0 && Character.isJavaIdentifierPart(documentText.charAt(startOffset - 1))) {
            // after java identifier
            continue;
          }
          if (StringUtil.endsWith(documentText, prefix)) {
            matchingTemplates.put(template, prefix);
            break;
          }
        }
      }

      if (searchInDescription && !matchingTemplates.containsKey(template)) {
        String templateDescription = template.getDescription();
        if (!prefixWithoutDots.isEmpty() && templateDescription != null && prefixSearchPattern.matcher(templateDescription).matches()) {
          matchingTemplates.put(template, prefixWithoutDots);
        }
      }
    }

    return matchingTemplates;
  }
public static Map<TemplateImpl, String> filterTemplatesByPrefix(@NotNull Collection<? extends TemplateImpl> templates, @NotNull Editor editor,
                                                                  int offset, boolean fullMatch, boolean searchInDescription)