void (@NotNull PyFStringFragment node) { super.visitPyFStringFragment(node); final ASTNode equalitySignInFStringFragment = node.getNode().findChildByType(PyTokenTypes.EQ); if (equalitySignInFStringFragment != null) { registerForAllMatchingVersions(level -> level.isOlderThan(LanguageLevel.PYTHON38) && registerForLanguageLevel(level), PyPsiBundle.message("INSP.compatibility.support.equality.signs.in.fstrings"), equalitySignInFStringFragment.getPsi()); } List<PyFStringFragment> containingFragmentsOfSameFString = PsiTreeUtil.collectParents(node, PyFStringFragment.class, false, o -> o instanceof PyStringLiteralExpression); if (containingFragmentsOfSameFString.size() > 1) { // At the moment, there is a limit of 2 for CPython 3.12, but it's implementation-dependent. // See https://peps.python.org/pep-0701/#specification registerForAllMatchingVersions(level -> level.isOlderThan(LanguageLevel.PYTHON312) && registerForLanguageLevel(level), PyPsiBundle.message("INSP.compatibility.feature.allow.deep.expression.nesting.in.f-strings"), node); } boolean isTopmostFragment = PsiTreeUtil.getParentOfType(node, PyFStringFragment.class, true) == null; if (isTopmostFragment) { List<PyFStringFragment> fragments = new ArrayList<>(); fragments.add(node); PyFStringFragmentFormatPart formatPart = node.getFormatPart(); if (formatPart != null) { fragments.addAll(formatPart.getFragments()); } for (PyFStringFragment fragment : fragments) { String wholeNodeText = fragment.getText(); TextRange range = fragment.getExpressionContentRange(); for (int i = range.getStartOffset(); i < range.getEndOffset(); i++) { if (wholeNodeText.charAt(i) == '\\') { TextRange backslashRange = TextRange.from(i, 1).shiftRight(fragment.getTextRange().getStartOffset()); registerForAllMatchingVersions( level -> level.isOlderThan(LanguageLevel.PYTHON312) && registerForLanguageLevel(level), PyPsiBundle.message("INSP.compatibility.feature.allow.backslashes.in.f-strings"), node, backslashRange, true ); } } } } List<PyFormattedStringElement> containingFStrings = PsiTreeUtil.collectParents(node, PyFormattedStringElement.class, false, e -> e instanceof PyStatement); assert !containingFStrings.isEmpty(); PyFormattedStringElement parentFString = containingFStrings.get(0); List<PyFormattedStringElement> remainingEnclosingFStrings = ContainerUtil.subList(containingFStrings, 1); // Report only on fragments of the topmost single-quoted f-string to avoid duplicates // in cases like: f'{f'{1<BR> // + 1}'}' boolean isFragmentOfTopmostSingleQuotedFString = !parentFString.isTripleQuoted() && ContainerUtil.all(remainingEnclosingFStrings, PyStringElement::isTripleQuoted); if (isFragmentOfTopmostSingleQuotedFString && node.textContains('\n')) { int lineBreakOffset = node.getText().indexOf('\n'); if (node.getExpressionContentRange().contains(lineBreakOffset)) { PsiElement multiLineLeaf = node.findElementAt(lineBreakOffset); assert multiLineLeaf != null; registerForAllMatchingVersions(level -> level.isOlderThan(LanguageLevel.PYTHON312) && registerForLanguageLevel(level), PyPsiBundle.message("INSP.compatibility.feature.allow.new.lines.in.f-strings"), multiLineLeaf); } } String parentFStringQuote = parentFString.getQuote(); // Report only on fragments of the topmost f-string with this quote type to avoid duplicates in cases like: f'{f'{f"'"}'}' boolean isFragmentOfTopmostFStringWithSuchQuotes = ContainerUtil.all(remainingEnclosingFStrings, fString -> !fString.getQuote().equals(parentFStringQuote)); if (isFragmentOfTopmostFStringWithSuchQuotes) { int illegalQuoteOffset = node.getText().indexOf(parentFStringQuote); if (node.getExpressionContentRange().contains(illegalQuoteOffset)) { TextRange illegalQuoteRange = TextRange.from(illegalQuoteOffset, parentFStringQuote.length()); registerForAllMatchingVersions(level -> level.isOlderThan(LanguageLevel.PYTHON312) && registerForLanguageLevel(level), PyPsiBundle.message("INSP.compatibility.feature.allow.quote.reuse.in.f-strings"), node, illegalQuoteRange.shiftRight(node.getTextRange().getStartOffset()), true); } } }