Merge remote-tracking branch 'origin/master'

Conflicts:
	python/testSrc/com/jetbrains/python/PyResolveTest.java
This commit is contained in:
Dmitry Jemerov
2012-08-30 20:11:59 +02:00
51 changed files with 395 additions and 101 deletions
+6 -2
View File
@@ -9,6 +9,10 @@ import javax.swing.*;
* Don't repeat mistakes of others ;-)
*/
public class PythonHelpersIcons {
public static final Icon Keybd_closed = IconLoader.getIcon("/coverage/htmlfiles/keybd_closed.png"); // 35x12
public static final Icon Keybd_open = IconLoader.getIcon("/coverage/htmlfiles/keybd_open.png"); // 35x12
private static Icon load(String path) {
return IconLoader.getIcon(path, PythonHelpersIcons.class);
}
public static final Icon Keybd_closed = load("/coverage/htmlfiles/keybd_closed.png"); // 35x12
public static final Icon Keybd_open = load("/coverage/htmlfiles/keybd_open.png"); // 35x12
}
@@ -9,12 +9,12 @@ import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.projectRoots.ProjectJdkTable;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.util.IconLoader;
import com.intellij.patterns.ElementPattern;
import com.intellij.util.indexing.FileContent;
import com.jetbrains.python.PythonFileType;
import com.jetbrains.python.module.PythonModuleType;
import com.jetbrains.python.sdk.PythonSdkType;
import icons.PythonIcons;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -26,7 +26,7 @@ import java.util.List;
* @author yole
*/
public class PythonFacetType extends FacetType<PythonFacet, PythonFacetConfiguration> {
public static final Icon ICON = IconLoader.getIcon("/com/jetbrains/python/icons/python.png");
public static final Icon ICON = PythonIcons.Python.Icons.Python;
@NonNls
private static final String ID = "Python";
@@ -1,7 +1,7 @@
package com.jetbrains.rest;
import com.intellij.openapi.fileTypes.LanguageFileType;
import com.intellij.openapi.util.IconLoader;
import icons.RestIcons;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -40,7 +40,7 @@ public class RestFileType extends LanguageFileType {
@Nullable
public Icon getIcon() {
return IconLoader.getIcon("/com/jetbrains/rest/res/rst.png", RestFileType.class);
return RestIcons.Rst;
}
}
+5 -1
View File
@@ -9,5 +9,9 @@ import javax.swing.*;
* Don't repeat mistakes of others ;-)
*/
public class RestIcons {
public static final Icon Rst = IconLoader.getIcon("/com/jetbrains/rest/res/rst.png"); // 16x16
private static Icon load(String path) {
return IconLoader.getIcon(path, RestIcons.class);
}
public static final Icon Rst = load("/com/jetbrains/rest/res/rst.png"); // 16x16
}
@@ -240,6 +240,11 @@
<category>Python</category>
</intentionAction>
<intentionAction>
<className>com.jetbrains.python.codeInsight.intentions.PyYieldFromIntention</className>
<category>Python</category>
</intentionAction>
<testFinder implementation="com.jetbrains.python.codeInsight.testIntegration.PyTestFinder"/>
<testCreator language="Python" implementationClass="com.jetbrains.python.codeInsight.testIntegration.PyTestCreator"/>
@@ -1,7 +1,7 @@
package com.jetbrains.pyqt;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.util.IconLoader;
import icons.PythonIcons;
/**
* @author yole
@@ -10,7 +10,7 @@ public class QtTranslationsFileType extends QtFileType implements FileType {
public static QtTranslationsFileType INSTANCE = new QtTranslationsFileType();
protected QtTranslationsFileType() {
super("Qt translations file", "Qt Linguist translations files", "ts", IconLoader.getIcon("/com/jetbrains/pyqt/tsFile.png"));
super("Qt translations file", "Qt Linguist translations files", "ts", PythonIcons.Pyqt.TsFile);
}
protected String getToolName() {
@@ -1,7 +1,7 @@
package com.jetbrains.pyqt;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.util.IconLoader;
import icons.PythonIcons;
/**
* @author yole
@@ -10,7 +10,7 @@ public class QtUIFileType extends QtFileType implements FileType {
public static QtUIFileType INSTANCE = new QtUIFileType();
protected QtUIFileType() {
super("Qt UI file", "Qt UI Designer form files", "ui", IconLoader.getIcon("/com/jetbrains/pyqt/uiForm.png"));
super("Qt UI file", "Qt UI Designer form files", "ui", PythonIcons.Pyqt.UiForm);
}
protected String getToolName() {
@@ -191,6 +191,9 @@ INTN.specify.type.in.annotation=Specify type for reference using annotation
#TypeAssertionIntention
INTN.insert.assertion=Insert type assertion
#PyYieldFromIntention
INTN.yield.from=Transform explicit iteration with 'yield' into 'yield from' expression
# Conflict checker
CONFLICT.name.$0.obscured=Name ''{0}'' obscured by local definitions
CONFLICT.name.$0.obscured.cannot.convert=Name ''{0}'' obscured. Cannot convert.
+4 -4
View File
@@ -1,6 +1,6 @@
package com.jetbrains.python;
import com.intellij.openapi.util.IconLoader;
import icons.PythonIcons;
import org.jetbrains.annotations.NonNls;
import javax.swing.*;
@@ -13,7 +13,7 @@ import javax.swing.*;
public interface PyIcons {
@NonNls String DATA_ROOT = "icons/"; /*"/com/jetbrains/python/PyIcons";*/
Icon PRIVATE = IconLoader.getIcon(DATA_ROOT + "nodes/lock.png");
Icon PREDEFINED = IconLoader.getIcon(DATA_ROOT + "nodes/cyan-dot.png");
Icon INVISIBLE = IconLoader.getIcon(DATA_ROOT + "nodes/red-inv-triangle.png");
Icon PRIVATE = PythonIcons.Python.Icons.Nodes.Lock;
Icon PREDEFINED = PythonIcons.Python.Icons.Nodes.Cyan_dot;
Icon INVISIBLE = PythonIcons.Python.Icons.Nodes.Red_inv_triangle;
}
@@ -2,7 +2,7 @@ package com.jetbrains.python;
import com.intellij.ide.util.projectWizard.ModuleBuilder;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.util.IconLoader;
import icons.PythonIcons;
import org.jetbrains.annotations.NonNls;
import javax.swing.*;
@@ -12,9 +12,9 @@ import javax.swing.*;
*/
public abstract class PythonModuleTypeBase<T extends ModuleBuilder> extends ModuleType<T> {
@NonNls public static final String PYTHON_MODULE = "PYTHON_MODULE";
private final Icon myBigIcon = IconLoader.getIcon("/com/jetbrains/python/icons/python_24.png");
private final Icon myOpenIcon = IconLoader.getIcon("/com/jetbrains/python/icons/pythonOpen.png");
private final Icon myClosedIcon = IconLoader.getIcon("/com/jetbrains/python/icons/pythonClosed.png");
private final Icon myBigIcon = PythonIcons.Python.Icons.Python_24;
private final Icon myOpenIcon = PythonIcons.Python.Icons.PythonOpen;
private final Icon myClosedIcon = PythonIcons.Python.Icons.PythonClosed;
protected PythonModuleTypeBase() {
super(PYTHON_MODULE);
@@ -6,8 +6,8 @@ import com.intellij.facet.FacetTypeId;
import com.intellij.facet.FacetTypeRegistry;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.util.IconLoader;
import com.jetbrains.python.PythonModuleTypeBase;
import icons.PythonIcons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -48,7 +48,7 @@ public class BuildoutFacetType extends FacetType<BuildoutFacet, BuildoutFacetCon
return (BuildoutFacetType)FacetTypeRegistry.getInstance().findFacetType(ID);
}
public final static Icon BUILDOUT_ICON = IconLoader.getIcon("/com/jetbrains/python/icons/buildout/buildout.png");
public final static Icon BUILDOUT_ICON = PythonIcons.Python.Icons.Buildout.Buildout;
@Override
public Icon getIcon() {
@@ -10,15 +10,18 @@ import java.util.Set;
public class PyCodeFragment extends CodeFragment {
private final Set<String> myGlobalWrites;
private final Set<String> myNonlocalWrites;
private final boolean myYieldInside;
public PyCodeFragment(final Set<String> input,
final Set<String> output,
final Set<String> globalWrites,
final Set<String> nonlocalWrites,
final boolean returnInside) {
final boolean returnInside,
final boolean yieldInside) {
super(input, output, returnInside);
myGlobalWrites = globalWrites;
myNonlocalWrites = nonlocalWrites;
myYieldInside = yieldInside;
}
public Set<String> getGlobalWrites() {
@@ -28,4 +31,8 @@ public class PyCodeFragment extends CodeFragment {
public Set<String> getNonlocalWrites() {
return myNonlocalWrites;
}
public boolean isYieldInside() {
return myYieldInside;
}
}
@@ -82,7 +82,13 @@ public class PyCodeFragmentUtil {
}
}
return new PyCodeFragment(inputNames, outputNames, globalWrites, nonlocalWrites, subGraphAnalysis.returns > 0);
final boolean yieldsFound = subGraphAnalysis.yieldExpressions > 0;
if (yieldsFound && LanguageLevel.forElement(owner).isOlderThan(LanguageLevel.PYTHON33)) {
throw new CannotCreateCodeFragmentException("Cannot perform refactoring with 'yield' statement inside code block");
}
return new PyCodeFragment(inputNames, outputNames, globalWrites, nonlocalWrites, subGraphAnalysis.returns > 0, yieldsFound);
}
private static boolean resolvesToBoundMethodParameter(@NotNull PsiElement element) {
@@ -164,13 +170,15 @@ public class PyCodeFragmentUtil {
private final int regularExits;
private final int returns;
private final int outerLoopBreaks;
private final int yieldExpressions;
public AnalysisResult(int starImports, int targetInstructions, int returns, int regularExits, int outerLoopBreaks) {
public AnalysisResult(int starImports, int targetInstructions, int returns, int regularExits, int outerLoopBreaks, int yieldExpressions) {
this.starImports = starImports;
this.targetInstructions = targetInstructions;
this.regularExits = regularExits;
this.returns = returns;
this.outerLoopBreaks = outerLoopBreaks;
this.yieldExpressions = yieldExpressions;
}
}
@@ -181,6 +189,7 @@ public class PyCodeFragmentUtil {
final Set<Instruction> targetInstructions = new HashSet<Instruction>();
int starImports = 0;
int outerLoopBreaks = 0;
int yieldExpressions = 0;
for (Pair<Instruction, Instruction> edge : getOutgoingEdges(subGraph)) {
final Instruction sourceInstruction = edge.getFirst();
@@ -218,9 +227,12 @@ public class PyCodeFragmentUtil {
outerLoopBreaks++;
}
}
if (element instanceof PyYieldExpression) {
yieldExpressions++;
}
}
return new AnalysisResult(starImports, targetInstructions.size(), returnSources, regularSources, outerLoopBreaks);
return new AnalysisResult(starImports, targetInstructions.size(), returnSources, regularSources, outerLoopBreaks, yieldExpressions);
}
@NotNull
@@ -425,6 +425,15 @@ public class PyControlFlowBuilder extends PyRecursiveElementVisitor {
myBuilder.flowAbrupted();
}
@Override
public void visitPyYieldExpression(PyYieldExpression node) {
myBuilder.startNode(node);
final PyExpression expression = node.getExpression();
if (expression != null) {
expression.accept(this);
}
}
@Override
public void visitPyRaiseStatement(final PyRaiseStatement node) {
myBuilder.startNode(node);
@@ -0,0 +1,108 @@
package com.jetbrains.python.codeInsight.intentions;
import com.intellij.codeInsight.intention.impl.BaseIntentionAction;
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.psi.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author vlan
*/
public class PyYieldFromIntention extends BaseIntentionAction {
@NotNull
@Override
public String getFamilyName() {
return PyBundle.message("INTN.yield.from");
}
@NotNull
@Override
public String getText() {
return PyBundle.message("INTN.yield.from");
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
if (LanguageLevel.forElement(file).isAtLeast(LanguageLevel.PYTHON33)) {
final PyForStatement forLoop = findForStatementAtCaret(editor, file);
if (forLoop != null) {
final PyTargetExpression forTarget = findSingleForLoopTarget(forLoop);
final PyReferenceExpression yieldValue = findSingleYieldValue(forLoop);
if (forTarget != null && yieldValue != null) {
final String targetName = forTarget.getName();
if (targetName != null && targetName.equals(yieldValue.getName())) {
return true;
}
}
}
}
return false;
}
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
final PyForStatement forLoop = findForStatementAtCaret(editor, file);
if (forLoop != null) {
final PyExpression source = forLoop.getForPart().getSource();
if (source != null) {
final PyElementGenerator generator = PyElementGenerator.getInstance(project);
final String text = "yield from foo";
final PyExpressionStatement exprStmt = generator.createFromText(LanguageLevel.forElement(file), PyExpressionStatement.class, text);
final PyExpression expr = exprStmt.getExpression();
if (expr instanceof PyYieldExpression) {
final PyExpression yieldValue = ((PyYieldExpression)expr).getExpression();
if (yieldValue != null) {
yieldValue.replace(source);
forLoop.replace(exprStmt);
}
}
}
}
}
@Nullable
private static PyForStatement findForStatementAtCaret(@NotNull Editor editor, @NotNull PsiFile file) {
final PsiElement elementAtCaret = file.findElementAt(editor.getCaretModel().getOffset());
return PsiTreeUtil.getParentOfType(elementAtCaret, PyForStatement.class);
}
@Nullable
private static PyTargetExpression findSingleForLoopTarget(@NotNull PyForStatement forLoop) {
final PyForPart forPart = forLoop.getForPart();
final PyExpression forTarget = forPart.getTarget();
if (forTarget instanceof PyTargetExpression) {
return (PyTargetExpression)forTarget;
}
return null;
}
@Nullable
private static PyReferenceExpression findSingleYieldValue(@NotNull PyForStatement forLoop) {
final PyForPart forPart = forLoop.getForPart();
final PyStatementList stmtList = forPart.getStatementList();
if (stmtList != null && forLoop.getElsePart() == null) {
final PyStatement[] statements = stmtList.getStatements();
if (statements.length == 1) {
final PyStatement firstStmt = statements[0];
if (firstStmt instanceof PyExpressionStatement) {
final PyExpression firstExpr = ((PyExpressionStatement)firstStmt).getExpression();
if (firstExpr instanceof PyYieldExpression) {
final PyYieldExpression yieldExpr = (PyYieldExpression)firstExpr;
final PyExpression yieldValue = yieldExpr.getExpression();
if (yieldValue instanceof PyReferenceExpression) {
return (PyReferenceExpression)yieldValue;
}
}
}
}
}
return null;
}
}
@@ -63,36 +63,33 @@ public class SpecifyTypeInPy3AnnotationsIntention implements IntentionAction {
}
final PyType type = problemElement.getType(TypeEvalContext.slow());
if (type == null || type instanceof PyReturnTypeReference) {
PyFunction pyFunction = PsiTreeUtil.getParentOfType(problemElement, PyFunction.class);
PsiReference reference = problemElement.getReference();
if (problemElement instanceof PyQualifiedExpression) {
final PyExpression qualifier = ((PyQualifiedExpression)problemElement).getQualifier();
if (qualifier != null && !qualifier.getText().equals(PyNames.CANONICAL_SELF)) reference = qualifier.getReference();
}
if (pyFunction != null) {
PyParameter parameter = null;
final PsiElement resolvedReference = reference != null?reference.resolve() : null;
if (problemElement instanceof PyParameter)
parameter = (PyParameter)problemElement;
else if (resolvedReference instanceof PyParameter)
parameter = (PyParameter)resolvedReference;
if (parameter instanceof PyNamedParameter && (((PyNamedParameter)parameter).getAnnotation() != null ||
parameter.getDefaultValue() != null)) return false;
if (parameter != null)
return true;
else {
if (resolvedReference instanceof PyTargetExpression) {
final PyExpression assignedValue = ((PyTargetExpression)resolvedReference).findAssignedValue();
if (assignedValue instanceof PyCallExpression) {
final PyExpression callee = ((PyCallExpression)assignedValue).getCallee();
if (callee != null) {
final PsiReference psiReference = callee.getReference();
if (psiReference != null && psiReference.resolve() == null) return false;
}
final Callable callable = ((PyCallExpression)assignedValue).resolveCalleeFunction(PyResolveContext.defaultContext());
if (callable instanceof PyFunction && ((PyFunction)callable).getAnnotation() == null) return true;
PyParameter parameter = null;
final PsiElement resolvedReference = reference != null?reference.resolve() : null;
if (problemElement instanceof PyParameter)
parameter = (PyParameter)problemElement;
else if (resolvedReference instanceof PyParameter)
parameter = (PyParameter)resolvedReference;
if (parameter instanceof PyNamedParameter && (((PyNamedParameter)parameter).getAnnotation() != null ||
parameter.getDefaultValue() != null)) return false;
if (parameter != null)
return true;
else {
if (resolvedReference instanceof PyTargetExpression) {
final PyExpression assignedValue = ((PyTargetExpression)resolvedReference).findAssignedValue();
if (assignedValue instanceof PyCallExpression) {
final PyExpression callee = ((PyCallExpression)assignedValue).getCallee();
if (callee != null) {
final PsiReference psiReference = callee.getReference();
if (psiReference != null && psiReference.resolve() == null) return false;
}
final Callable callable = ((PyCallExpression)assignedValue).resolveCalleeFunction(PyResolveContext.defaultContext());
if (callable instanceof PyFunction && ((PyFunction)callable).getAnnotation() == null) return true;
}
}
}
@@ -20,7 +20,7 @@ import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.util.IconLoader;
import icons.PythonIcons;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -218,7 +218,7 @@ public class PythonDebugLanguageConsoleView extends JPanel implements ConsoleVie
public ShowDebugConsoleAction(final PythonDebugLanguageConsoleView console) {
super(ExecutionBundle.message("run.configuration.show.command.line.action.name"), null,
IconLoader.getIcon("/com/jetbrains/python/icons/debug/commandLine.png"));
PythonIcons.Python.Icons.Debug.CommandLine);
myConsole = console;
}
@@ -14,7 +14,6 @@ import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
@@ -22,6 +21,7 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.jetbrains.python.buildout.BuildoutFacet;
import com.jetbrains.python.run.PythonCommandLineState;
import com.jetbrains.python.sdk.PythonSdkType;
import icons.PythonIcons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -34,7 +34,7 @@ public class RunPythonConsoleAction extends AnAction implements DumbAware {
public RunPythonConsoleAction() {
super();
getTemplatePresentation().setIcon(IconLoader.getIcon("/com/jetbrains/python/icons/python.png"));
getTemplatePresentation().setIcon(PythonIcons.Python.Icons.Python);
}
@Override
@@ -43,14 +43,14 @@ public class DocStringReferenceProvider extends PsiReferenceProvider {
StructuredDocString docString = StructuredDocString.parse(text);
if (docString != null) {
result.addAll(referencesFromNames(element, offset, docString,
docString.getTagArguments(StructuredDocString.PARAM_TAGS), "parameter"));
docString.getTagArguments(StructuredDocString.PARAM_TAGS), StructuredDocString.PARAMETER));
result.addAll(referencesFromNames(element, offset, docString,
docString.getTagArguments(StructuredDocString.PARAM_TYPE_TAGS), "parameter_type"));
docString.getTagArguments(StructuredDocString.PARAM_TYPE_TAGS), StructuredDocString.PARAMETER_TYPE));
result.addAll(referencesFromNames(element, offset, docString,
docString.getKeywordArgumentSubstrings(), "keyword"));
docString.getKeywordArgumentSubstrings(), StructuredDocString.KEYWORD));
result.addAll(referencesFromNames(element, offset, docString,
docString.getTagArguments(StructuredDocString.VARIABLE_TAGS), "variable"));
docString.getTagArguments(StructuredDocString.VARIABLE_TAGS), StructuredDocString.VARIABLE));
}
return result.toArray(new PsiReference[result.size()]);
}
@@ -69,9 +69,11 @@ public class DocStringReferenceProvider extends PsiReferenceProvider {
if (PyNames.isIdentifier(s)) {
result.add(new DocStringParameterReference(element, name.getTextRange().shiftRight(offset), refType));
}
final Substring type = docString.getParamTypeSubstring(s);
if (type != null) {
result.addAll(parseTypeReferences(element, type, offset));
if (!refType.equals(StructuredDocString.PARAMETER_TYPE)) {
final Substring type = docString.getParamTypeSubstring(s);
if (type != null) {
result.addAll(parseTypeReferences(element, type, offset));
}
}
}
final Substring rtype = docString.getReturnTypeSubstring();
@@ -33,6 +33,11 @@ public abstract class StructuredDocString {
public static String[] RAISES_TAGS = new String[] { "raises", "raise", "except", "exception" };
public static String[] RETURN_TAGS = new String[] { "return", "returns" };
public static String PARAMETER = "parameter";
public static String PARAMETER_TYPE = "parameter_type";
public static String KEYWORD = "keyword";
public static String VARIABLE = "variable";
@Nullable
public static StructuredDocString parse(String text) {
if (text == null) {
@@ -3,6 +3,7 @@ package com.jetbrains.python.editor;
import com.intellij.codeInsight.editorActions.JoinRawLinesHandlerDelegate;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiComment;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
@@ -73,29 +74,52 @@ public class PyJoinLinesHandler implements JoinRawLinesHandlerDelegate {
}
// single string case PY-4375
final PyExpression leftExpression = request.leftExpr();
final PyExpression rightExpression = request.rightExpr();
if (request.leftElem() == request.rightElem()) {
IElementType type = request.leftElem().getNode().getElementType();
if (PyTokenTypes.SINGLE_QUOTED_STRING == type || PyTokenTypes.SINGLE_QUOTED_UNICODE == type) {
PyExpression element = request.leftExpr();
PyExpression element = leftExpression;
if (element == null) return CANNOT_JOIN;
String[] substrings = element.getText().split("\n");
if (substrings.length != 1) {
StringBuilder replacement = new StringBuilder();
for (String string : substrings) {
if (string.trim().endsWith("\\"))
replacement.append(string.substring(0, string.length()-1));
else
replacement.append(string);
}
document.replaceString(element.getTextOffset(), element.getTextOffset()+element.getTextLength(), replacement);
if (removeBackSlash(document, element, false)) {
return element.getTextOffset();
}
}
}
PsiElement expression = null;
if (leftExpression != null && rightExpression != null) {
if (PsiTreeUtil.isAncestor(leftExpression, rightExpression, false))
expression = leftExpression;
else if (PsiTreeUtil.isAncestor(rightExpression, leftExpression, false))
expression = rightExpression;
if (expression != null && !(expression instanceof PyStringLiteralExpression)) {
if (removeBackSlash(document, expression, true)) {
return expression.getTextOffset();
}
}
}
}
return CANNOT_JOIN;
}
private boolean removeBackSlash(Document document, PsiElement element, boolean trim) {
String[] substrings = element.getText().split("\n");
if (substrings.length != 1) {
StringBuilder replacement = new StringBuilder();
for (String string : substrings) {
if (trim)
string = StringUtil.trimLeading(string);
if (string.trim().endsWith("\\"))
replacement.append(string.substring(0, string.length()-1));
else
replacement.append(string);
}
document.replaceString(element.getTextOffset(), element.getTextOffset()+element.getTextLength(), replacement);
return true;
}
return false;
}
// a dumb immutable result holder
private static class Result {
final String myInsert;
@@ -449,6 +449,11 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
if (description == null) {
boolean marked_qualified = false;
if (element instanceof PyQualifiedExpression) {
// TODO: Add __qualname__ for Python 3.3 to the skeleton of <class 'object'>, introduce a pseudo-class skeleton for
// <class 'function'>
if ("__qualname__".equals(ref_text) && LanguageLevel.forElement(element).isAtLeast(LanguageLevel.PYTHON33)) {
return;
}
final PyQualifiedExpression qexpr = (PyQualifiedExpression)element;
if (PyNames.COMPARISON_OPERATORS.contains(qexpr.getReferencedName()) || refname == null) {
return;
@@ -3,7 +3,6 @@ package com.jetbrains.python.psi.impl;
import com.google.common.collect.Maps;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.text.StringUtil;
@@ -30,6 +29,7 @@ import com.jetbrains.python.psi.stubs.PyFunctionStub;
import com.jetbrains.python.psi.stubs.PyTargetExpressionStub;
import com.jetbrains.python.psi.types.*;
import com.jetbrains.python.sdk.PythonSdkType;
import icons.PythonIcons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -44,9 +44,9 @@ import static com.jetbrains.python.psi.impl.PyCallExpressionHelper.interpretAsMo
* Implements PyFunction.
*/
public class PyFunctionImpl extends PyPresentableElementImpl<PyFunctionStub> implements PyFunction {
private static final Icon PROPERTY_GETTER = IconLoader.findIcon("/com/jetbrains/python/icons/propertyGetter.png");
private static final Icon PROPERTY_SETTER = IconLoader.findIcon("/com/jetbrains/python/icons/propertySetter.png");
private static final Icon PROPERTY_DELETER = IconLoader.findIcon("/com/jetbrains/python/icons/propertyDeleter.png");
private static final Icon PROPERTY_GETTER = PythonIcons.Python.Icons.PropertyGetter;
private static final Icon PROPERTY_SETTER = PythonIcons.Python.Icons.PropertySetter;
private static final Icon PROPERTY_DELETER = PythonIcons.Python.Icons.PropertyDeleter;
public PyFunctionImpl(ASTNode astNode) {
super(astNode);
@@ -1,7 +1,6 @@
package com.jetbrains.python.refactoring.extractmethod;
import com.intellij.codeInsight.codeFragment.CannotCreateCodeFragmentException;
import com.intellij.codeInsight.codeFragment.CodeFragment;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.project.Project;
@@ -93,7 +92,7 @@ public class PyExtractMethodHandler implements RefactoringActionHandler {
if (owner == null) {
return;
}
final CodeFragment fragment;
final PyCodeFragment fragment;
try {
fragment = PyCodeFragmentUtil.createCodeFragment(owner, element1, element2);
}
@@ -110,6 +110,9 @@ public class PyExtractMethodUtil {
if (fragment.isReturnInstructionInside()) {
builder.append("return ");
}
if (fragment.isYieldInside()) {
builder.append("yield from ");
}
if (isMethod) {
appendSelf(firstElement, builder, isStaticMethod);
}
@@ -158,6 +161,9 @@ public class PyExtractMethodUtil {
// Generate call element
builder.append(" = ");
if (fragment.isYieldInside()) {
builder.append("yield from ");
}
if (isMethod){
appendSelf(elementsRange.get(0), builder, isStaticMethod);
}
@@ -234,7 +240,7 @@ public class PyExtractMethodUtil {
public static void extractFromExpression(final Project project,
final Editor editor,
final CodeFragment fragment,
final PyCodeFragment fragment,
final PsiElement expression) {
if (!fragment.getOutputVariables().isEmpty()){
CommonRefactoringUtil.showErrorHint(project, editor,
@@ -281,6 +287,9 @@ public class PyExtractMethodUtil {
// Generating call element
final StringBuilder builder = new StringBuilder();
builder.append("return ");
if (fragment.isYieldInside()) {
builder.append("yield from ");
}
if (isMethod){
appendSelf(expression, builder, isStaticMethod);
}
@@ -295,14 +295,14 @@ public class PythonRemoteSdkAdditionalData extends PythonSdkAdditionalData imple
if (element != null) {
data.setHost(element.getAttributeValue(HOST));
data.setPort(Integer.parseInt(element.getAttributeValue(PORT)));
data.setAnonymous(Boolean.parseBoolean(element.getAttributeValue(ANONYMOUS)));
data.setPort(StringUtil.parseInt(element.getAttributeValue(PORT), 22));
data.setAnonymous(StringUtil.parseBoolean(element.getAttributeValue(ANONYMOUS), false));
data.setSerializedUserName(element.getAttributeValue(USERNAME));
data.setSerializedPassword(element.getAttributeValue(PASSWORD));
data.setPrivateKeyFile(StringUtil.nullize(element.getAttributeValue(PRIVATE_KEY_FILE)));
data.setKnownHostsFile(StringUtil.nullize(element.getAttributeValue(KNOWN_HOSTS_FILE)));
data.setSerializedPassphrase(element.getAttributeValue(PASSPHRASE));
data.setUseKeyPair(Boolean.parseBoolean(element.getAttributeValue(USE_KEY_PAIR)));
data.setUseKeyPair(StringUtil.parseBoolean(element.getAttributeValue(USE_KEY_PAIR), false));
data.setInterpreterPath(StringUtil.nullize(element.getAttributeValue(INTERPRETER_PATH)));
data.setPyCharmTempFilesPath(StringUtil.nullize(element.getAttributeValue(PYCHARM_HELPERS_PATH)));
@@ -6,7 +6,7 @@ import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.execution.configurations.RunConfigurationModule;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.IconLoader;
import icons.PythonIcons;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -29,7 +29,7 @@ public class PythonConfigurationType implements ConfigurationType {
return null;
}
private final Icon _icon = IconLoader.getIcon("/com/jetbrains/python/icons/python.png");
private final Icon _icon = PythonIcons.Python.Icons.Python;
private static class PythonConfigurationFactory extends ConfigurationFactory {
protected PythonConfigurationFactory(ConfigurationType configurationType) {
@@ -1,8 +1,8 @@
package com.jetbrains.python.sdk;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.text.StringUtil;
import icons.PythonIcons;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -84,6 +84,6 @@ public class IronPythonSdkFlavor extends PythonSdkFlavor {
@Override
public Icon getIcon() {
return IconLoader.getIcon("/com/jetbrains/python/icons/dotnet.png");
return PythonIcons.Python.Icons.Dotnet;
}
}
@@ -2,10 +2,10 @@ package com.jetbrains.python.sdk;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.configurations.ParamsGroup;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.jetbrains.python.run.PythonCommandLineState;
import icons.PythonIcons;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -66,6 +66,6 @@ public class JythonSdkFlavor extends PythonSdkFlavor {
@Override
public Icon getIcon() {
return IconLoader.getIcon("/com/jetbrains/python/icons/jython.png");
return PythonIcons.Python.Icons.Jython;
}
}
@@ -16,6 +16,7 @@ public class MacPythonSdkFlavor extends CPythonSdkFlavor {
}
public static MacPythonSdkFlavor INSTANCE = new MacPythonSdkFlavor();
private static final String[] POSSIBLE_BINARY_NAMES = {"python", "python2", "python3"};
@Override
public Collection<String> suggestHomePaths() {
@@ -36,10 +37,15 @@ public class MacPythonSdkFlavor extends CPythonSdkFlavor {
final String dir_name = dir.getName().toLowerCase();
if (dir.isDirectory()) {
if ("Current".equals(dir_name) || dir_name.startsWith("2") || dir_name.startsWith("3")) {
VirtualFile bin_dir = dir.findChild("bin");
if (bin_dir != null && bin_dir.isDirectory()) {
VirtualFile python_exe = bin_dir.findChild("python");
if (python_exe != null) candidates.add(python_exe.getPath());
final VirtualFile binDir = dir.findChild("bin");
if (binDir != null && binDir.isDirectory()) {
for (String name : POSSIBLE_BINARY_NAMES) {
final VirtualFile child = binDir.findChild(name);
if (child != null) {
candidates.add(child.getPath());
break;
}
}
}
}
}
@@ -1,10 +1,10 @@
package com.jetbrains.python.sdk;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.jetbrains.python.psi.LanguageLevel;
import icons.PythonIcons;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -77,6 +77,6 @@ public class PyPySdkFlavor extends PythonSdkFlavor {
@Override
public Icon getIcon() {
return IconLoader.getIcon("/com/jetbrains/python/icons/pypy.png");
return PythonIcons.Python.Icons.Pypy;
}
}
@@ -6,12 +6,12 @@ import com.intellij.execution.process.ProcessOutput;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.SdkAdditionalData;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.encoding.EncodingManager;
import com.jetbrains.python.psi.LanguageLevel;
import icons.PythonIcons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -226,6 +226,6 @@ public abstract class PythonSdkFlavor {
}
public Icon getIcon() {
return IconLoader.getIcon("/com/jetbrains/python/icons/python.png");
return PythonIcons.Python.Icons.Python;
}
}
@@ -28,7 +28,6 @@ import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
@@ -46,6 +45,7 @@ import com.jetbrains.python.psi.LanguageLevel;
import com.jetbrains.python.psi.impl.PyBuiltinCache;
import com.jetbrains.python.psi.search.PyProjectScopeBuilder;
import com.jetbrains.python.remote.PythonRemoteSdkAdditionalData;
import icons.PythonIcons;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -84,7 +84,7 @@ public class PythonSdkType extends SdkType {
}
public Icon getIcon() {
return IconLoader.getIcon("/com/jetbrains/python/icons/python.png");
return PythonIcons.Python.Icons.Python;
}
@NotNull
@@ -3,12 +3,12 @@ package com.jetbrains.python.sdk;
import com.intellij.ide.DataManager;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.SystemProperties;
import icons.PythonIcons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -117,6 +117,6 @@ public class VirtualEnvSdkFlavor extends CPythonSdkFlavor {
@Override
public Icon getIcon() {
return IconLoader.getIcon("/com/jetbrains/python/icons/virtualenv.png");
return PythonIcons.Python.Icons.Virtualenv;
}
}
@@ -2,13 +2,13 @@ package com.jetbrains.python.testing;
import com.intellij.execution.configurations.*;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.IconLoader;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.testing.attest.PythonAtTestRunConfiguration;
import com.jetbrains.python.testing.doctest.PythonDocTestRunConfiguration;
import com.jetbrains.python.testing.nosetest.PythonNoseTestRunConfiguration;
import com.jetbrains.python.testing.pytest.PyTestRunConfiguration;
import com.jetbrains.python.testing.unittest.PythonUnitTestRunConfiguration;
import icons.PythonIcons;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -29,7 +29,7 @@ public class PythonTestConfigurationType implements ConfigurationType {
return ConfigurationTypeUtil.findConfigurationType(PythonTestConfigurationType.class);
}
private static final Icon ICON = IconLoader.getIcon("/com/jetbrains/python/icons/pythonTests.png");
private static final Icon ICON = PythonIcons.Python.Icons.PythonTests;
private static class PythonUnitTestConfigurationFactory extends ConfigurationFactory {
protected PythonUnitTestConfigurationFactory(ConfigurationType configurationType) {
@@ -484,6 +484,7 @@ public abstract class CompatibilityVisitor extends PyAnnotator {
if (level.isOlderThan(LanguageLevel.PYTHON33)) {
registerProblem(node, "Python versions < 3.3 do not support this syntax. Delegating to a subgenerator is available since " +
"Python 3.3; use explicit iteration over subgenerator instead.");
break;
}
}
}
@@ -0,0 +1,10 @@
class C:
pass
def f(x):
x.__qualname__ #pass
C.__qualname__ #pass
c = C()
c.__qualname__ #pass
f.__qualname__ #pass
@@ -0,0 +1,4 @@
def f(g):
yield 'begin'
yield from g()
print('end')
@@ -0,0 +1,5 @@
def f(g):
yield 'begin'
for x in g():
yield <caret>x
print('end')
@@ -0,0 +1 @@
really_really_really_really_really_really_really_long_name = percentage_complete.as_integer_ratio()
@@ -0,0 +1,2 @@
really_really_really_really_rea<caret>lly_really_really_long_name = percentage_complete\
.as_integer_ratio()
@@ -0,0 +1,6 @@
def f(xs):
found = False
<selection>for x in xs:
yield x
found = True</selection>
print(found)
@@ -0,0 +1,11 @@
def bar(found_new, xs_new):
for x in xs_new:
yield x
found_new = True
return found_new
def f(xs):
found = False
found = yield from bar(found, xs)
print(found)
@@ -0,0 +1,6 @@
def f(xs):
found = False
<selection>for x in xs:
yield x
found = True</selection>
print(found)
@@ -0,0 +1,7 @@
from datetime import datetime
def foo(p):
"""Foo
:param datetime p: a datetime
<ref>
"""
@@ -261,6 +261,11 @@ public class PyIntentionTest extends PyTestCase {
doDocStubTest();
}
// PY-7383
public void testYieldFrom() {
doTest(PyBundle.message("INTN.yield.from"), LanguageLevel.PYTHON33);
}
private void doDocStubTest() {
CodeInsightSettings codeInsightSettings = CodeInsightSettings.getInstance();
codeInsightSettings.JAVADOC_STUB_ON_ENTER = true;
@@ -65,4 +65,5 @@ public class PyJoinLinesTest extends PyTestCase {
public void testTwoStatements() { doTest(); }
public void testStringWithSlash() { doTest(); }
public void testListOfStrings() { doTest(); }
public void testLongExpression() { doTest(); }
}
@@ -480,4 +480,8 @@ public class PyResolveTest extends PyResolveTestCase {
public void testShadowingTargetExpression() {
assertResolvesTo(PyTargetExpression.class, "lab");
}
public void testReferenceInDocstring() {
assertResolvesTo(PyClass.class, "datetime");
}
}
@@ -27,6 +27,7 @@ import com.jetbrains.python.psi.LanguageLevel;
import com.jetbrains.python.psi.PyFile;
import com.jetbrains.python.psi.impl.PyFileImpl;
import com.jetbrains.python.psi.impl.PythonLanguageLevelPusher;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
@@ -89,6 +90,16 @@ public abstract class PyTestCase extends UsefulTestCase {
PythonLanguageLevelPusher.setForcedLanguageLevel(myFixture.getProject(), languageLevel);
}
protected void runWithLanguageLevel(@NotNull LanguageLevel languageLevel, @NotNull Runnable action) {
setLanguageLevel(languageLevel);
try {
action.run();
}
finally {
setLanguageLevel(null);
}
}
protected static void assertNotParsed(PyFile file) {
assertNull(PARSED_ERROR_MSG, ((PyFileImpl)file).getTreeElement());
}
@@ -1,6 +1,7 @@
package com.jetbrains.python.inspections;
import com.jetbrains.python.fixtures.PyTestCase;
import com.jetbrains.python.psi.LanguageLevel;
import org.jetbrains.annotations.NotNull;
/**
@@ -190,6 +191,16 @@ public class PyUnresolvedReferencesInspectionTest extends PyTestCase {
doTest();
}
// PY-6745
public void testQualNameAttribute() {
runWithLanguageLevel(LanguageLevel.PYTHON33, new Runnable() {
@Override
public void run() {
doTest();
}
});
}
private void doTest() {
myFixture.configureByFile(TEST_DIRECTORY + getTestName(true) + ".py");
myFixture.enableInspections(PyUnresolvedReferencesInspection.class);
@@ -235,4 +235,14 @@ public class PyExtractMethodTest extends LightMarkedTestCase {
public void testNonlocal() {
doTest("baz", LanguageLevel.PYTHON30);
}
// PY-7381
public void testYield() {
doFail("bar", "Cannot perform refactoring with 'yield' statement inside code block");
}
// PY-7382
public void testYield33() {
doTest("bar", LanguageLevel.PYTHON33);
}
}