Unsupported features inspection is annotator now

This commit is contained in:
alexey.ivanov
2010-03-06 19:07:38 +03:00
parent 749412633d
commit 5098035f18
62 changed files with 737 additions and 832 deletions

View File

@@ -32,24 +32,6 @@ QFIX.action.failed=Action failed
QFIX.remove.trailing.semicolon=Remove trailing semicolon
QFIX.replace.noteq.operator=Replace not equal operator
QFIX.replace.backquote.expression=Replace backquote expression
QFIX.replace.method=Replace method which is not supported in current Python version
QFIX.remove.leading.u=Remove leading U
QFIX.remove.trailing.l=Remove trailing L
QFIX.replace.raise.statement=Convert raise statement to supported form
QFIX.replace.except.part=Convert except clause to supported form
QFIX.replace.list.comprehensions=Convert list comprehensions to supported form
QFIX.replace.octal.numeric.literal=Convert octal numeric literal to supported form
QFIX.dict.creation=Replace dictionary creation
QFIX.classic.class.transform=Inherit from object
@@ -70,7 +52,9 @@ INTN.alias.for.$0.dialog.title=Alias for ''{0}''?
INTN.add.alias.for.import.$0=Add alias to ''{0}''
INTN.remove.alias.for.import.$0=Remove alias ''{0}''
INTN.convert.except.to=Convert 'except exceptClass as Target' to 'except exceptClass, Target'
INTN.Family.migration.to.python3=Migration to Python 3
INTN.convert.except.to=Convert 'except exceptClass, Target' to 'except exceptClass as Target'
INTN.convert.set.literal.to=Convert set literal to 'set' method call
@@ -78,6 +62,22 @@ INTN.convert.builtin.import=Convert builtin module import to supported form
INTN.convert.dict.comp.to=Convert dictionary comprehension to 'dict' method call
INTN.replace.noteq.operator=Replace not equal operator
INTN.remove.leading.u=Remove leading U
INTN.remove.trailing.l=Remove trailing L
INTN.replace.list.comprehensions=Convert list comprehensions to supported form
INTN.replace.octal.numeric.literal=Convert octal numeric literal to supported form
INTN.replace.raise.statement=Convert raise statement to supported form
INTN.replace.backquote.expression=Replace backquote expression
INTN.replace.method=Replace method which is not supported in current Python version
# Conflict checker
CONFLICT.name.$0.obscured=Name ''{0}'' obscured by local definitions
CONFLICT.name.$0.obscured.cannot.convert=Name ''{0}'' obscured. Cannot convert.
@@ -148,11 +148,6 @@ INSP.NAME.unused=Unused local variable
INSP.unused.locals.parameter.isnot.used=Parameter ''{0}'' value is not used
INSP.unused.locals.local.variable.isnot.used=Local variable ''{0}'' value is not used
# PyUnsupportedFeaturesInspection
INSP.NAME.unsupported.features=Feature is not supported by Python 3
INSP.method.$0.removed.use.$1=Method ''{0}'' has been removed, use ''{1}'' instead
INSP.method.$0.removed=Method ''{0}'' removed
# PyDeprecatedModulesInspection
INSP.NAME.deprecated.modules=Module marked as deprecated
INSP.module.$0.is.deprecated.in.version=Module ''{0}'' is deprecated in current Python version
@@ -170,9 +165,6 @@ INSP.NAME.incorrect.assignment=Tuple assignment balance is incorrect
# PyClassicStyleClassInspection
INSP.NAME.classic.class.usage=Classic style class usage
# PyAssigningFunctionCallInspection
INSP.NAME.assigning.function=Assigning to function call which doesn't return or returns only ''None''
# Refactoring
# introduce
refactoring.introduce.name.error=Incorrect name
@@ -250,6 +242,9 @@ ANN.tuple.py3=tuple parameter unpacking is not supported in Python 3
ANN.star.import.at.top.only='import *' only allowed at module level
ANN.method.$0.removed.use.$1=Method ''{0}'' has been removed, use ''{1}'' instead
ANN.method.$0.removed=Method ''{0}'' removed
### parsing
PARSE.expected.expression=expression expected
PARSE.expected.rbracket=']' expected

View File

@@ -35,7 +35,7 @@ public class PythonLanguage extends Language {
_annotators.add(ImportAnnotator.class);
_annotators.add(StringConstantAnnotator.class);
_annotators.add(PyBuiltinAnnotator.class);
_annotators.add(UnsupportedFeaturesIn2.class);
_annotators.add(UnsupportedFeatures.class);
}

View File

@@ -1,34 +0,0 @@
package com.jetbrains.python.actions;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.PythonLanguage;
import com.jetbrains.python.psi.PyElementGenerator;
import com.jetbrains.python.psi.PyStringLiteralExpression;
import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
* User: Alexey.Ivanov
* Date: 10.02.2010
* Time: 17:45:58
*/
public class ReamoveLeadingUQuickFix implements LocalQuickFix {
@NotNull
public String getName() {
return PyBundle.message("QFIX.remove.leading.u");
}
@NotNull
public String getFamilyName() {
return PyBundle.message("INSP.GROUP.python");
}
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
PyStringLiteralExpression stringLiteralExpression = (PyStringLiteralExpression) descriptor.getPsiElement();
PyElementGenerator elementGenerator = PythonLanguage.getInstance().getElementGenerator();
stringLiteralExpression.replace(elementGenerator.createExpressionFromText(project, stringLiteralExpression.getText().substring(1)));
}
}

View File

@@ -1,35 +0,0 @@
package com.jetbrains.python.actions;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.PythonLanguage;
import com.jetbrains.python.psi.PyElementGenerator;
import com.jetbrains.python.psi.PyNumericLiteralExpression;
import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
* User: Alexey.Ivanov
* Date: 10.02.2010
* Time: 17:45:58
*/
public class RemoveTrailingLQuickFix implements LocalQuickFix {
@NotNull
public String getName() {
return PyBundle.message("QFIX.remove.trailing.l");
}
@NotNull
public String getFamilyName() {
return PyBundle.message("INSP.GROUP.python");
}
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
PyNumericLiteralExpression numericLiteralExpression = (PyNumericLiteralExpression) descriptor.getPsiElement();
PyElementGenerator elementGenerator = PythonLanguage.getInstance().getElementGenerator();
String text = numericLiteralExpression.getText();
numericLiteralExpression.replace(elementGenerator.createExpressionFromText(project, text.substring(0, text.length() - 1)));
}
}

