PY-27749 Return tokens composing literal f-string parts in getStringLiteralElements()

instead of the whole STRING_LITERAL_EXPRESSION as it's expected to
return tokens instead of composite AST nodes, and, otherwise, real
expressions embedded inside f-strings get caught as string occurrences.

GitOrigin-RevId: 5625b7c3ba9aac37dc047c6d876df80de0a4ab31
This commit is contained in:
Mikhail Golubev
2019-06-13 12:25:29 +03:00
committed by intellij-monorepo-bot
parent eb87190ea4
commit c83753100d
4 changed files with 30 additions and 1 deletions
@@ -186,4 +186,12 @@ public class PyTokenTypes {
public static final PyElementType FSTRING_FRAGMENT_END = new PyElementType("FSTRING_FRAGMENT_END");
public static final PyElementType FSTRING_FRAGMENT_FORMAT_START = new PyElementType("FSTRING_FRAGMENT_FORMAT_START");
public static final PyElementType FSTRING_FRAGMENT_TYPE_CONVERSION = new PyElementType("FSTRING_FRAGMENT_TYPE_CONVERSION");
public static final TokenSet FSTRING_TOKENS = TokenSet.create(FSTRING_TEXT,
FSTRING_START,
FSTRING_END,
FSTRING_FRAGMENT_START,
FSTRING_FRAGMENT_END,
FSTRING_FRAGMENT_FORMAT_START,
FSTRING_FRAGMENT_TYPE_CONVERSION);
}
@@ -53,7 +53,7 @@ public class PythonParserDefinition implements ParserDefinition {
@Override
@NotNull
public TokenSet getStringLiteralElements() {
return TokenSet.orSet(PyTokenTypes.STRING_NODES, TokenSet.create(PyElementTypes.STRING_LITERAL_EXPRESSION));
return TokenSet.orSet(PyTokenTypes.STRING_NODES, PyTokenTypes.FSTRING_TOKENS);
}
@Override
@@ -0,0 +1,3 @@
def func():
v<caret>ar = 42
s = f'{var}'
@@ -5,15 +5,20 @@ import com.intellij.codeInsight.TargetElementUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.refactoring.BaseRefactoringProcessor;
import com.intellij.refactoring.util.TextOccurrencesUtil;
import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.PythonTestUtil;
import com.jetbrains.python.documentation.docstrings.DocStringFormat;
import com.jetbrains.python.fixtures.PyTestCase;
import com.jetbrains.python.psi.LanguageLevel;
import com.jetbrains.python.psi.PyTargetExpression;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* @author yole
@@ -323,6 +328,19 @@ public class PyRenameTest extends PyTestCase {
assertEquals("foo_bar_baz", PyNameSuggestionProvider.toUnderscores("foo_BarBAZ"));
}
// PY-27749
public void testReferencesInsideFStringsNotReportedAsStringOccurrences() {
myFixture.configureByFile(RENAME_DATA_PATH + getTestName(true) + ".py");
final PyTargetExpression attr = (PyTargetExpression)myFixture.getElementAtCaret();
final GlobalSearchScope singleFileScope = GlobalSearchScope.fileScope(myFixture.getFile());
final List<PsiElement> found = new ArrayList<>();
TextOccurrencesUtil.processUsagesInStringsAndComments(attr, singleFileScope, attr.getName(), true, (psiElement, textRange) -> {
found.add(psiElement);
return true;
});
assertEmpty(found);
}
private void renameWithDocStringFormat(DocStringFormat format, final String newName) {
runWithDocStringFormat(format, () -> doTest(newName));
}