mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
+3
-1
@@ -18,6 +18,7 @@ package com.jetbrains.python.templateLanguages;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@@ -34,7 +35,8 @@ public interface TemplateContextProvider {
|
||||
* name of the variable; the object is the PsiElement declaring the variable.
|
||||
*
|
||||
* @param template the template file
|
||||
* @return the list of variables
|
||||
* @return the list of variables, or null if the template is not used in the context handled by this processor.
|
||||
*/
|
||||
@Nullable
|
||||
Collection<LookupElement> getTemplateContext(PsiFile template);
|
||||
}
|
||||
|
||||
@@ -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"/>
|
||||
|
||||
|
||||
@@ -193,6 +193,9 @@ INTN.specify.returt.type.in.annotation=Specify return type 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.
|
||||
|
||||
@@ -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
|
||||
|
||||
+4
-9
@@ -216,7 +216,7 @@ public class PyKeywordCompletionContributor extends CompletionContributor {
|
||||
psiElement().inside(PyStringLiteralExpression.class);
|
||||
|
||||
private static final PsiElementPattern.Capture<PsiElement> IN_FUNCTION_HEADER =
|
||||
psiElement().inside(PyFunction.class).andNot(psiElement().inside(PyStatementList.class));
|
||||
psiElement().inside(PyFunction.class).andNot(psiElement().inside(false, psiElement(PyStatementList.class), psiElement(PyFunction.class)));
|
||||
|
||||
public static final PsiElementPattern.Capture<PsiElement> AFTER_QUALIFIER =
|
||||
psiElement().afterLeaf(psiElement().withText(".").inside(PyReferenceExpression.class));
|
||||
@@ -289,13 +289,8 @@ public class PyKeywordCompletionContributor extends CompletionContributor {
|
||||
private static final PsiElementPattern.Capture<PsiElement> AFTER_IF = afterStatement(psiElement(PyIfStatement.class));
|
||||
private static final PsiElementPattern.Capture<PsiElement> AFTER_TRY = afterStatement(psiElement(PyTryExceptStatement.class));
|
||||
|
||||
/*
|
||||
private static final FilterPattern AFTER_LOOP_NO_ELSE = new FilterPattern(new PrecededByFilter(
|
||||
psiElement()
|
||||
.withChild(StandardPatterns.or(psiElement(PyWhileStatement.class), psiElement(PyForStatement.class)))
|
||||
.withLastChild(StandardPatterns.not(psiElement(PyElsePart.class)))
|
||||
));
|
||||
*/
|
||||
private static final PsiElementPattern.Capture<PsiElement> AFTER_LOOP_NO_ELSE =
|
||||
afterStatement(psiElement(PyLoopStatement.class).withLastChild(StandardPatterns.not(psiElement(PyElsePart.class))));
|
||||
|
||||
private static final PsiElementPattern.Capture<PsiElement> AFTER_COND_STMT_NO_ELSE =
|
||||
afterStatement(psiElement().withChild(psiElement(PyConditionalStatementPart.class))
|
||||
@@ -485,7 +480,7 @@ public class PyKeywordCompletionContributor extends CompletionContributor {
|
||||
CompletionType.BASIC, psiElement()
|
||||
.withLanguage(PythonLanguage.getInstance())
|
||||
.and(FIRST_ON_LINE)
|
||||
.andOr(IN_COND_STMT, IN_TRY_BODY, IN_EXCEPT_BODY, AFTER_COND_STMT_NO_ELSE, AFTER_TRY_NO_ELSE)
|
||||
.andOr(IN_COND_STMT, IN_TRY_BODY, IN_EXCEPT_BODY, AFTER_COND_STMT_NO_ELSE, AFTER_LOOP_NO_ELSE, AFTER_TRY_NO_ELSE)
|
||||
//.andNot(RIGHT_AFTER_COLON)
|
||||
.andNot(AFTER_QUALIFIER).andNot(IN_STRING_LITERAL)
|
||||
,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -183,7 +183,7 @@ public class PyOverrideImplementUtil {
|
||||
statementBody.append(PyNames.PASS);
|
||||
}
|
||||
else {
|
||||
if (baseFunction.getReturnType(TypeEvalContext.slow(), null) != PyNoneType.INSTANCE) {
|
||||
if (!PyNames.INIT.equals(baseFunction.getName()) && baseFunction.getReturnType(TypeEvalContext.slow(), null) != PyNoneType.INSTANCE) {
|
||||
statementBody.append("return ");
|
||||
}
|
||||
if (baseClass.isNewStyleClass()) {
|
||||
|
||||
@@ -32,7 +32,7 @@ public class PyClassFindUsagesHandler extends FindUsagesHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSearchForTextOccurencesAvailable(PsiElement psiElement, boolean isSingleFile) {
|
||||
protected boolean isSearchForTextOccurencesAvailable(@NotNull PsiElement psiElement, boolean isSingleFile) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ public class PyFunctionFindUsagesHandler extends FindUsagesHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSearchForTextOccurencesAvailable(PsiElement psiElement, boolean isSingleFile) {
|
||||
protected boolean isSearchForTextOccurencesAvailable(@NotNull PsiElement psiElement, boolean isSingleFile) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,11 +6,20 @@ import com.intellij.find.findUsages.FindUsagesHandler;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFileSystemItem;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.ui.SimpleColoredComponent;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.psi.PyFile;
|
||||
import com.jetbrains.python.psi.PyUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
@@ -40,10 +49,21 @@ public class PyModuleFindUsagesHandler extends FindUsagesHandler {
|
||||
isSingleFile,
|
||||
this) {
|
||||
@Override
|
||||
public void configureLabelComponent(final SimpleColoredComponent coloredComponent) {
|
||||
public void configureLabelComponent(@NotNull final SimpleColoredComponent coloredComponent) {
|
||||
coloredComponent.append(myElement instanceof PsiDirectory ? "Package " : "Module ");
|
||||
coloredComponent.append(myElement.getName(), SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<PsiReference> findReferencesToHighlight(PsiElement target, SearchScope searchScope) {
|
||||
if (target instanceof PyFile && PyNames.INIT_DOT_PY.equals(((PyFile)target).getName())) {
|
||||
List<PsiReference> result = new ArrayList<PsiReference>();
|
||||
result.addAll(super.findReferencesToHighlight(target, searchScope));
|
||||
result.addAll(ReferencesSearch.search(PyUtil.turnInitIntoDir(target), searchScope, false).findAll());
|
||||
return result;
|
||||
}
|
||||
return super.findReferencesToHighlight(target, searchScope);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -549,11 +549,19 @@ public class PyBlock implements ASTBlock {
|
||||
}
|
||||
|
||||
ASTNode lastChild = getLastNonSpaceChild(_node, false);
|
||||
if (lastChild != null && lastChild.getElementType() == PyElementTypes.STATEMENT_LIST) {
|
||||
// only multiline statement lists are considered incomplete
|
||||
ASTNode statementListPrev = lastChild.getTreePrev();
|
||||
if (statementListPrev != null && statementListPrev.getText().indexOf('\n') >= 0) {
|
||||
return true;
|
||||
if (lastChild != null) {
|
||||
if (lastChild.getElementType() == PyElementTypes.STATEMENT_LIST) {
|
||||
// only multiline statement lists are considered incomplete
|
||||
ASTNode statementListPrev = lastChild.getTreePrev();
|
||||
if (statementListPrev != null && statementListPrev.getText().indexOf('\n') >= 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (lastChild.getElementType() == PyElementTypes.BINARY_EXPRESSION) {
|
||||
PyBinaryExpression binaryExpression = (PyBinaryExpression) lastChild.getPsi();
|
||||
if (binaryExpression.getRightExpression() == null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -77,6 +77,7 @@ public class PythonFormattingModelBuilder implements FormattingModelBuilderEx, C
|
||||
.before(COLON).spaceIf(pySettings.SPACE_BEFORE_PY_COLON)
|
||||
.after(COMMA).spaceIf(commonSettings.SPACE_AFTER_COMMA)
|
||||
.before(COMMA).spaceIf(commonSettings.SPACE_BEFORE_COMMA)
|
||||
.between(FROM_KEYWORD, DOT).spaces(1)
|
||||
.around(DOT).spaces(0)
|
||||
.before(SEMICOLON).spaceIf(commonSettings.SPACE_BEFORE_SEMICOLON)
|
||||
.withinPairInside(LPAR, RPAR, ARGUMENT_LIST).spaceIf(commonSettings.SPACE_WITHIN_METHOD_CALL_PARENTHESES)
|
||||
|
||||
@@ -5,6 +5,8 @@ import com.intellij.psi.PsiElementResolveResult;
|
||||
import com.intellij.psi.ResolveResult;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.jetbrains.python.psi.PyClass;
|
||||
import com.jetbrains.python.psi.PyFunction;
|
||||
import com.jetbrains.python.psi.PyImportElement;
|
||||
import com.jetbrains.python.psi.PyQualifiedExpression;
|
||||
import com.jetbrains.python.psi.resolve.PyResolveContext;
|
||||
@@ -22,15 +24,16 @@ public class PyTargetReference extends PyReferenceImpl {
|
||||
@Override
|
||||
public ResolveResult[] multiResolve(boolean incompleteCode) {
|
||||
final ResolveResult[] results = super.multiResolve(incompleteCode);
|
||||
boolean resolvedToAnotherFile = false;
|
||||
boolean shadowed = false;
|
||||
for (ResolveResult result : results) {
|
||||
final PsiElement element = result.getElement();
|
||||
if (element != null && element.getContainingFile() != myElement.getContainingFile()) {
|
||||
resolvedToAnotherFile = true;
|
||||
if (element != null && (element.getContainingFile() != myElement.getContainingFile() ||
|
||||
element instanceof PyFunction || element instanceof PyClass)) {
|
||||
shadowed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (results.length > 0 && !resolvedToAnotherFile) {
|
||||
if (results.length > 0 && !shadowed) {
|
||||
return results;
|
||||
}
|
||||
// resolve to self if no other target found
|
||||
|
||||
+1
-2
@@ -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)));
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.jetbrains.python.sdk.CreateVirtualEnvDialog">
|
||||
<grid id="cbd77" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="6" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<grid id="cbd77" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="7" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<xy x="48" y="54" width="550" height="342"/>
|
||||
@@ -16,7 +16,7 @@
|
||||
</component>
|
||||
<vspacer id="b277d">
|
||||
<constraints>
|
||||
<grid row="5" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
<grid row="6" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</vspacer>
|
||||
<component id="48fd" class="com.intellij.ui.components.JBLabel">
|
||||
@@ -58,13 +58,13 @@
|
||||
<text value="&Location:"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="41e08" class="com.intellij.ui.components.JBCheckBox" binding="myAssociateCheckbox">
|
||||
<component id="41e08" class="com.intellij.ui.components.JBCheckBox" binding="myMakeAvailableToAllProjectsCheckbox">
|
||||
<constraints>
|
||||
<grid row="4" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
<grid row="5" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<selected value="true"/>
|
||||
<text value="&Associate this virtual environment with current project"/>
|
||||
<selected value="false"/>
|
||||
<text value="Make available to &all projects"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="9835d" class="com.intellij.ui.components.JBCheckBox" binding="mySitePackagesCheckBox">
|
||||
@@ -75,6 +75,15 @@
|
||||
<text value="&Inherit global site-packages"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="fd5f3" class="com.intellij.ui.components.JBCheckBox" binding="mySetAsProjectInterpreterCheckbox" default-binding="true">
|
||||
<constraints>
|
||||
<grid row="4" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<selected value="true"/>
|
||||
<text value="&Set as project interpreter for this project"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
</form>
|
||||
|
||||
@@ -34,7 +34,8 @@ public class CreateVirtualEnvDialog extends IdeaDialog {
|
||||
private TextFieldWithBrowseButton myDestination;
|
||||
private JTextField myName;
|
||||
private JBCheckBox mySitePackagesCheckBox;
|
||||
private JBCheckBox myAssociateCheckbox;
|
||||
private JBCheckBox myMakeAvailableToAllProjectsCheckbox;
|
||||
private JBCheckBox mySetAsProjectInterpreterCheckbox;
|
||||
private Project myProject;
|
||||
private String myInitialPath;
|
||||
|
||||
@@ -45,13 +46,13 @@ public class CreateVirtualEnvDialog extends IdeaDialog {
|
||||
setTitle("Create Virtual Environment");
|
||||
updateSdkList(sdk, allSdks);
|
||||
|
||||
myAssociateCheckbox.setBorder(BorderFactory.createEmptyBorder(8, 0, 0, 0));
|
||||
myMakeAvailableToAllProjectsCheckbox.setBorder(BorderFactory.createEmptyBorder(8, 0, 0, 0));
|
||||
if (project.isDefault()) {
|
||||
myAssociateCheckbox.setSelected(false);
|
||||
myAssociateCheckbox.setVisible(false);
|
||||
myMakeAvailableToAllProjectsCheckbox.setSelected(true);
|
||||
myMakeAvailableToAllProjectsCheckbox.setVisible(false);
|
||||
}
|
||||
else if (isNewProject) {
|
||||
myAssociateCheckbox.setText("Associate this virtual environment with the project being created");
|
||||
mySetAsProjectInterpreterCheckbox.setText("Set as project interpreter for the project being created");
|
||||
}
|
||||
|
||||
setOKActionEnabled(false);
|
||||
@@ -206,7 +207,11 @@ public class CreateVirtualEnvDialog extends IdeaDialog {
|
||||
}
|
||||
|
||||
public boolean associateWithProject() {
|
||||
return myAssociateCheckbox.isSelected();
|
||||
return !myMakeAvailableToAllProjectsCheckbox.isSelected();
|
||||
}
|
||||
|
||||
public boolean setAsProjectInterpreter() {
|
||||
return mySetAsProjectInterpreterCheckbox.isSelected();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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 @@
|
||||
from..foo import foo2
|
||||
@@ -0,0 +1 @@
|
||||
from ..foo import foo2
|
||||
@@ -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,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,4 @@
|
||||
def lab(): pass
|
||||
lab = 1
|
||||
# <ref>
|
||||
print(lab)
|
||||
@@ -171,6 +171,10 @@ public class PyFormatterTest extends PyTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testFromImportRelative() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testPsiFormatting() { // IDEA-69724
|
||||
String initial =
|
||||
"def method_name(\n" +
|
||||
|
||||
@@ -313,6 +313,14 @@ public class PyIndentTest extends PyTestCase {
|
||||
"<caret>");
|
||||
}
|
||||
|
||||
public void testIndentOnBackslash() { // PY-7360
|
||||
doTest("def index():\n" +
|
||||
" return 'some string' + \\<caret>",
|
||||
"def index():\n" +
|
||||
" return 'some string' + \\\n" +
|
||||
" <caret>");
|
||||
}
|
||||
|
||||
/*
|
||||
TODO: formatter core problem?
|
||||
public void testAlignListBeforeEquals() throws Exception {
|
||||
|
||||
@@ -269,6 +269,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;
|
||||
|
||||
@@ -477,6 +477,10 @@ public class PyResolveTest extends PyResolveTestCase {
|
||||
assertResolvesTo(PyClass.class, "timedelta");
|
||||
}
|
||||
|
||||
public void testShadowingTargetExpression() {
|
||||
assertResolvesTo(PyTargetExpression.class, "lab");
|
||||
}
|
||||
|
||||
public void testReferenceInDocstring() {
|
||||
assertResolvesTo(PyClass.class, "datetime");
|
||||
}
|
||||
|
||||
@@ -606,4 +606,10 @@ public class PythonCompletionTest extends PyTestCase {
|
||||
" pass\n" +
|
||||
"except IOError <caret>").contains("as"));
|
||||
}
|
||||
|
||||
public void testElseInFor() { // PY-6755
|
||||
assertTrue(doTestByText("for item in range(10):\n" +
|
||||
" pass\n" +
|
||||
"el<caret>").contains("else"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user