View File

@@ -1,36 +0,0 @@
package com.jetbrains.python.actions;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.PythonLanguage;
import com.jetbrains.python.psi.PyElementGenerator;
import com.jetbrains.python.psi.PyReprExpression;
import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
* User: Alexey.Ivanov
* Date: 08.02.2010
* Time: 20:23:53
*/
public class ReplaceBackquoteExpressionQuickFix implements LocalQuickFix {
@NotNull
public String getName() {
return PyBundle.message("QFIX.replace.backquote.expression");
}
@NotNull
public String getFamilyName() {
return PyBundle.message("INSP.GROUP.python");
}
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
PyReprExpression problemElement = (PyReprExpression) descriptor.getPsiElement();
if (problemElement != null && problemElement.getExpression() != null) {
PyElementGenerator elementGenerator = PythonLanguage.getInstance().getElementGenerator();
problemElement.replace(elementGenerator.createExpressionFromText(project, "repr(" + problemElement.getExpression().getText() + ")"));
}
}
}

View File

@@ -1,57 +0,0 @@
package com.jetbrains.python.actions;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiWhiteSpace;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.PythonLanguage;
import com.jetbrains.python.psi.PyElementGenerator;
import com.jetbrains.python.psi.PyExceptPart;
import com.jetbrains.python.psi.PyTryExceptStatement;
import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
* User: Alexey.Ivanov
* Date: 10.02.2010
* Time: 19:24:17
*/
public class ReplaceExceptPartQuickFix implements LocalQuickFix {
private final boolean myPy3KFlag;
public ReplaceExceptPartQuickFix(boolean py3KFlag) {
myPy3KFlag = py3KFlag;
}
@NotNull
public String getName() {
return PyBundle.message("QFIX.replace.except.part");
}
@NotNull
public String getFamilyName() {
return PyBundle.message("INSP.GROUP.python");
}
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
PyExceptPart exceptPart = (PyExceptPart) descriptor.getPsiElement();
PyElementGenerator elementGenerator = PythonLanguage.getInstance().getElementGenerator();
PsiElement element = exceptPart.getExceptClass().getNextSibling();
while (element instanceof PsiWhiteSpace) {
element = element.getNextSibling();
}
assert element != null;
if (myPy3KFlag) {
PyTryExceptStatement newElement = elementGenerator.createFromText(project, PyTryExceptStatement.class, "try: pass except a as b: pass");
ASTNode node = newElement.getExceptParts()[0].getNode().findChildByType(PyTokenTypes.AS_KEYWORD);
assert node != null;
element.replace(node.getPsi());
} else {
element.replace(elementGenerator.createComma(project).getPsi());
}
}
}

View File

@@ -1,37 +0,0 @@
package com.jetbrains.python.actions;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.PythonLanguage;
import com.jetbrains.python.psi.PyElementGenerator;
import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.psi.PyExpressionStatement;
import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
* User: Alexey.Ivanov
* Date: 12.02.2010
* Time: 18:15:24
*/
public class ReplaceListComprehensionsQuickFix implements LocalQuickFix {
@NotNull
public String getName() {
return PyBundle.message("QFIX.replace.list.comprehensions");
}
@NotNull
public String getFamilyName() {
return PyBundle.message("INSP.GROUP.python");
}
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
PyExpression expression = (PyExpression) descriptor.getPsiElement();
PyElementGenerator elementGenerator = PythonLanguage.getInstance().getElementGenerator();
PyExpressionStatement statement = elementGenerator.createFromText(project, PyExpressionStatement.class,
"(" + expression.getText() + ")");
expression.replace(statement.getExpression());
}
}

View File

@@ -1,42 +0,0 @@
package com.jetbrains.python.actions;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.PythonLanguage;
import com.jetbrains.python.psi.PyElementGenerator;
import com.jetbrains.python.psi.PyExpression;
import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
* User: Alexey.Ivanov
* Date: 10.02.2010
* Time: 15:46:03
*/
public class ReplaceMethodQuickFix implements LocalQuickFix {
private final String myNewName;
public ReplaceMethodQuickFix(String newName) {
myNewName = newName;
}
@NotNull
public String getName() {
return PyBundle.message("QFIX.replace.method");
}
@NotNull
public String getFamilyName() {
return PyBundle.message("INSP.GROUP.python");
}
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
PyExpression problemElement = (PyExpression) descriptor.getPsiElement();
if (problemElement != null) {
PyElementGenerator elementGenerator = PythonLanguage.getInstance().getElementGenerator();
problemElement.replace(elementGenerator.createCallExpression(project, myNewName).getCallee());
}
}
}

View File

@@ -1,38 +0,0 @@
package com.jetbrains.python.actions;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.impl.source.tree.LeafPsiElement;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.PythonLanguage;
import com.jetbrains.python.psi.PyBinaryExpression;
import com.jetbrains.python.psi.PyElementGenerator;
import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
* User: Alexey.Ivanov
* Date: 08.02.2010
* Time: 19:28:35
*/
public class ReplaceNotEqOperatorQuickFix implements LocalQuickFix {
@NotNull
public String getName() {
return PyBundle.message("QFIX.replace.noteq.operator");
}
@NotNull
public String getFamilyName() {
return PyBundle.message("INSP.GROUP.python");
}
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
PsiElement operator = ((PyBinaryExpression) descriptor.getPsiElement()).getPsiOperator();
if (operator != null) {
PyElementGenerator elementGenerator = PythonLanguage.getInstance().getElementGenerator();
operator.replace(elementGenerator.createFromText(project, LeafPsiElement.class, "!="));
}
}
}

View File

