private void addKeyCompletions(@NotNull CompletionParameters params,
                                 @NotNull YamlMetaTypeProvider metaTypeProvider,
                                 @NotNull YamlMetaTypeProvider.MetaTypeProxy meta,
                                 @NotNull CompletionResultSet result,
                                 @NotNull PsiElement insertedScalar) {
    final YamlMetaType metaType = meta.getMetaType();
    if (metaType instanceof YamlScalarType) {
      return;
    }

    YAMLValue metaOwner = metaTypeProvider.getMetaOwner(insertedScalar);
    if (metaOwner instanceof YAMLScalar && metaOwner.getParent() instanceof YAMLMapping) {
      // workaround for case when completion has added scalar in the middle of the tags
      // in the correct YAML mappings should not directly contain scalars, so it is supposedly safe (?)
      metaOwner = (YAMLValue)metaOwner.getParent();
    }

    YAMLMapping existingMapping = ObjectUtils.tryCast(metaOwner, YAMLMapping.class);
    Collection<YAMLKeyValue> existingPairs = Optional.ofNullable(existingMapping)
      .map(YAMLMapping::getKeyValues)
      .orElse(Collections.emptyList());

    Map<String, YAMLKeyValue> existingByKey = existingPairs.stream().collect(
      Collectors.toMap(kv -> kv.getKeyText().trim(), kv -> kv, (oldValue, newValue) -> oldValue));

    final List<Field> suggestedFields = metaType.computeKeyCompletions(existingMapping);
    final List<Field> filteredList = ContainerUtil
      .filter(suggestedFields, childField -> !existingByKey.containsKey(childField.getName()) && childField.isEditable());

    final boolean needsSequenceItemMark = existingPairs.isEmpty() && needsSequenceItem(meta.getField());

    if (params.getCompletionType() == CompletionType.SMART) {
      final String text = insertedScalar.getText();
      final int caretPos = text.indexOf(DUMMY_IDENTIFIER_TRIMMED);
      String pattern = StringUtil.toLowerCase((caretPos >= 0 ? text.substring(0, caretPos) : text));

      final Collection<List<Field>> paths = collectPaths(filteredList, pattern.length() > 0 ? 10 : 1);

      for (List<Field> pathToInsert : paths) {
        final Field lastField = pathToInsert.get(pathToInsert.size() - 1);
        if (StringUtil.toLowerCase(lastField.getName()).startsWith(pattern)) {
          final YamlMetaType.ForcedCompletionPath completionPath = YamlMetaType.ForcedCompletionPath.forDeepCompletion(pathToInsert);
          LookupElementBuilder l = LookupElementBuilder
            .create(completionPath, completionPath.getName())
            .withIcon(lastField.getLookupIcon())
            .withInsertHandler(createKeyInsertHandler(params.getPosition().getProject(), needsSequenceItemMark, pathToInsert.get(0)))
            .withTypeText(lastField.getDefaultType().getDisplayName(), true)
            .withStrikeoutness(lastField.isDeprecated());
          result.addElement(l);
        }
      }
    }
    else {
      filteredList.stream()
        .filter(childField -> !existingByKey.containsKey(childField.getName()))
        .forEach(childField -> {
          var lookups = ContainerUtil.filter(childField.getKeyLookups(metaType, insertedScalar), l -> {
            return !existingByKey.containsKey(l.getLookupString());
          });

          registerBasicKeyCompletion(result, lookups,
                                     createKeyInsertHandler(params.getPosition().getProject(), needsSequenceItemMark, childField));
        });
    }
  }
private void addKeyCompletions(@NotNull CompletionParameters params,
                                 @NotNull YamlMetaTypeProvider metaTypeProvider,
                                 @NotNull YamlMetaTypeProvider.MetaTypeProxy meta,
                                 @NotNull CompletionResultSet result,
                                 @NotNull PsiElement insertedScalar)