void (@NotNull CompletionParameters parameters, @NotNull ProcessingContext context, @NotNull CompletionResultSet result) { PyPlainStringElement stringElem = as(parameters.getPosition(), PyPlainStringElement.class); if (stringElem == null || stringElem.isBytes() || stringElem.isUnicode()) { return; } if (LanguageLevel.forElement(stringElem).isOlderThan(LanguageLevel.PYTHON36)) { return; } PyStringLiteralExpression stringLiteral = (PyStringLiteralExpression)stringElem.getParent(); String stringElemText = stringElem.getText(); int offset = parameters.getOffset(); int stringElemStart = stringElem.getTextRange().getStartOffset(); int relOffset = offset - stringElemStart; int braceOffset = CharArrayUtil.shiftBackwardUntil(stringElemText, relOffset - 1, "{"); if (braceOffset < 0) { return; } String completionPrefix = stringElemText.substring(braceOffset + 1, relOffset); boolean autoPopupAfterOpeningBrace = completionPrefix.isEmpty() && parameters.isAutoPopup(); if (autoPopupAfterOpeningBrace) { return; } boolean prefixCannotStartReference = !completionPrefix.isEmpty() && !PyNames.isIdentifier(completionPrefix); if (prefixCannotStartReference) { return; } String fStringText = new StringBuilder() .append("f").append(stringElemText) .insert(relOffset + 1 + CompletionUtilCore.DUMMY_IDENTIFIER.length(), "} ") .toString(); PyExpression fString = PyUtil.createExpressionFromFragment(fStringText, stringLiteral.getParent()); assert fString != null; PsiReference reference = fString.findReferenceAt(relOffset + 1); if (reference == null) { return; } List<@NotNull LookupElement> fStringVariants = ContainerUtil.mapNotNull(reference.getVariants(), v -> as(v, LookupElement.class)); if (fStringVariants.isEmpty()) { return; } CompletionResultSet prefixPatchedResultSet = result.withPrefixMatcher(completionPrefix); for (LookupElement variant : fStringVariants) { prefixPatchedResultSet.addElement(new LookupElementDecorator<>(variant) { @Override public void handleInsert(@NotNull InsertionContext context) { super.handleInsert(context); Document document = context.getDocument(); CharSequence docChars = document.getCharsSequence(); int tailOffset = context.getTailOffset(); if (!(tailOffset < document.getTextLength() && docChars.charAt(tailOffset) == '}')) { document.insertString(tailOffset, "}"); } // It can happen when completion is invoked on multiple carets inside the same string String stringElemPrefix = PyStringLiteralCoreUtil.getPrefix(docChars, stringElemStart); if (!PyStringLiteralUtil.isFormattedPrefix(stringElemPrefix)) { document.insertString(stringElemStart, "f"); } } }