@@ -1,35 +0,0 @@
package com.jetbrains.python.actions;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.PythonLanguage;
import com.jetbrains.python.psi.PyElementGenerator;
import com.jetbrains.python.psi.PyNumericLiteralExpression;
import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
* User: Alexey.Ivanov
* Date: 12.02.2010
* Time: 18:41:44
*/
public class ReplaceOctalNumericLiteralQuickFix implements LocalQuickFix {
@NotNull
public String getName() {
return PyBundle.message("QFIX.replace.octal.numeric.literal");
}
@NotNull
public String getFamilyName() {
return PyBundle.message("INSP.GROUP.python");
}
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
PyNumericLiteralExpression numericLiteralExpression = (PyNumericLiteralExpression) descriptor.getPsiElement();
PyElementGenerator elementGenerator = PythonLanguage.getInstance().getElementGenerator();
String text = numericLiteralExpression.getText();
numericLiteralExpression.replace(elementGenerator.createExpressionFromText(project, "0o" + text.substring(1)));
}
}

View File

@@ -0,0 +1,49 @@
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.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.PyElementGenerator;
import com.jetbrains.python.psi.PyStringLiteralExpression;
import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
* Author: Alexey.Ivanov
* Date: 06.03.2010
* Time: 16:50:53
*/
public class RemoveLeadingUIntention implements IntentionAction {
@NotNull
public String getText() {
return PyBundle.message("INTN.remove.leading.u");
}
@NotNull
public String getFamilyName() {
return PyBundle.message("INTN.Family.migration.to.python3");
}
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
return true;
}
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
PyStringLiteralExpression stringLiteralExpression =
PsiTreeUtil.getParentOfType(file.findElementAt(editor.getCaretModel().getOffset()), PyStringLiteralExpression.class);
if (stringLiteralExpression == null) {
return;
}
PyElementGenerator elementGenerator = PythonLanguage.getInstance().getElementGenerator();
stringLiteralExpression.replace(elementGenerator.createExpressionFromText(project, stringLiteralExpression.getText().substring(1)));
}
public boolean startInWriteAction() {
return true;
}
}

View File

@@ -0,0 +1,50 @@
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.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.PyElementGenerator;
import com.jetbrains.python.psi.PyNumericLiteralExpression;
import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
* Author: Alexey.Ivanov
* Date: 06.03.2010
* Time: 16:50:53
*/
public class RemoveTrailingLIntention implements IntentionAction {
@NotNull
public String getText() {
return PyBundle.message("INTN.remove.trailing.l");
}
@NotNull
public String getFamilyName() {
return PyBundle.message("INTN.Family.migration.to.python3");
}
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
return true;
}
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
PyNumericLiteralExpression numericLiteralExpression =
PsiTreeUtil.getParentOfType(file.findElementAt(editor.getCaretModel().getOffset()), PyNumericLiteralExpression.class);
if (numericLiteralExpression == null) {
return;
}
PyElementGenerator elementGenerator = PythonLanguage.getInstance().getElementGenerator();
String text = numericLiteralExpression.getText();
numericLiteralExpression.replace(elementGenerator.createExpressionFromText(project, text.substring(0, text.length() - 1)));
}
public boolean startInWriteAction() {
return true;
}
}

View File

@@ -0,0 +1,51 @@
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.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.PyElementGenerator;
import com.jetbrains.python.psi.PyReprExpression;
import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
* Author: Alexey.Ivanov
* Date: 06.03.2010
* Time: 16:50:53
*/
public class ReplaceBackquoteExpressionIntention implements IntentionAction {
@NotNull
public String getText() {
return PyBundle.message("INTN.replace.backquote.expression");
}
@NotNull
public String getFamilyName() {
return PyBundle.message("INTN.Family.migration.to.python3");
}
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
return true;
}
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
PyReprExpression problemElement =
PsiTreeUtil.getParentOfType(file.findElementAt(editor.getCaretModel().getOffset()), PyReprExpression.class);
if (problemElement == null) {
return;
}
if (problemElement.getExpression() != null) {
PyElementGenerator elementGenerator = PythonLanguage.getInstance().getElementGenerator();
problemElement.replace(elementGenerator.createExpressionFromText(project, "repr(" + problemElement.getExpression().getText() + ")"));
}
}
public boolean startInWriteAction() {
return true;
}
}

View File

@@ -1,6 +1,7 @@
package com.jetbrains.python.codeInsight.intentions;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
@@ -10,10 +11,11 @@ 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.PyTokenTypes;
import com.jetbrains.python.PythonLanguage;
import com.jetbrains.python.psi.LanguageLevel;
import com.jetbrains.python.psi.PyElementGenerator;
import com.jetbrains.python.psi.PyExceptPart;
import com.jetbrains.python.psi.PyTryExceptStatement;
import org.jetbrains.annotations.NotNull;
/**
@@ -30,12 +32,12 @@ public class ReplaceExceptPartIntention implements IntentionAction {
@NotNull
public String getFamilyName() {
return PyBundle.message("INTN.Family.convert.except.part");
return PyBundle.message("INTN.Family.migration.to.python3");
}
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
VirtualFile virtualFile = file.getVirtualFile();
if (virtualFile != null && !LanguageLevel.forFile(virtualFile).isPy3K()) {
if (virtualFile != null) {
PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
PyExceptPart exceptPart = PsiTreeUtil.getParentOfType(element, PyExceptPart.class);
return (exceptPart != null);
@@ -52,9 +54,11 @@ public class ReplaceExceptPartIntention implements IntentionAction {
element = element.getNextSibling();
}
assert element != null;
element = element.replace(elementGenerator.createComma(project).getPsi());
assert element.getPrevSibling() instanceof PsiWhiteSpace;
element.getPrevSibling().delete();
PyTryExceptStatement newElement =
elementGenerator.createFromText(project, PyTryExceptStatement.class, "try: pass except a as b: pass");
ASTNode node = newElement.getExceptParts()[0].getNode().findChildByType(PyTokenTypes.AS_KEYWORD);
assert node != null;
element.replace(node.getPsi());
}
public boolean startInWriteAction() {

View File

@@ -0,0 +1,52 @@
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.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.PyElementGenerator;
import com.jetbrains.python.psi.PyExpressionStatement;
import com.jetbrains.python.psi.PyTupleExpression;
import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
* Author: Alexey.Ivanov
* Date: 06.03.2010
* Time: 16:50:53
*/
public class ReplaceListComprehensionsIntention implements IntentionAction {
@NotNull
public String getText() {
return PyBundle.message("INTN.replace.list.comprehensions");
}
@NotNull
public String getFamilyName() {
return PyBundle.message("INTN.Family.migration.to.python3");
}
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
return true;
}
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
PyTupleExpression expression =
PsiTreeUtil.getParentOfType(file.findElementAt(editor.getCaretModel().getOffset()), PyTupleExpression.class);
if (expression == null) {
return;
}
PyElementGenerator elementGenerator = PythonLanguage.getInstance().getElementGenerator();
PyExpressionStatement statement = elementGenerator.createFromText(project, PyExpressionStatement.class,
"(" + expression.getText() + ")");
expression.replace(statement.getExpression());
}
public boolean startInWriteAction() {
return true;
}
}

