Migrate PyDictConstructorToLiteralFormIntention, PyDictLiteralFormToConstructorIntention, PyFlipComparisonIntention

PY-65297

GitOrigin-RevId: 535ec8dce4ecb5933f840fb6237ecec1b9ed07ad
This commit is contained in:
Georgii Ustinov
2024-01-11 16:14:56 +02:00
committed by intellij-monorepo-bot
parent 83a345e0ba
commit 1ca8156c65
3 changed files with 106 additions and 104 deletions

View File

@@ -1,16 +1,18 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.jetbrains.python.codeInsight.intentions;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiFile;
import com.intellij.modcommand.ActionContext;
import com.intellij.modcommand.ModPsiUpdater;
import com.intellij.modcommand.Presentation;
import com.intellij.modcommand.PsiUpdateModCommandAction;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.PyPsiBundle;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* User: catherine
@@ -21,7 +23,33 @@ import org.jetbrains.annotations.NotNull;
* dict(foo) -> no transformation
* dict(**foo) -> no transformation
*/
public final class PyDictConstructorToLiteralFormIntention extends PyBaseIntentionAction {
public final class PyDictConstructorToLiteralFormIntention extends PsiUpdateModCommandAction<PsiElement> {
PyDictConstructorToLiteralFormIntention() {
super(PsiElement.class);
}
@Override
protected @Nullable Presentation getPresentation(@NotNull ActionContext actionContext, @NotNull PsiElement element) {
if (!(actionContext.file() instanceof PyFile)) {
return null;
}
PyCallExpression expression = PsiTreeUtil.getParentOfType(element, PyCallExpression.class);
if (expression != null && expression.isCalleeText("dict")) {
final TypeEvalContext context = TypeEvalContext.codeAnalysis(actionContext.project(), actionContext.file());
PyType type = context.getType(expression);
if (type != null && type.isBuiltin()) {
PyExpression[] argumentList = expression.getArguments();
for (PyExpression argument : argumentList) {
if (!(argument instanceof PyKeywordArgument)) return null;
}
return super.getPresentation(actionContext, element);
}
}
return null;
}
@Override
@NotNull
public String getFamilyName() {
@@ -29,39 +57,10 @@ public final class PyDictConstructorToLiteralFormIntention extends PyBaseIntenti
}
@Override
@NotNull
public String getText() {
return PyPsiBundle.message("INTN.convert.dict.constructor.to.dict.literal");
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
if (!(file instanceof PyFile)) {
return false;
}
protected void invoke(@NotNull ActionContext context, @NotNull PsiElement element, @NotNull ModPsiUpdater updater) {
PyCallExpression expression =
PsiTreeUtil.getParentOfType(file.findElementAt(editor.getCaretModel().getOffset()), PyCallExpression.class);
if (expression != null && expression.isCalleeText("dict")) {
final TypeEvalContext context = TypeEvalContext.codeAnalysis(file.getProject(), file);
PyType type = context.getType(expression);
if (type != null && type.isBuiltin()) {
PyExpression[] argumentList = expression.getArguments();
for (PyExpression argument : argumentList) {
if (!(argument instanceof PyKeywordArgument)) return false;
}
return true;
}
}
return false;
}
@Override
public void doInvoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
PyCallExpression expression =
PsiTreeUtil.getParentOfType(file.findElementAt(editor.getCaretModel().getOffset()), PyCallExpression.class);
PyElementGenerator elementGenerator = PyElementGenerator.getInstance(project);
PsiTreeUtil.getParentOfType(element, PyCallExpression.class);
PyElementGenerator elementGenerator = PyElementGenerator.getInstance(context.project());
if (expression != null) {
replaceDictConstructor(expression, elementGenerator);
}

View File

@@ -1,16 +1,18 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.jetbrains.python.codeInsight.intentions;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.modcommand.ActionContext;
import com.intellij.modcommand.ModPsiUpdater;
import com.intellij.modcommand.Presentation;
import com.intellij.modcommand.PsiUpdateModCommandAction;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.PyPsiBundle;
import com.jetbrains.python.psi.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* User: catherine
@@ -21,54 +23,52 @@ import org.jetbrains.annotations.NotNull;
* {'a': 3, 'b': 5} -> dict(a=3, b=5)
* {a: 3, b: 5} -> no transformation
*/
public final class PyDictLiteralFormToConstructorIntention extends PyBaseIntentionAction {
public final class PyDictLiteralFormToConstructorIntention extends PsiUpdateModCommandAction<PsiElement> {
PyDictLiteralFormToConstructorIntention() {
super(PsiElement.class);
}
@Override
protected @Nullable Presentation getPresentation(@NotNull ActionContext context, @NotNull PsiElement element) {
if (!(context.file() instanceof PyFile)) {
return null;
}
PyDictLiteralExpression dictExpression =
PsiTreeUtil.getParentOfType(element, PyDictLiteralExpression.class);
if (dictExpression != null) {
PyKeyValueExpression[] elements = dictExpression.getElements();
for (PyKeyValueExpression expression : elements) {
PyExpression key = expression.getKey();
if (!(key instanceof PyStringLiteralExpression)) return null;
String str = ((PyStringLiteralExpression)key).getStringValue();
if (PyNames.isReserved(str)) return null;
if (str.isEmpty() || Character.isDigit(str.charAt(0))) return null;
if (!StringUtil.isJavaIdentifier(str)) return null;
}
return super.getPresentation(context, element);
}
return null;
}
@Override
protected void invoke(@NotNull ActionContext context, @NotNull PsiElement element, @NotNull ModPsiUpdater updater) {
PyDictLiteralExpression dictExpression =
PsiTreeUtil.getParentOfType(element, PyDictLiteralExpression.class);
PyElementGenerator elementGenerator = PyElementGenerator.getInstance(context.project());
if (dictExpression != null) {
replaceDictLiteral(dictExpression, elementGenerator);
}
}
@Override
@NotNull
public String getFamilyName() {
return PyPsiBundle.message("INTN.convert.dict.literal.to.dict.constructor");
}
@Override
@NotNull
public String getText() {
return PyPsiBundle.message("INTN.convert.dict.literal.to.dict.constructor");
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
if (!(file instanceof PyFile)) {
return false;
}
PyDictLiteralExpression dictExpression =
PsiTreeUtil.getParentOfType(file.findElementAt(editor.getCaretModel().getOffset()), PyDictLiteralExpression.class);
if (dictExpression != null) {
PyKeyValueExpression[] elements = dictExpression.getElements();
for (PyKeyValueExpression element : elements) {
PyExpression key = element.getKey();
if (!(key instanceof PyStringLiteralExpression)) return false;
String str = ((PyStringLiteralExpression)key).getStringValue();
if (PyNames.isReserved(str)) return false;
if (str.length() == 0 || Character.isDigit(str.charAt(0))) return false;
if (!StringUtil.isJavaIdentifier(str)) return false;
}
return true;
}
return false;
}
@Override
public void doInvoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
PyDictLiteralExpression dictExpression =
PsiTreeUtil.getParentOfType(file.findElementAt(editor.getCaretModel().getOffset()), PyDictLiteralExpression.class);
PyElementGenerator elementGenerator = PyElementGenerator.getInstance(project);
if (dictExpression != null) {
replaceDictLiteral(dictExpression, elementGenerator);
}
}
private static void replaceDictLiteral(PyDictLiteralExpression dictExpression, PyElementGenerator elementGenerator) {
PyExpression[] argumentList = dictExpression.getElements();
StringBuilder stringBuilder = new StringBuilder("dict(");

View File

@@ -1,12 +1,12 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.jetbrains.python.codeInsight.intentions;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.modcommand.ActionContext;
import com.intellij.modcommand.ModPsiUpdater;
import com.intellij.modcommand.Presentation;
import com.intellij.modcommand.PsiUpdateModCommandAction;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.PyPsiBundle;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.psi.PyBinaryExpression;
@@ -14,10 +14,15 @@ import com.jetbrains.python.psi.PyElementGenerator;
import com.jetbrains.python.psi.PyElementType;
import com.jetbrains.python.psi.PyFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
public final class PyFlipComparisonIntention extends PyBaseIntentionAction {
public final class PyFlipComparisonIntention extends PsiUpdateModCommandAction<PsiElement> {
PyFlipComparisonIntention() {
super(PsiElement.class);
}
private static class Holder {
private static final Map<PyElementType, String> FLIPPED_OPERATORS = Map.of(
PyTokenTypes.EQEQ, "==",
@@ -29,19 +34,13 @@ public final class PyFlipComparisonIntention extends PyBaseIntentionAction {
PyTokenTypes.LT, ">");
}
@Override
@NotNull
public String getFamilyName() {
return PyPsiBundle.message("INTN.NAME.flip.comparison");
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
if (!(file instanceof PyFile)) {
return false;
protected @Nullable Presentation getPresentation(@NotNull ActionContext context, @NotNull PsiElement element) {
if (!(context.file() instanceof PyFile)) {
return null;
}
PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
PyBinaryExpression binaryExpression = PsiTreeUtil.getParentOfType(element, PyBinaryExpression.class, false);
while (binaryExpression != null) {
PyElementType operator = binaryExpression.getOperator();
@@ -49,26 +48,30 @@ public final class PyFlipComparisonIntention extends PyBaseIntentionAction {
String operatorText = binaryExpression.getPsiOperator().getText();
String flippedOperatorText = Holder.FLIPPED_OPERATORS.get(operator);
if (flippedOperatorText.equals(operatorText)) {
setText(PyPsiBundle.message("INTN.flip.comparison", operatorText));
return Presentation.of(PyPsiBundle.message("INTN.flip.comparison", operatorText));
}
else {
setText(PyPsiBundle.message("INTN.flip.comparison.to.operator", operatorText, flippedOperatorText));
return Presentation.of(PyPsiBundle.message("INTN.flip.comparison.to.operator", operatorText, flippedOperatorText));
}
return true;
}
binaryExpression = PsiTreeUtil.getParentOfType(binaryExpression, PyBinaryExpression.class);
}
return false;
return null;
}
@Override
public void doInvoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
@NotNull
public String getFamilyName() {
return PyPsiBundle.message("INTN.NAME.flip.comparison");
}
@Override
protected void invoke(@NotNull ActionContext context, @NotNull PsiElement element, @NotNull ModPsiUpdater updater) {
PyBinaryExpression binaryExpression = PsiTreeUtil.getParentOfType(element, PyBinaryExpression.class, false);
while (binaryExpression != null) {
PyElementType operator = binaryExpression.getOperator();
if (operator != null && Holder.FLIPPED_OPERATORS.containsKey(operator)) {
PyElementGenerator elementGenerator = PyElementGenerator.getInstance(project);
PyElementGenerator elementGenerator = PyElementGenerator.getInstance(context.project());
binaryExpression.replace(elementGenerator.createBinaryExpression(Holder.FLIPPED_OPERATORS.get(operator),
binaryExpression.getRightExpression(),
binaryExpression.getLeftExpression()));