Introduce inside argument list suggests names based on argument names (PY-1260)

This commit is contained in:
Dmitry Jemerov
2010-07-17 19:46:53 +04:00
parent 60e17645e3
commit 1a445bce8e
9 changed files with 68 additions and 35 deletions
@@ -30,6 +30,7 @@ public interface PyArgumentList extends PyElement {
* Tries to map the argument list to callee's idea of parameters.
* @return a result object with mappings and diagnostic flags.
*/
@NotNull
AnalysisResult analyzeCall();
/**
@@ -221,6 +221,7 @@ public class PyArgumentListImpl extends PyElementImpl implements PyArgumentList
super.deleteChildInternal(node);
}
@NotNull
public AnalysisResult analyzeCall() {
final PyCallExpressionHelper.AnalysisResultImpl ret = new PyCallExpressionHelper.AnalysisResultImpl(this);
PyExpression[] arguments = getArguments();
@@ -9,10 +9,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Created by IntelliJ IDEA.
* User: Alexey.Ivanov
* Date: Aug 24, 2009
* Time: 6:49:13 PM
* @author Alexey.Ivanov
*/
public class NameSuggestorUtil {
private NameSuggestorUtil() {
@@ -18,9 +18,7 @@ import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.IntroduceTargetChooser;
import com.intellij.refactoring.RefactoringActionHandler;
import com.intellij.refactoring.util.CommonRefactoringUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.HashSet;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyPsiUtils;
@@ -31,10 +29,7 @@ import com.jetbrains.python.refactoring.PyRefactoringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.*;
/**
* @author Alexey.Ivanov
@@ -72,28 +67,42 @@ abstract public class IntroduceHandler implements RefactoringActionHandler {
public void invoke(@NotNull Project project, @NotNull PsiElement[] elements, DataContext dataContext) {
}
protected String[] getSuggestedNames(@NotNull final PyExpression expression) {
Collection<String> res = new HashSet<String>();
public Collection<String> getSuggestedNames(@NotNull final PyExpression expression) {
Collection<String> candidates = new HashSet<String>();
String text = expression.getText();
if (text != null) {
for (String name : NameSuggestorUtil.generateNames(text)) {
if (myValidator.checkPossibleName(name, expression)) {
res.add(name);
}
}
candidates.addAll(NameSuggestorUtil.generateNames(text));
}
PyType type = expression.getType(TypeEvalContext.fast());
if (type != null) {
final String typeName = type.getName();
if (typeName != null) {
for (String name : NameSuggestorUtil.generateNamesByType(typeName)) {
if (myValidator.checkPossibleName(name, expression)) {
res.add(name);
}
candidates.addAll(NameSuggestorUtil.generateNamesByType(typeName));
}
}
final PyKeywordArgument kwArg = PsiTreeUtil.getParentOfType(expression, PyKeywordArgument.class);
if (kwArg != null && kwArg.getValueExpression() == expression) {
candidates.add(kwArg.getKeyword());
}
final PyArgumentList argList = PsiTreeUtil.getParentOfType(expression, PyArgumentList.class);
if (argList != null) {
final PyArgumentList.AnalysisResult result = argList.analyzeCall();
if (result.getMarkedCallee() != null && !result.isImplicitlyResolved()) {
final PyNamedParameter namedParameter = result.getPlainMappedParams().get(expression);
if (namedParameter != null) {
candidates.add(namedParameter.getName());
}
}
}
return ArrayUtil.toStringArray(res);
Collection<String> res = new HashSet<String>();
for (String name : candidates) {
if (myValidator.checkPossibleName(name, expression)) {
res.add(name);
}
}
return res;
}
public void performAction(@NotNull final Project project, Editor editor, PsiFile file, String name, boolean replaceAll, boolean hasConstructor, boolean isTestClass) {
@@ -202,7 +211,7 @@ abstract public class IntroduceHandler implements RefactoringActionHandler {
else {
occurrences = Collections.emptyList();
}
String[] possibleNames = getSuggestedNames(expression);
Collection<String> possibleNames = getSuggestedNames(expression);
replaceAll &= occurrences.size() > 0;
InitPlace initInConstructor = InitPlace.SAME_METHOD;
if (name == null) {
@@ -17,6 +17,7 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.event.*;
import java.util.Collection;
/**
* Created by IntelliJ IDEA.
@@ -45,7 +46,7 @@ public class PyIntroduceDialog extends DialogWrapper implements PyIntroduceSetti
@NotNull final String caption,
@NotNull final IntroduceValidator validator,
final int occurrencesCount,
final String[] possibleNames,
final Collection<String> possibleNames,
final String helpId,
boolean hasConstructor,
boolean isTestClass) {
@@ -69,7 +70,7 @@ public class PyIntroduceDialog extends DialogWrapper implements PyIntroduceSetti
return myHelpId;
}
private void setUpNameComboBox(String[] possibleNames) {
private void setUpNameComboBox(Collection<String> possibleNames) {
final EditorComboBoxEditor comboEditor = new StringComboboxEditor(myProject, PythonFileType.INSTANCE, myNameComboBox);
myNameComboBox.setEditor(comboEditor);
@@ -1,7 +1,6 @@
package com.jetbrains.python.refactoring.introduce.constant;
import com.intellij.psi.PsiElement;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.HashSet;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.psi.PyExpression;
@@ -13,10 +12,7 @@ import java.util.Collection;
import java.util.List;
/**
* Created by IntelliJ IDEA.
* User: Alexey.Ivanov
* Date: Aug 25, 2009
* Time: 6:48:16 PM
* @author Alexey.Ivanov
*/
public class ConstantIntroduceHandler extends IntroduceHandler {
public ConstantIntroduceHandler() {
@@ -35,12 +31,12 @@ public class ConstantIntroduceHandler extends IntroduceHandler {
return anchor.addBefore(declaration, ((PyFile)anchor).getStatements().get(0));
}
protected String[] getSuggestedNames(@NotNull final PyExpression expression) {
public Collection<String> getSuggestedNames(@NotNull final PyExpression expression) {
Collection<String> names = new HashSet<String>();
for (String name : super.getSuggestedNames(expression)) {
names.add(name.toUpperCase());
}
return ArrayUtil.toStringArray(names);
return names;
}
@Override
@@ -0,0 +1,4 @@
def foo(extra_context):
pass
foo(<caret>{'a': 1})
@@ -0,0 +1,4 @@
def foo(**kwargs):
pass
foo(extra_context=<caret>{'a': 1})
@@ -1,8 +1,12 @@
package com.jetbrains.python.refactoring;
import com.intellij.psi.util.PsiTreeUtil;
import com.jetbrains.python.fixtures.PyLightFixtureTestCase;
import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.refactoring.introduce.variable.VariableIntroduceHandler;
import java.util.Collection;
/**
* @author yole
*/
@@ -12,15 +16,31 @@ public class PyIntroduceVariableTest extends PyLightFixtureTestCase {
return super.getTestDataPath() + "/refactoring/introduceVariable";
}
public void testSimple() throws Exception {
public void testSimple() {
doTest();
}
public void testPy995() throws Exception {
public void testPy995() {
doTest();
}
private void doTest() throws Exception {
public void testSuggestKeywordArgumentName() { // PY-1260
myFixture.configureByFile(getTestName(true) + ".py");
VariableIntroduceHandler handler = new VariableIntroduceHandler();
PyExpression expr = PsiTreeUtil.getParentOfType(myFixture.getFile().findElementAt(myFixture.getEditor().getCaretModel().getOffset()), PyExpression.class);
final Collection<String> names = handler.getSuggestedNames(expr);
assertTrue(names.contains("extra_context"));
}
public void testSuggestArgumentName() { // PY-1260
myFixture.configureByFile(getTestName(true) + ".py");
VariableIntroduceHandler handler = new VariableIntroduceHandler();
PyExpression expr = PsiTreeUtil.getParentOfType(myFixture.getFile().findElementAt(myFixture.getEditor().getCaretModel().getOffset()), PyExpression.class);
final Collection<String> names = handler.getSuggestedNames(expr);
assertTrue(names.contains("extra_context"));
}
private void doTest() {
myFixture.configureByFile(getTestName(true) + ".py");
VariableIntroduceHandler handler = new VariableIntroduceHandler();
handler.performAction(myFixture.getProject(), myFixture.getEditor(), myFixture.getFile(), "a", true, false, false);