View File

@@ -0,0 +1,54 @@
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.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.PyCallExpression;
import com.jetbrains.python.psi.PyElementGenerator;
import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
* Author: Alexey.Ivanov
* Date: 06.03.2010
* Time: 16:50:53
*/
public class ReplaceMethodIntention implements IntentionAction {
private final String myNewName;
public ReplaceMethodIntention(String newName) {
myNewName = newName;
}
@NotNull
public String getText() {
return PyBundle.message("INTN.replace.method");
}
@NotNull
public String getFamilyName() {
return PyBundle.message("INTN.Family.migration.to.python3");
}
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
return true;
}
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
PyCallExpression problemElement =
PsiTreeUtil.getParentOfType(file.findElementAt(editor.getCaretModel().getOffset()), PyCallExpression.class);
if (problemElement != null) {
PyElementGenerator elementGenerator = PythonLanguage.getInstance().getElementGenerator();
problemElement.getCallee().replace(elementGenerator.createCallExpression(project, myNewName).getCallee());
}
}
public boolean startInWriteAction() {
return true;
}
}

View File

@@ -0,0 +1,53 @@
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.impl.source.tree.LeafPsiElement;
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.PyBinaryExpression;
import com.jetbrains.python.psi.PyElementGenerator;
import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
* Author: Alexey.Ivanov
* Date: 06.03.2010
* Time: 16:16:52
*/
public class ReplaceNotEqOperatorIntention implements IntentionAction {
@NotNull
public String getText() {
return PyBundle.message("INTN.replace.noteq.operator");
}
@NotNull
public String getFamilyName() {
return PyBundle.message("INTN.Family.migration.to.python3");
}
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
return true;
}
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
PyBinaryExpression binaryExpression = PsiTreeUtil.getParentOfType(file.findElementAt(editor.getCaretModel().getOffset()), PyBinaryExpression.class);
if (binaryExpression == null) {
return;
}
PsiElement operator = binaryExpression.getPsiOperator();
if (operator != null) {
PyElementGenerator elementGenerator = PythonLanguage.getInstance().getElementGenerator();
operator.replace(elementGenerator.createFromText(project, LeafPsiElement.class, "!="));
}
}
public boolean startInWriteAction() {
return true;
}
}

View File

@@ -0,0 +1,50 @@
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.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.PyElementGenerator;
import com.jetbrains.python.psi.PyNumericLiteralExpression;
import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
* Author: Alexey.Ivanov
* Date: 06.03.2010
* Time: 16:50:53
*/
public class ReplaceOctalNumericLiteralIntention implements IntentionAction {
@NotNull
public String getText() {
return PyBundle.message("INTN.replace.octal.numeric.literal");
}
@NotNull
public String getFamilyName() {
return PyBundle.message("INTN.Family.migration.to.python3");
}
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
return true;
}
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
PyNumericLiteralExpression numericLiteralExpression =
PsiTreeUtil.getParentOfType(file.findElementAt(editor.getCaretModel().getOffset()), PyNumericLiteralExpression.class);
if (numericLiteralExpression == null) {
return;
}
PyElementGenerator elementGenerator = PythonLanguage.getInstance().getElementGenerator();
String text = numericLiteralExpression.getText();
numericLiteralExpression.replace(elementGenerator.createExpressionFromText(project, "0o" + text.substring(1)));
}
public boolean startInWriteAction() {
return true;
}
}

View File

@@ -1,8 +1,11 @@
package com.jetbrains.python.actions;
package com.jetbrains.python.codeInsight.intentions;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
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.PyElementGenerator;
@@ -12,23 +15,31 @@ import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
* User: Alexey.Ivanov
* Date: 10.02.2010
* Time: 19:24:17
* Author: Alexey.Ivanov
* Date: 06.03.2010
* Time: 16:50:53
*/
public class ReplaceRaiseStatementQuickFix implements LocalQuickFix {
public class ReplaceRaiseStatementIntention implements IntentionAction {
@NotNull
public String getName() {
return PyBundle.message("QFIX.replace.raise.statement");
public String getText() {
return PyBundle.message("INTN.replace.raise.statement");
}
@NotNull
public String getFamilyName() {
return PyBundle.message("INSP.GROUP.python");
return PyBundle.message("INTN.Family.migration.to.python3");
}
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
PyRaiseStatement raiseStatement = (PyRaiseStatement) descriptor.getPsiElement();
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
return true;
}
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
PyRaiseStatement raiseStatement =
PsiTreeUtil.getParentOfType(file.findElementAt(editor.getCaretModel().getOffset()), PyRaiseStatement.class);
if (raiseStatement == null) {
return;
}
PyExpression[] expressions = raiseStatement.getExpressions();
assert expressions != null;
PyElementGenerator elementGenerator = PythonLanguage.getInstance().getElementGenerator();
@@ -40,4 +51,8 @@ public class ReplaceRaiseStatementQuickFix implements LocalQuickFix {
"raise " + newExpressionText + ".with_traceback(" + expressions[2].getText() + ")"));
}
}
}
public boolean startInWriteAction() {
return true;
}
}

View File

