mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-05 01:50:56 +07:00
Annotator to highlight unsupported features in Python2
This commit is contained in:
@@ -57,6 +57,7 @@ INTN.Family.toggle.import.alias=Toggle import alias
|
||||
INTN.Family.convert.except.part=Convert except part to supported form
|
||||
INTN.Family.convert.set.literal=Convert set literal two supported forms
|
||||
INTN.Family.convert.builtin=Convert builtin module import
|
||||
INTN.Family.convert.dict.comp.expression=Convert dictionary comprehension expression
|
||||
|
||||
INTN.convert.to.from.$0.import.$1=Convert to ''from {0} import {1}''
|
||||
INTN.convert.to.import.$0=Convert to ''import {0}''
|
||||
@@ -71,6 +72,8 @@ INTN.convert.set.literal.to=Convert set literal to 'set' method call
|
||||
|
||||
INTN.convert.builtin.import=Convert builtin module import to supported form
|
||||
|
||||
INTN.convert.dict.comp.to=Convert dictionary comprehension to 'dict' method call
|
||||
|
||||
# Conflict checker
|
||||
CONFLICT.name.$0.obscured=Name ''{0}'' obscured by local definitions
|
||||
CONFLICT.name.$0.obscured.cannot.convert=Name ''{0}'' obscured. Cannot convert.
|
||||
|
||||
@@ -35,6 +35,7 @@ public class PythonLanguage extends Language {
|
||||
_annotators.add(ImportAnnotator.class);
|
||||
_annotators.add(StringConstantAnnotator.class);
|
||||
_annotators.add(PyBuiltinAnnotator.class);
|
||||
_annotators.add(UnsupportedFeaturesIn2.class);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
package com.jetbrains.python.codeInsight.intentions;
|
||||
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
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.PyBundle;
|
||||
import com.jetbrains.python.PythonLanguage;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: Alexey.Ivanov
|
||||
* Date: 20.02.2010
|
||||
* Time: 15:49:35
|
||||
*/
|
||||
public class ConvertDictCompIntention implements IntentionAction {
|
||||
@NotNull
|
||||
@Override
|
||||
public String getText() {
|
||||
return PyBundle.message("INTN.convert.dict.comp.to");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
return PyBundle.message("INTN.Family.convert.dict.comp.expression");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
|
||||
VirtualFile virtualFile = file.getVirtualFile();
|
||||
if (virtualFile != null && !LanguageLevel.forFile(virtualFile).isPy3K()) {
|
||||
PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
|
||||
PyDictCompExpression expression = PsiTreeUtil.getParentOfType(element, PyDictCompExpression.class);
|
||||
if (expression == null) {
|
||||
return false;
|
||||
}
|
||||
return expression.getResultExpression() instanceof PyKeyValueExpression;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: {k, v for k in range(4) for v in range(4)}
|
||||
@Override
|
||||
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
|
||||
VirtualFile virtualFile = file.getVirtualFile();
|
||||
if (virtualFile != null && !LanguageLevel.forFile(virtualFile).isPy3K()) {
|
||||
PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
|
||||
PyDictCompExpression expression = PsiTreeUtil.getParentOfType(element, PyDictCompExpression.class);
|
||||
assert expression != null;
|
||||
replaceComprehension(project, expression);
|
||||
}
|
||||
}
|
||||
|
||||
private static void replaceComprehension(Project project, PyDictCompExpression expression) {
|
||||
List<ComprhForComponent> forComponents = expression.getForComponents();
|
||||
if (expression.getResultExpression() instanceof PyKeyValueExpression) {
|
||||
PyKeyValueExpression keyValueExpression = (PyKeyValueExpression)expression.getResultExpression();
|
||||
PyElementGenerator elementGenerator = PythonLanguage.getInstance().getElementGenerator();
|
||||
assert keyValueExpression.getValue() != null;
|
||||
expression.replace(elementGenerator.createFromText(project, PyExpressionStatement.class,
|
||||
"dict([(" + keyValueExpression.getKey().getText() + ", " +
|
||||
keyValueExpression.getValue().getText() + ") for " +
|
||||
forComponents.get(0).getIteratorVariable().getText() + " in " +
|
||||
forComponents.get(0).getIteratedList().getText() + "])"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startInWriteAction() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.jetbrains.python.codeInsight.intentions;
|
||||
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
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.PyBundle;
|
||||
import com.jetbrains.python.PythonLanguage;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: Alexey.Ivanov
|
||||
* Date: 16.02.2010
|
||||
* Time: 21:33:28
|
||||
*/
|
||||
public class ConvertSetLiteralIntention implements IntentionAction {
|
||||
@NotNull
|
||||
public String getText() {
|
||||
return PyBundle.message("INTN.convert.set.literal.to");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getFamilyName() {
|
||||
return PyBundle.message("INTN.Family.convert.set.literal");
|
||||
}
|
||||
|
||||
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
|
||||
VirtualFile virtualFile = file.getVirtualFile();
|
||||
if (virtualFile != null && !LanguageLevel.forFile(virtualFile).isPy3K()) {
|
||||
PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
|
||||
PySetLiteralExpression setLiteral = PsiTreeUtil.getParentOfType(element, PySetLiteralExpression.class);
|
||||
return (setLiteral != null);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
|
||||
VirtualFile virtualFile = file.getVirtualFile();
|
||||
if (virtualFile != null && !LanguageLevel.forFile(virtualFile).isPy3K()) {
|
||||
PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
|
||||
PySetLiteralExpression setLiteral = PsiTreeUtil.getParentOfType(element, PySetLiteralExpression.class);
|
||||
assert setLiteral != null;
|
||||
PyExpression[] expressions = setLiteral.getElements();
|
||||
if (expressions != null) {
|
||||
PyElementGenerator elementGenerator = PythonLanguage.getInstance().getElementGenerator();
|
||||
assert expressions.length != 0;
|
||||
StringBuilder stringBuilder = new StringBuilder(expressions[0].getText());
|
||||
for (int i = 1; i < expressions.length; ++i) {
|
||||
stringBuilder.append(", ");
|
||||
stringBuilder.append(expressions[i].getText());
|
||||
}
|
||||
PyStatement newElement = elementGenerator.createFromText(project, PyExpressionStatement.class, "set([" + stringBuilder.toString() + "])");
|
||||
setLiteral.replace(newElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean startInWriteAction() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.jetbrains.python.codeInsight.intentions;
|
||||
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
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.PyBundle;
|
||||
import com.jetbrains.python.PythonLanguage;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: Alexey.Ivanov
|
||||
* Date: 19.02.2010
|
||||
* Time: 18:50:24
|
||||
*/
|
||||
public class ReplaceBuiltinsIntention implements IntentionAction {
|
||||
@NotNull
|
||||
public String getText() {
|
||||
return PyBundle.message("INTN.convert.builtin.import");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getFamilyName() {
|
||||
return PyBundle.message("INTN.Family.convert.builtin");
|
||||
}
|
||||
|
||||
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
|
||||
PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
|
||||
PyImportStatement importStatement = PsiTreeUtil.getParentOfType(element, PyImportStatement.class);
|
||||
return (importStatement != null);
|
||||
}
|
||||
|
||||
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
|
||||
PyElementGenerator elementGenerator = PythonLanguage.getInstance().getElementGenerator();
|
||||
PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
|
||||
PyImportStatement importStatement = PsiTreeUtil.getParentOfType(element, PyImportStatement.class);
|
||||
for (PyImportElement importElement : importStatement.getImportElements()) {
|
||||
PyReferenceExpression importReference = importElement.getImportReference();
|
||||
if (importReference != null) {
|
||||
if (LanguageLevel.forFile(file.getVirtualFile()).isPy3K()) {
|
||||
if ("__builtin__".equals(importReference.getName())) {
|
||||
importReference.replace(elementGenerator.createFromText(project, PyReferenceExpression.class, "builtins"));
|
||||
}
|
||||
} else {
|
||||
if ("builtins".equals(importReference.getName())) {
|
||||
importReference.replace(elementGenerator.createFromText(project, PyReferenceExpression.class, "__builtin__"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean startInWriteAction() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.jetbrains.python.codeInsight.intentions;
|
||||
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiWhiteSpace;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.PythonLanguage;
|
||||
import com.jetbrains.python.psi.LanguageLevel;
|
||||
import com.jetbrains.python.psi.PyElementGenerator;
|
||||
import com.jetbrains.python.psi.PyExceptPart;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: Alexey.Ivanov
|
||||
* Date: 16.02.2010
|
||||
* Time: 18:07:55
|
||||
*/
|
||||
public class ReplaceExceptPartIntention implements IntentionAction {
|
||||
@NotNull
|
||||
public String getText() {
|
||||
return PyBundle.message("INTN.convert.except.to");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getFamilyName() {
|
||||
return PyBundle.message("INTN.Family.convert.except.part");
|
||||
}
|
||||
|
||||
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
|
||||
VirtualFile virtualFile = file.getVirtualFile();
|
||||
if (virtualFile != null && !LanguageLevel.forFile(virtualFile).isPy3K()) {
|
||||
PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
|
||||
PyExceptPart exceptPart = PsiTreeUtil.getParentOfType(element, PyExceptPart.class);
|
||||
return (exceptPart != null);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
|
||||
PyExceptPart exceptPart = PsiTreeUtil.getParentOfType(file.findElementAt(editor.getCaretModel().getOffset()), PyExceptPart.class);
|
||||
PyElementGenerator elementGenerator = PythonLanguage.getInstance().getElementGenerator();
|
||||
assert exceptPart != null;
|
||||
PsiElement element = exceptPart.getExceptClass().getNextSibling();
|
||||
while (element instanceof PsiWhiteSpace) {
|
||||
element = element.getNextSibling();
|
||||
}
|
||||
assert element != null;
|
||||
element = element.replace(elementGenerator.createComma(project).getPsi());
|
||||
assert element.getPrevSibling() instanceof PsiWhiteSpace;
|
||||
element.getPrevSibling().delete();
|
||||
}
|
||||
|
||||
public boolean startInWriteAction() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -62,14 +62,18 @@ public class PyUnsupportedFeaturesInspection extends LocalInspectionTool {
|
||||
REMOVED_METHODS.add("reload");
|
||||
}
|
||||
|
||||
private static boolean isPy3K(PyElement node) {
|
||||
VirtualFile virtualFile = node.getContainingFile().getVirtualFile();
|
||||
return virtualFile != null && LanguageLevel.forFile(virtualFile).isPy3K();
|
||||
}
|
||||
|
||||
public Visitor(final ProblemsHolder holder) {
|
||||
super(holder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyBinaryExpression(PyBinaryExpression node) {
|
||||
VirtualFile virtualFile = node.getContainingFile().getVirtualFile();
|
||||
if (virtualFile != null && LanguageLevel.forFile(virtualFile).isPy3K()) {
|
||||
if (isPy3K(node)) {
|
||||
if (node.isOperator("<>")) {
|
||||
registerProblem(node, "<> is not supported in Python 3, use != instead", new ReplaceNotEqOperatorQuickFix());
|
||||
}
|
||||
@@ -78,8 +82,7 @@ public class PyUnsupportedFeaturesInspection extends LocalInspectionTool {
|
||||
|
||||
@Override
|
||||
public void visitPyNumericLiteralExpression(PyNumericLiteralExpression node) {
|
||||
VirtualFile virtualFile = node.getContainingFile().getVirtualFile();
|
||||
if (virtualFile != null && LanguageLevel.forFile(virtualFile).isPy3K()) {
|
||||
if (isPy3K(node)) {
|
||||
String text = node.getText();
|
||||
if (text.endsWith("l") || text.endsWith("L")) {
|
||||
registerProblem(node, "Integer literals do not support a trailing \'l\' or \'L\' in Python 3", new RemoveTrailingLQuickFix());
|
||||
@@ -92,8 +95,7 @@ public class PyUnsupportedFeaturesInspection extends LocalInspectionTool {
|
||||
|
||||
@Override
|
||||
public void visitPyStringLiteralExpression(PyStringLiteralExpression node) {
|
||||
VirtualFile virtualFile = node.getContainingFile().getVirtualFile();
|
||||
if (virtualFile != null && LanguageLevel.forFile(virtualFile).isPy3K()) {
|
||||
if (isPy3K(node)) {
|
||||
String text = node.getText();
|
||||
if (text.startsWith("u") || text.startsWith("U")) {
|
||||
registerProblem(node, "String literals do not support a leading \'u\' or \'U\' in Python 3", new ReamoveLeadingUQuickFix());
|
||||
@@ -101,13 +103,14 @@ public class PyUnsupportedFeaturesInspection extends LocalInspectionTool {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void visitPyListCompExpression(PyListCompExpression node) {
|
||||
List<ComprhForComponent> forComponents = node.getForComponents();
|
||||
for (ComprhForComponent forComponent: forComponents) {
|
||||
PyExpression iteratedList = forComponent.getIteratedList();
|
||||
if (iteratedList instanceof PyTupleExpression) {
|
||||
registerProblem(iteratedList, "List comprehensions do not support this syntax in Python 3", new ReplaceListComprehensionsQuickFix());
|
||||
registerProblem(iteratedList, "List comprehensions do not support such syntax in Python 3", new ReplaceListComprehensionsQuickFix());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -116,16 +119,13 @@ public class PyUnsupportedFeaturesInspection extends LocalInspectionTool {
|
||||
public void visitPyExceptBlock(PyExceptPart node) {
|
||||
PyExpression exceptClass = node.getExceptClass();
|
||||
if (exceptClass != null && node.getTarget() != null) {
|
||||
VirtualFile virtualFile = node.getContainingFile().getVirtualFile();
|
||||
if (virtualFile != null) {
|
||||
if (LanguageLevel.forFile(virtualFile).isPy3K()) {
|
||||
PsiElement element = exceptClass.getNextSibling();
|
||||
while (element instanceof PsiWhiteSpace) {
|
||||
element = element.getNextSibling();
|
||||
}
|
||||
if (element != null && ",".equals(element.getText())) {
|
||||
registerProblem(node, "Python 3 does not support this syntax", new ReplaceExceptPartQuickFix(true));
|
||||
}
|
||||
if (isPy3K(node)) {
|
||||
PsiElement element = exceptClass.getNextSibling();
|
||||
while (element instanceof PsiWhiteSpace) {
|
||||
element = element.getNextSibling();
|
||||
}
|
||||
if (element != null && ",".equals(element.getText())) {
|
||||
registerProblem(node, "Python 3 does not support this syntax", new ReplaceExceptPartQuickFix(true));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -134,68 +134,60 @@ public class PyUnsupportedFeaturesInspection extends LocalInspectionTool {
|
||||
@Override
|
||||
public void visitPyRaiseStatement(PyRaiseStatement node) {
|
||||
PyExpression[] expressions = node.getExpressions();
|
||||
assert(expressions != null);
|
||||
assert (expressions != null);
|
||||
if (expressions.length < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
VirtualFile virtualFile = node.getContainingFile().getVirtualFile();
|
||||
if (virtualFile != null) {
|
||||
if (LanguageLevel.forFile(virtualFile).isPy3K()) {
|
||||
if (expressions.length == 3) {
|
||||
registerProblem(node, "Python 3 does not support this syntax", new ReplaceRaiseStatementQuickFix());
|
||||
return;
|
||||
}
|
||||
PsiElement element = expressions[0].getNextSibling();
|
||||
while (element instanceof PsiWhiteSpace) {
|
||||
element = element.getNextSibling();
|
||||
}
|
||||
if (element != null && ",".equals(element.getText())) {
|
||||
registerProblem(node, "Python 3 does not support this syntax", new ReplaceRaiseStatementQuickFix());
|
||||
}
|
||||
} else {
|
||||
if (expressions.length == 2) {
|
||||
PsiElement element = expressions[0].getNextSibling();
|
||||
while (element instanceof PsiWhiteSpace) {
|
||||
element = element.getNextSibling();
|
||||
}
|
||||
if (element != null && "from".equals(element.getText())) {
|
||||
registerProblem(node, "Python 2 does not support raise ... from syntax");
|
||||
}
|
||||
}
|
||||
if (isPy3K(node)) {
|
||||
if (expressions.length == 3) {
|
||||
registerProblem(node, "Python 3 does not support this syntax", new ReplaceRaiseStatementQuickFix());
|
||||
return;
|
||||
}
|
||||
PsiElement element = expressions[0].getNextSibling();
|
||||
while (element instanceof PsiWhiteSpace) {
|
||||
element = element.getNextSibling();
|
||||
}
|
||||
if (element != null && ",".equals(element.getText())) {
|
||||
registerProblem(node, "Python 3 does not support this syntax", new ReplaceRaiseStatementQuickFix());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyReprExpression(PyReprExpression node) {
|
||||
VirtualFile virtualFile = node.getContainingFile().getVirtualFile();
|
||||
if (virtualFile != null && LanguageLevel.forFile(virtualFile).isPy3K()) {
|
||||
if (isPy3K(node)) {
|
||||
registerProblem(node, "Backquote is not supported in Python 3, use repr() instead", new ReplaceBackquoteExpressionQuickFix());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyCallExpression(PyCallExpression node) {
|
||||
VirtualFile virtualFile = node.getContainingFile().getVirtualFile();
|
||||
if (virtualFile != null) {
|
||||
String name = node.getCallee().getName();
|
||||
if (LanguageLevel.forFile(virtualFile).isPy3K()) {
|
||||
if ("raw_input".equals(name)) {
|
||||
registerProblem(node.getCallee(), PyBundle.message("INSP.method.$0.removed.use.$1", name, "input"),
|
||||
new ReplaceMethodQuickFix("input"));
|
||||
} else if (REMOVED_METHODS.contains(name)) {
|
||||
registerProblem(node.getCallee(), PyBundle.message("INSP.method.$0.removed", name));
|
||||
}
|
||||
} else {
|
||||
if ("super".equals(name)) {
|
||||
PyArgumentList argumentList = node.getArgumentList();
|
||||
if (argumentList != null && argumentList.getArguments().length == 0) {
|
||||
registerProblem(node, "super() should have arguments in current language version");
|
||||
public void visitPyImportStatement(PyImportStatement node) {
|
||||
if (isPy3K(node)) {
|
||||
PyImportElement[] importElements = node.getImportElements();
|
||||
for (PyImportElement importElement : importElements) {
|
||||
PyReferenceExpression importReference = importElement.getImportReference();
|
||||
if (importReference != null) {
|
||||
String name = importReference.getName();
|
||||
if ("__builtin__".equals(name)) {
|
||||
registerProblem(node, "Module __builtin__ renamed to builtins");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyCallExpression(PyCallExpression node) {
|
||||
if (isPy3K(node)) {
|
||||
String name = node.getCallee().getName();
|
||||
if ("raw_input".equals(name)) {
|
||||
registerProblem(node.getCallee(), PyBundle.message("INSP.method.$0.removed.use.$1", name, "input"),
|
||||
new ReplaceMethodQuickFix("input"));
|
||||
} else if (REMOVED_METHODS.contains(name)) {
|
||||
registerProblem(node.getCallee(), PyBundle.message("INSP.method.$0.removed", name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
package com.jetbrains.python.psi;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Dict comprehension: {x:x+1 for x in range(10)}
|
||||
*
|
||||
* @author yole
|
||||
*/
|
||||
public interface PyDictCompExpression extends PyExpression, NameDefiner {
|
||||
PyExpression getResultExpression();
|
||||
List<ComprhForComponent> getForComponents();
|
||||
List<ComprhIfComponent> getIfComponents();
|
||||
}
|
||||
|
||||
@@ -217,4 +217,8 @@ public class PyElementVisitor extends PsiElementVisitor {
|
||||
public void visitPyReprExpression(PyReprExpression node) {
|
||||
visitPyExpression(node);
|
||||
}
|
||||
|
||||
public void visitPyNonlocalStatement(PyNonlocalStatement node) {
|
||||
visitPyStatement(node);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,4 +4,5 @@ package com.jetbrains.python.psi;
|
||||
* @author yole
|
||||
*/
|
||||
public interface PyNonlocalStatement extends PyStatement {
|
||||
void accept(PyElementVisitor visitor);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
package com.jetbrains.python.psi;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Represents a Python 3 set literal expression, for example, <tt>{1, 2, 3}</tt>
|
||||
*
|
||||
* @author yole
|
||||
*/
|
||||
public interface PySetLiteralExpression extends PyExpression {
|
||||
@Nullable
|
||||
PyExpression[] getElements();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.jetbrains.python.psi.impl;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.jetbrains.python.psi.PyElementVisitor;
|
||||
import com.jetbrains.python.psi.PyNonlocalStatement;
|
||||
|
||||
/**
|
||||
@@ -10,4 +11,8 @@ public class PyNonlocalStatementImpl extends PyElementImpl implements PyNonlocal
|
||||
public PyNonlocalStatementImpl(ASTNode astNode) {
|
||||
super(astNode);
|
||||
}
|
||||
|
||||
public void accept(PyElementVisitor visitor) {
|
||||
visitor.visitPyNonlocalStatement(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
package com.jetbrains.python.psi.impl;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.jetbrains.python.psi.PyElementVisitor;
|
||||
import com.jetbrains.python.psi.PyExpression;
|
||||
import com.jetbrains.python.psi.PySetLiteralExpression;
|
||||
import com.jetbrains.python.psi.types.PyType;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
@@ -21,4 +24,9 @@ public class PySetLiteralExpressionImpl extends PyElementImpl implements PySetLi
|
||||
protected void acceptPyVisitor(PyElementVisitor pyVisitor) {
|
||||
pyVisitor.visitPySetLiteralExpression(this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PyExpression[] getElements() {
|
||||
return PsiTreeUtil.getChildrenOfType(this, PyExpression.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
package com.jetbrains.python.validation;
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiWhiteSpace;
|
||||
import com.jetbrains.python.codeInsight.intentions.ConvertDictCompIntention;
|
||||
import com.jetbrains.python.codeInsight.intentions.ConvertSetLiteralIntention;
|
||||
import com.jetbrains.python.codeInsight.intentions.ReplaceBuiltinsIntention;
|
||||
import com.jetbrains.python.codeInsight.intentions.ReplaceExceptPartIntention;
|
||||
import com.jetbrains.python.psi.*;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: Alexey.Ivanov
|
||||
* Date: 16.02.2010
|
||||
* Time: 16:16:45
|
||||
*/
|
||||
public class UnsupportedFeaturesIn2 extends PyAnnotator {
|
||||
|
||||
private static boolean isPy2(PyElement node) {
|
||||
VirtualFile virtualFile = node.getContainingFile().getVirtualFile();
|
||||
return virtualFile != null && !LanguageLevel.forFile(virtualFile).isPy3K();
|
||||
}
|
||||
|
||||
private static boolean isPy3K(PyElement node) {
|
||||
VirtualFile virtualFile = node.getContainingFile().getVirtualFile();
|
||||
return virtualFile != null && LanguageLevel.forFile(virtualFile).isPy3K();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyDictCompExpression(PyDictCompExpression node) {
|
||||
if (isPy2(node)) {
|
||||
getHolder().createWarningAnnotation(node, "Dictionary comprehension not supported in Python2").registerFix(new ConvertDictCompIntention());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPySetLiteralExpression(PySetLiteralExpression node) {
|
||||
if (isPy2(node)) {
|
||||
getHolder().createWarningAnnotation(node, "Python2 not supported set literal expressions").registerFix(new ConvertSetLiteralIntention());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyExceptBlock(PyExceptPart node) {
|
||||
if (isPy2(node)) {
|
||||
PyExpression exceptClass = node.getExceptClass();
|
||||
if (exceptClass != null) {
|
||||
PsiElement element = exceptClass.getNextSibling();
|
||||
while (element instanceof PsiWhiteSpace) {
|
||||
element = element.getNextSibling();
|
||||
}
|
||||
if (element != null && "as".equals(element.getText())) {
|
||||
getHolder().createWarningAnnotation(node, "Python2 not supported such syntax").registerFix(new ReplaceExceptPartIntention());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyImportStatement(PyImportStatement node) {
|
||||
if (isPy2(node)) {
|
||||
PyImportElement[] importElements = node.getImportElements();
|
||||
for (PyImportElement importElement : importElements) {
|
||||
PyReferenceExpression importReference = importElement.getImportReference();
|
||||
if (importReference != null) {
|
||||
String name = importReference.getName();
|
||||
if ("builtins".equals(name)) {
|
||||
getHolder().createWarningAnnotation(node, "There is no module builtins in Python2").registerFix(new ReplaceBuiltinsIntention());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyCallExpression(PyCallExpression node) {
|
||||
if (isPy2(node)) {
|
||||
PsiElement firstChild = node.getFirstChild();
|
||||
if (firstChild != null) {
|
||||
String name = firstChild.getText();
|
||||
if ("super".equals(name)) {
|
||||
PyArgumentList argumentList = node.getArgumentList();
|
||||
if (argumentList != null && argumentList.getArguments().length == 0) {
|
||||
getHolder().createWarningAnnotation(node, "super() should have arguments in Python2");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
12
python/testData/highlighting/unsupportedFeaturesInPython2.py
Normal file
12
python/testData/highlighting/unsupportedFeaturesInPython2.py
Normal file
@@ -0,0 +1,12 @@
|
||||
<warning descr="Dictionary comprehension not supported in Python2">{k: v for k, v in stuff}</warning>
|
||||
|
||||
try:
|
||||
pass
|
||||
<warning descr="Python2 not supported such syntax">except a as name:
|
||||
pass</warning>
|
||||
|
||||
class A(B):
|
||||
def foo(self):
|
||||
<warning descr="super() should have arguments in Python2">super()</warning>
|
||||
|
||||
<warning descr="Python2 not supported set literal expressions">{1, 2}</warning>
|
||||
1
python/testData/intentions/afterConvertBuiltins.py
Normal file
1
python/testData/intentions/afterConvertBuiltins.py
Normal file
@@ -0,0 +1 @@
|
||||
import __builtin__
|
||||
1
python/testData/intentions/afterConvertDictComp.py
Normal file
1
python/testData/intentions/afterConvertDictComp.py
Normal file
@@ -0,0 +1 @@
|
||||
dict([(k, chr(k + 65)) for k in range(10)])
|
||||
1
python/testData/intentions/afterConvertSetLiteral.py
Normal file
1
python/testData/intentions/afterConvertSetLiteral.py
Normal file
@@ -0,0 +1 @@
|
||||
set([1, 2, 3, 5, 34])
|
||||
4
python/testData/intentions/afterReplaceExceptPart.py
Normal file
4
python/testData/intentions/afterReplaceExceptPart.py
Normal file
@@ -0,0 +1,4 @@
|
||||
try:
|
||||
pass
|
||||
except e, name:
|
||||
pass
|
||||
1
python/testData/intentions/beforeConvertBuiltins.py
Normal file
1
python/testData/intentions/beforeConvertBuiltins.py
Normal file
@@ -0,0 +1 @@
|
||||
import <caret>builtins
|
||||
1
python/testData/intentions/beforeConvertDictComp.py
Normal file
1
python/testData/intentions/beforeConvertDictComp.py
Normal file
@@ -0,0 +1 @@
|
||||
{k: chr(k + 65)<caret> for k in range(10)}
|
||||
1
python/testData/intentions/beforeConvertSetLiteral.py
Normal file
1
python/testData/intentions/beforeConvertSetLiteral.py
Normal file
@@ -0,0 +1 @@
|
||||
{1, 2, 3,<caret> 5, 34}
|
||||
4
python/testData/intentions/beforeReplaceExceptPart.py
Normal file
4
python/testData/intentions/beforeReplaceExceptPart.py
Normal file
@@ -0,0 +1,4 @@
|
||||
try:
|
||||
pass
|
||||
except e as<caret> name:
|
||||
pass
|
||||
41
python/testSrc/com/jetbrains/python/PyIntentionTest.java
Normal file
41
python/testSrc/com/jetbrains/python/PyIntentionTest.java
Normal file
@@ -0,0 +1,41 @@
|
||||
package com.jetbrains.python;
|
||||
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.jetbrains.python.fixtures.PyLightFixtureTestCase;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: Alexey.Ivanov
|
||||
* Date: 25.02.2010
|
||||
* Time: 12:45:53
|
||||
*/
|
||||
public class PyIntentionTest extends PyLightFixtureTestCase {
|
||||
|
||||
private void doTest(String hint) throws Exception {
|
||||
myFixture.configureByFile("before" + getTestName(false) + ".py");
|
||||
final IntentionAction action = myFixture.findSingleIntention(hint);
|
||||
myFixture.launchAction(action);
|
||||
myFixture.checkResultByFile("after" + getTestName(false) + ".py");
|
||||
|
||||
}
|
||||
|
||||
protected String getTestDataPath() {
|
||||
return PythonTestUtil.getTestDataPath() + "/intentions/";
|
||||
}
|
||||
|
||||
public void testConvertDictComp() throws Exception {
|
||||
doTest(PyBundle.message("INTN.convert.dict.comp.to"));
|
||||
}
|
||||
|
||||
public void testConvertSetLiteral() throws Exception {
|
||||
doTest(PyBundle.message("INTN.convert.set.literal.to"));
|
||||
}
|
||||
|
||||
public void testReplaceExceptPart() throws Exception {
|
||||
doTest(PyBundle.message("INTN.convert.except.to"));
|
||||
}
|
||||
|
||||
public void testConvertBuiltins() throws Exception {
|
||||
doTest(PyBundle.message("INTN.convert.builtin.import"));
|
||||
}
|
||||
}
|
||||
@@ -107,6 +107,10 @@ public class PythonHighlightingTest extends PyLightFixtureTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testUnsupportedFeaturesInPython2() throws Exception {
|
||||
doTest(LanguageLevel.PYTHON26, true, false);
|
||||
}
|
||||
|
||||
public void testYieldInNestedFunction() throws Exception {
|
||||
// highlight func declaration first, lest we get an "Extra fragment highlighted" error.
|
||||
EditorColorsManager manager = EditorColorsManager.getInstance();
|
||||
|
||||
Reference in New Issue
Block a user