@@ -1,79 +0,0 @@
package com.jetbrains.python.inspections;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.psi.PsiElementVisitor;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.psi.*;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
* Author: Alexey.Ivanov
* Date: 06.03.2010
* Time: 14:34:10
*/
public class PyAssigningFunctionCallInspection extends LocalInspectionTool {
@Nls
@NotNull
@Override
public String getGroupDisplayName() {
return PyBundle.message("INSP.GROUP.python");
}
@Nls
@NotNull
@Override
public String getDisplayName() {
return PyBundle.message("INSP.NAME.assigning.function");
}
@NotNull
@Override
public String getShortName() {
return "PyAssigningFunctionCallInspection";
}
@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
return new Visitor(holder);
}
private static class Visitor extends PyInspectionVisitor {
public Visitor(final ProblemsHolder holder) {
super(holder);
}
@Override
public void visitPyAssignmentStatement(PyAssignmentStatement node) {
if (node.getAssignedValue() instanceof PyCallExpression) {
PyCallExpression callExpression = (PyCallExpression)node.getAssignedValue();
PyCallExpression.PyMarkedFunction pyMarkedFunction = callExpression.resolveCallee();
if (pyMarkedFunction == null) {
return;
}
PyReturnStatement[] returnStatements = PyUtil.getAllChildrenOfType(pyMarkedFunction.getFunction(), PyReturnStatement.class);
if (returnStatements.length == 0) {
registerProblem(node, "Assigning to function call which doesn't have return statements");
return;
}
for (PyReturnStatement returnStatement: returnStatements) {
PyExpression expression = returnStatement.getExpression();
if (expression instanceof PyReferenceExpression) {
PyReferenceExpression referenceExpression = (PyReferenceExpression)expression;
if (!PyNames.NONE.equals(referenceExpression.getReferencedName())) {
return;
}
} else if (expression != null) {
return;
}
}
registerProblem(node, "Assigning to function which doesn't return value");
}
}
}
}

View File

@@ -1,193 +0,0 @@
package com.jetbrains.python.inspections;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiWhiteSpace;
import com.intellij.util.containers.HashSet;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.actions.*;
import com.jetbrains.python.psi.*;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.Set;
/**
* Created by IntelliJ IDEA.
* User: Alexey.Ivanov
* Date: 08.02.2010
* Time: 18:05:36
*/
public class PyUnsupportedFeaturesInspection extends LocalInspectionTool {
@Nls
@NotNull
@Override
public String getGroupDisplayName() {
return PyBundle.message("INSP.GROUP.python");
}
@Nls
@NotNull
@Override
public String getDisplayName() {
return PyBundle.message("INSP.NAME.unsupported.features");
}
@NotNull
@Override
public String getShortName() {
return "PyUnsupportedFeaturesInspection";
}
@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
return new Visitor(holder);
}
static class Visitor extends PyInspectionVisitor {
private static Set<String> REMOVED_METHODS = new HashSet<String>();
static {
REMOVED_METHODS.add("cmp");
REMOVED_METHODS.add("apply");
REMOVED_METHODS.add("callable");
REMOVED_METHODS.add("coerce");
REMOVED_METHODS.add("execfile");
REMOVED_METHODS.add("reduce");
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) {
if (node.isOperator("<>")) {
String message = isPy3K(node) ? "<> is not supported in Python 3, use != instead" : "<> is deprecated, use != instead";
registerProblem(node, message, new ReplaceNotEqOperatorQuickFix());
}
}
@Override
public void visitPyNumericLiteralExpression(PyNumericLiteralExpression node) {
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());
}
if (text.charAt(0) == '0' && (text.charAt(1) != 'o' || text.charAt(1) != 'b')) {
registerProblem(node, "Python 3 requires '0o' prefix for octal literals", new ReplaceOctalNumericLiteralQuickFix());
}
}
}
@Override
public void visitPyStringLiteralExpression(PyStringLiteralExpression node) {
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());
}
}
}
@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());
}
}
}
@Override
public void visitPyExceptBlock(PyExceptPart node) {
PyExpression exceptClass = node.getExceptClass();
if (exceptClass != null && node.getTarget() != null) {
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));
}
}
}
}
@Override
public void visitPyRaiseStatement(PyRaiseStatement node) {
PyExpression[] expressions = node.getExpressions();
if (expressions != null) {
if (expressions.length < 2) {
return;
}
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) {
if (isPy3K(node)) {
registerProblem(node, "Backquote is not supported in Python 3, use repr() instead", new ReplaceBackquoteExpressionQuickFix());
}
}
@Override
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));
}
}
}
}
}

View File

@@ -21,13 +21,11 @@ public class PythonInspectionToolProvider implements InspectionToolProvider {
PyTrailingSemicolonInspection.class,
PyReturnFromInitInspection.class,
PyUnusedLocalVariableInspection.class,
PyUnsupportedFeaturesInspection.class,
PyDeprecatedModulesInspection.class,
PyDictCreationInspection.class,
PyExceptClausesOrderInspection.class,
PyTupleAssignmentBalanceInspection.class,
PyClassicStyleClassInspection.class,
PyAssigningFunctionCallInspection.class
PyClassicStyleClassInspection.class
};
}
}

View File

@@ -0,0 +1,223 @@
package com.jetbrains.python.validation;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiWhiteSpace;
import com.intellij.util.containers.HashSet;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.codeInsight.intentions.*;
import com.jetbrains.python.psi.*;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.Set;
/**
* Created by IntelliJ IDEA.
* User: Alexey.Ivanov
* Date: 16.02.2010
* Time: 16:16:45
*/
public class UnsupportedFeatures extends PyAnnotator {
private static Set<String> REMOVED_METHODS = new HashSet<String>();
static {
REMOVED_METHODS.add("cmp");
REMOVED_METHODS.add("apply");
REMOVED_METHODS.add("callable");
REMOVED_METHODS.add("coerce");
REMOVED_METHODS.add("execfile");
REMOVED_METHODS.add("reduce");
REMOVED_METHODS.add("reload");
}
@NotNull
private static LanguageLevel getLanguageLevel(PyElement node) {
VirtualFile virtualFile = node.getContainingFile().getVirtualFile();
if (virtualFile != null) {
return LanguageLevel.forFile(virtualFile);
}
return LanguageLevel.getDefault();
}
private static boolean isPy2(PyElement node) {
return !getLanguageLevel(node).isPy3K();
}
private static boolean isPy3K(PyElement node) {
return getLanguageLevel(node).isPy3K();
}
@Override
public void visitPyDictCompExpression(PyDictCompExpression node) {
if (isPy2(node)) {
getHolder().createWarningAnnotation(node, "Dictionary comprehension is not supported in Python 2").registerFix(new ConvertDictCompIntention());
}
}
@Override
public void visitPySetLiteralExpression(PySetLiteralExpression node) {
if (isPy2(node)) {
getHolder().createWarningAnnotation(node, "Python 2 does not support set literal expressions").registerFix(new ConvertSetLiteralIntention());
}
}
@Override
public void visitPyExceptBlock(PyExceptPart node) {
PyExpression exceptClass = node.getExceptClass();
if (exceptClass != null) {
LanguageLevel languageLevel = getLanguageLevel(node);
if (languageLevel == LanguageLevel.PYTHON24 || languageLevel == LanguageLevel.PYTHON25) {
PsiElement element = exceptClass.getNextSibling();
while (element instanceof PsiWhiteSpace) {
element = element.getNextSibling();
}
if (element != null && "as".equals(element.getText())) {
getHolder().createWarningAnnotation(node, "This Python version does not support this syntax");
}
}
else if (isPy3K(node)) {
PsiElement element = exceptClass.getNextSibling();
while (element instanceof PsiWhiteSpace) {
element = element.getNextSibling();
}
if (element != null && ",".equals(element.getText())) {
getHolder().createWarningAnnotation(node, "Python 3 does not support this syntax").registerFix(new ReplaceExceptPartIntention());
}
}
}
}
@Override
public void visitPyImportStatement(PyImportStatement node) {
PyImportElement[] importElements = node.getImportElements();
for (PyImportElement importElement : importElements) {
PyReferenceExpression importReference = importElement.getImportReference();
if (importReference != null) {
String name = importReference.getName();
if (isPy2(node)) {
if ("builtins".equals(name)) {
getHolder().createWarningAnnotation(node, "There is no module builtins in Python 2")
.registerFix(new ReplaceBuiltinsIntention());
}
}
else {
if ("__builtin__".equals(name)) {
getHolder().createWarningAnnotation(node, "Module __builtin__ renamed to builtins").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 Python 2");
}
}
}
} else {
String name = node.getCallee().getName();
if ("raw_input".equals(name)) {
getHolder().createWarningAnnotation(node.getCallee(), PyBundle.message("ANN.method.$0.removed.use.$1", name, "input")).
registerFix(new ReplaceMethodIntention("input"));
}
else if (REMOVED_METHODS.contains(name)) {
getHolder().createWarningAnnotation(node.getCallee(), PyBundle.message("ANN.method.$0.removed", name));
}
}
}
@Override
public void visitPyStarExpression(PyStarExpression node) {
if (isPy2(node)) {
getHolder().createWarningAnnotation(node, "Python 2 does not support star expressions");
}
}
@Override
public void visitPyBinaryExpression(PyBinaryExpression node) {
if (node.isOperator("<>")) {
String message = isPy3K(node) ? "<> is not supported in Python 3, use != instead" : "<> is deprecated, use != instead";
getHolder().createWarningAnnotation(node, message).registerFix(new ReplaceNotEqOperatorIntention());
}
}
@Override
public void visitPyNumericLiteralExpression(PyNumericLiteralExpression node) {
if (isPy3K(node)) {
String text = node.getText();
if (text.endsWith("l") || text.endsWith("L")) {
getHolder().createWarningAnnotation(node,
"Integer literals do not support a trailing \'l\' or \'L\' in Python 3").registerFix(new RemoveTrailingLIntention());
}
if (text.length() > 1 && text.charAt(0) == '0' && (text.charAt(1) != 'o' || text.charAt(1) != 'b')) {
getHolder().createWarningAnnotation(node,
"Python 3 requires '0o' prefix for octal literals").registerFix(new ReplaceOctalNumericLiteralIntention());
}
}
}
@Override
public void visitPyStringLiteralExpression(PyStringLiteralExpression node) {
if (isPy3K(node)) {
String text = node.getText();
if (text.startsWith("u") || text.startsWith("U")) {
getHolder().createWarningAnnotation(node,
"String literals do not support a leading \'u\' or \'U\' in Python 3").registerFix(new RemoveLeadingUIntention());
}
}
}
@Override
public void visitPyListCompExpression(PyListCompExpression node) {
List<ComprhForComponent> forComponents = node.getForComponents();
for (ComprhForComponent forComponent : forComponents) {
PyExpression iteratedList = forComponent.getIteratedList();
if (iteratedList instanceof PyTupleExpression) {
getHolder().createWarningAnnotation(iteratedList,
"List comprehensions do not support this syntax in Python 3").registerFix(new ReplaceListComprehensionsIntention());
}
}
}
@Override
public void visitPyRaiseStatement(PyRaiseStatement node) {
PyExpression[] expressions = node.getExpressions();
if (expressions != null) {
if (expressions.length < 2) {
return;
}
if (isPy3K(node)) {
if (expressions.length == 3) {
getHolder().createWarningAnnotation(node, "Python 3 does not support this syntax")
.registerFix(new ReplaceRaiseStatementIntention());
return;
}
PsiElement element = expressions[0].getNextSibling();
while (element instanceof PsiWhiteSpace) {
element = element.getNextSibling();
}
if (element != null && ",".equals(element.getText())) {
getHolder().createWarningAnnotation(node, "Python 3 does not support this syntax")
.registerFix(new ReplaceRaiseStatementIntention());
}
}
}
}
@Override
public void visitPyReprExpression(PyReprExpression node) {
if (isPy3K(node)) {
getHolder().createWarningAnnotation(node, "Backquote is not supported in Python 3, use repr() instead").registerFix(new ReplaceBackquoteExpressionIntention());
}
}
}

View File

@@ -1,98 +0,0 @@
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 is not supported in Python 2").registerFix(new ConvertDictCompIntention());
}
}
@Override
public void visitPySetLiteralExpression(PySetLiteralExpression node) {
if (isPy2(node)) {
getHolder().createWarningAnnotation(node, "Python 2 does not support 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, "Python 2 does not support this 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 Python 2").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 Python 2");
}
}
}
}
}
@Override
public void visitPyStarExpression(PyStarExpression node) {
if (isPy2(node)) {
getHolder().createWarningAnnotation(node, "Python 2 does not support star expressions");
}
}
}

View File

@@ -2,7 +2,7 @@
try:
pass
<warning descr="Python 2 does not support this syntax">except a as name:
<warning descr="This Python version does not support this syntax">except a as name:
pass</warning>
class A(B):
@@ -11,4 +11,7 @@ class A(B):
<warning descr="Python 2 does not support set literal expressions">{1, 2}</warning>
<warning descr="Python 2 does not support star expressions">*b</warning>, c = 1, 2, 3, 4, 5
<warning descr="Python 2 does not support star expressions">*b</warning>, c = 1, 2, 3, 4, 5
if <warning descr="<> is deprecated, use != instead">a <> 2</warning>:
pass

View File

@@ -0,0 +1,17 @@
print(<warning descr="<> is not supported in Python 3, use != instead">a <> 3</warning>)
<warning descr="Backquote is not supported in Python 3, use repr() instead">`foo()`</warning>
x = <warning descr="Method 'raw_input' has been removed, use 'input' instead">raw_input</warning>()
a = <warning descr="Integer literals do not support a trailing 'l' or 'L' in Python 3">123l</warning>
a = <warning descr="Python 3 requires '0o' prefix for octal literals">043</warning>
s = <warning descr="String literals do not support a leading 'u' or 'U' in Python 3">u"text"</warning>
<warning descr="Python 3 does not support this syntax">raise a, b, c</warning>
<warning descr="Python 3 does not support this syntax">raise a, b</warning>
try:
pass
<warning descr="Python 3 does not support this syntax">except a, name:
pass</warning>
[x * 2 for x in <warning descr="List comprehensions do not support this syntax in Python 3">vec1, vec2</warning>]
<warning descr="Module __builtin__ renamed to builtins">import __builtin__</warning>

View File

@@ -1 +0,0 @@
a = <caret><warning descr="String literals do not support a leading 'u' or 'U' in Python 3">u"text"</warning>

View File

@@ -1 +0,0 @@
a = <caret><warning descr="Integer literals do not support a trailing 'l' or 'L' in Python 3">1223l</warning>

View File

@@ -1 +0,0 @@
<caret><warning descr="Backquote is not supported in Python 3, use repr() instead">`a + b, 34 + a`</warning>

View File

@@ -1,4 +0,0 @@
try:
pass
<caret><warning descr="Python2 not supported such syntax">except a as name:
pass</warning>

View File

@@ -1,4 +0,0 @@
try:
pass
except a , name:
pass

View File

@@ -1,4 +0,0 @@
try:
pass
<caret><warning descr="Python 3 does not support this syntax">except a, name:
pass</warning>

View File

@@ -1,4 +0,0 @@
try:
pass
except a as name:
pass

View File

@@ -1 +0,0 @@
[x * 2 for x in <caret><warning descr="List comprehensions do not support this syntax in Python 3">[1, 2], [2, 3]</warning>]

View File

@@ -1 +0,0 @@
a = <caret><warning descr="Method 'raw_input' has been removed, use 'input' instead">raw_input</warning>()

View File

@@ -1 +0,0 @@
print(<caret><warning descr="<> is not supported in Python 3, use != instead">a <> b</warning>)

View File

@@ -1 +0,0 @@
a = <caret><warning descr="Python 3 requires '0o' prefix for octal literals">01223</warning>

View File

@@ -1 +0,0 @@
<caret><warning descr="Python 3 does not support this syntax">raise a, b, c</warning>

View File

@@ -1 +1 @@
import __builtin__
import builtins

View File

@@ -1,4 +1,4 @@
try:
pass
except e, name:
except e as name:
pass

View File

@@ -1 +1 @@
import <caret>builtins
import __<caret>builtin__

View File

@@ -0,0 +1 @@
a = <caret>u"text"

View File

@@ -0,0 +1 @@
a = <caret>1223l

View File

@@ -0,0 +1 @@
<caret>`a + b, 34 + a`

View File

@@ -1,4 +1,4 @@
try:
pass
except e as<caret> name:
except e,<caret> name:
pass

View File

@@ -0,0 +1 @@
[x * 2 for x in [1, 2], <caret>[2, 3]]

View File

@@ -0,0 +1 @@
a = <caret>raw_input()

View File

@@ -0,0 +1 @@
print(<caret>a <> b)

View File

@@ -0,0 +1 @@
a = <caret>01223

View File

@@ -0,0 +1 @@
raise<caret> a, b, c

View File

@@ -2,6 +2,8 @@ package com.jetbrains.python;
import com.intellij.codeInsight.intention.IntentionAction;
import com.jetbrains.python.fixtures.PyLightFixtureTestCase;
import com.jetbrains.python.psi.LanguageLevel;
import com.jetbrains.python.psi.impl.PythonLanguageLevelPusher;
/**
* Created by IntelliJ IDEA.
@@ -16,7 +18,17 @@ public class PyIntentionTest extends PyLightFixtureTestCase {
final IntentionAction action = myFixture.findSingleIntention(hint);
myFixture.launchAction(action);
myFixture.checkResultByFile("after" + getTestName(false) + ".py");
}
private void doTest(String hint, LanguageLevel languageLevel) throws Exception {
PythonLanguageLevelPusher.FORCE_LANGUAGE_LEVEL = languageLevel;
PythonLanguageLevelPusher.pushLanguageLevel(myFixture.getProject());
try {
doTest(hint);
}
finally {
PythonLanguageLevelPusher.FORCE_LANGUAGE_LEVEL = null;
}
}
protected String getTestDataPath() {
@@ -32,10 +44,43 @@ public class PyIntentionTest extends PyLightFixtureTestCase {
}
public void testReplaceExceptPart() throws Exception {
doTest(PyBundle.message("INTN.convert.except.to"));
doTest(PyBundle.message("INTN.convert.except.to"), LanguageLevel.PYTHON30);
}
public void testConvertBuiltins() throws Exception {
doTest(PyBundle.message("INTN.convert.builtin.import"));
doTest(PyBundle.message("INTN.convert.builtin.import"), LanguageLevel.PYTHON30);
}
public void testReplaceNotEqOperator() throws Exception {
doTest(PyBundle.message("INTN.replace.noteq.operator"));
}
public void testRemoveLeadingU() throws Exception {
doTest(PyBundle.message("INTN.remove.leading.u"), LanguageLevel.PYTHON30);
}
public void testRemoveTrailingL() throws Exception {
doTest(PyBundle.message("INTN.remove.trailing.l"), LanguageLevel.PYTHON30);
}
public void testReplaceOctalNumericLiteral() throws Exception {
doTest(PyBundle.message("INTN.replace.octal.numeric.literal"), LanguageLevel.PYTHON30);
}
public void testReplaceListComprehensions() throws Exception {
doTest(PyBundle.message("INTN.replace.list.comprehensions"), LanguageLevel.PYTHON30);
}
public void testReplaceRaiseStatement() throws Exception {
doTest(PyBundle.message("INTN.replace.raise.statement"), LanguageLevel.PYTHON30);
}
public void testReplaceBackquoteExpression() throws Exception {
doTest(PyBundle.message("INTN.replace.backquote.expression"), LanguageLevel.PYTHON30);
}
public void testReplaceMethod() throws Exception {
doTest(PyBundle.message("INTN.replace.method"), LanguageLevel.PYTHON30);
}
}

View File

@@ -88,55 +88,6 @@ public class PyQuickFixTest extends PyLightFixtureTestCase {
true, true);
}
// we don't really need quickfixes for convering Py3 syntax into Py2
public void _testReplaceExceptPartTo2() throws Exception {
doInspectionTest("ReplaceExceptPartTo2.py", PyUnsupportedFeaturesInspection.class, PyBundle.message("QFIX.replace.except.part"), true,
true);
}
public void testReplaceNotEqOperator() throws Exception {
doInspectionTestWithPy3k("ReplaceNotEqOperator.py", PyUnsupportedFeaturesInspection.class,
PyBundle.message("QFIX.replace.noteq.operator"), true, true);
}
public void testReplaceBackquoteExpression() throws Exception {
doInspectionTestWithPy3k("ReplaceBackQuoteExpression.py", PyUnsupportedFeaturesInspection.class,
PyBundle.message("QFIX.replace.backquote.expression"), true, true);
}
public void testReplaceMethod() throws Exception {
doInspectionTestWithPy3k("ReplaceMethod.py", PyUnsupportedFeaturesInspection.class, PyBundle.message("QFIX.replace.method"),
true, true);
}
public void testRemoveLeadingU() throws Exception {
doInspectionTestWithPy3k("RemoveLeadingU.py", PyUnsupportedFeaturesInspection.class, PyBundle.message("QFIX.remove.leading.u"), true, true);
}
public void testTrailingL() throws Exception {
doInspectionTestWithPy3k("RemoveTrailingL.py", PyUnsupportedFeaturesInspection.class, PyBundle.message("QFIX.remove.trailing.l"), true, true);
}
public void testReplaceOctalNumericLiteral() throws Exception {
doInspectionTestWithPy3k("ReplaceOctalNumericLiteral.py", PyUnsupportedFeaturesInspection.class,
PyBundle.message("QFIX.replace.octal.numeric.literal"), true, true);
}
public void testReplaceRaiseStatement() throws Exception {
doInspectionTestWithPy3k("ReplaceRaiseStatement.py", PyUnsupportedFeaturesInspection.class,
PyBundle.message("QFIX.replace.raise.statement"), true, true);
}
public void testReplaceExceptPartTo3() throws Exception {
doInspectionTestWithPy3k("ReplaceExceptPartTo3.py", PyUnsupportedFeaturesInspection.class, PyBundle.message("QFIX.replace.except.part"),
true, true);
}
public void testReplaceListComprehensions() throws Exception {
doInspectionTestWithPy3k("ReplaceListComprehensions.py", PyUnsupportedFeaturesInspection.class,
PyBundle.message("QFIX.replace.list.comprehensions"), true, true);
}
public void testDictCreation() throws Exception {
doInspectionTest("DictCreation.py", PyDictCreationInspection.class, PyBundle.message("QFIX.dict.creation"), true, true);
}
@@ -146,12 +97,13 @@ public class PyQuickFixTest extends PyLightFixtureTestCase {
PyBundle.message("QFIX.classic.class.transform"), true, true);
}
protected void doInspectionTestWithPy3k(@NonNls String testFileName,
final Class inspectionClass,
@NonNls String quickFixName,
boolean applyFix,
boolean available) throws Exception {
PythonLanguageLevelPusher.FORCE_LANGUAGE_LEVEL = LanguageLevel.PYTHON30;
protected void doInspectionTest(@NonNls String testFileName,
final Class inspectionClass,
@NonNls String quickFixName,
boolean applyFix,
boolean available,
LanguageLevel languageLevel) throws Exception {
PythonLanguageLevelPusher.FORCE_LANGUAGE_LEVEL = languageLevel;
PythonLanguageLevelPusher.pushLanguageLevel(myFixture.getProject());
try {
doInspectionTest(testFileName, inspectionClass, quickFixName, applyFix, available);

View File

@@ -126,7 +126,11 @@ public class PythonHighlightingTest extends PyLightFixtureTestCase {
}
public void testUnsupportedFeaturesInPython2() throws Exception {
doTest(LanguageLevel.PYTHON26, true, false);
doTest(LanguageLevel.PYTHON25, true, false);
}
public void testUnsupportedFeaturesInPython3() throws Exception {
doTest(LanguageLevel.PYTHON30, true, false);
}
public void testYieldInNestedFunction() throws Exception {

View File

@@ -81,11 +81,6 @@ public class PythonInspectionsTest extends PyLightFixtureTestCase {
doTest(getTestName(false), inspection);
}
public void testPyUnsupportedFeaturesInspection() throws Throwable {
LocalInspectionTool inspection = new PyUnsupportedFeaturesInspection();
doTestWithPy3k(getTestName(false), inspection);
}
public void testPyDictCreationInspection() throws Throwable {
LocalInspectionTool inspection = new PyDictCreationInspection();
doTest(getTestName(false), inspection);
@@ -122,9 +117,4 @@ public class PythonInspectionsTest extends PyLightFixtureTestCase {
LocalInspectionTool inspection = new PyExceptClausesOrderInspection();
doTest(getTestName(false), inspection);
}
public void testPyAssigningFunctionCallInspection() throws Throwable {
LocalInspectionTool inspection = new PyAssigningFunctionCallInspection();
doTest(getTestName(false), inspection);
}
}