summaryrefslogtreecommitdiff
path: root/python/src/com/jetbrains/python/codeInsight
diff options
context:
space:
mode:
Diffstat (limited to 'python/src/com/jetbrains/python/codeInsight')
-rw-r--r--python/src/com/jetbrains/python/codeInsight/PyTypingTypeProvider.java375
-rw-r--r--python/src/com/jetbrains/python/codeInsight/highlighting/PyHighlightExitPointsHandlerFactory.java24
-rw-r--r--python/src/com/jetbrains/python/codeInsight/intentions/ImportToImportFromIntention.java122
-rw-r--r--python/src/com/jetbrains/python/codeInsight/intentions/PyGenerateDocstringIntention.java1
-rw-r--r--python/src/com/jetbrains/python/codeInsight/override/PyOverrideImplementUtil.java8
5 files changed, 458 insertions, 72 deletions
diff --git a/python/src/com/jetbrains/python/codeInsight/PyTypingTypeProvider.java b/python/src/com/jetbrains/python/codeInsight/PyTypingTypeProvider.java
new file mode 100644
index 000000000000..f03befac6c14
--- /dev/null
+++ b/python/src/com/jetbrains/python/codeInsight/PyTypingTypeProvider.java
@@ -0,0 +1,375 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.jetbrains.python.codeInsight;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiPolyVariantReference;
+import com.intellij.psi.util.QualifiedName;
+import com.jetbrains.python.PyNames;
+import com.jetbrains.python.psi.*;
+import com.jetbrains.python.psi.impl.PyExpressionCodeFragmentImpl;
+import com.jetbrains.python.psi.impl.PyPsiUtils;
+import com.jetbrains.python.psi.resolve.PyResolveContext;
+import com.jetbrains.python.psi.types.*;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author vlan
+ */
+public class PyTypingTypeProvider extends PyTypeProviderBase {
+ private static ImmutableMap<String, String> BUILTIN_COLLECTIONS = ImmutableMap.<String, String>builder()
+ .put("typing.List", "list")
+ .put("typing.Dict", "dict")
+ .put("typing.Set", PyNames.SET)
+ .put("typing.Tuple", PyNames.TUPLE)
+ .build();
+
+ private static ImmutableSet<String> GENERIC_CLASSES = ImmutableSet.<String>builder()
+ .add("typing.Generic")
+ .add("typing.AbstractGeneric")
+ .add("typing.Protocol")
+ .build();
+
+ public PyType getParameterType(@NotNull PyNamedParameter param, @NotNull PyFunction func, @NotNull TypeEvalContext context) {
+ final PyAnnotation annotation = param.getAnnotation();
+ if (annotation != null) {
+ // XXX: Requires switching from stub to AST
+ final PyExpression value = annotation.getValue();
+ if (value != null) {
+ return getTypingType(value, context);
+ }
+ }
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public PyType getReturnType(@NotNull Callable callable, @NotNull TypeEvalContext context) {
+ if (callable instanceof PyFunction) {
+ final PyFunction function = (PyFunction)callable;
+ final PyAnnotation annotation = function.getAnnotation();
+ if (annotation != null) {
+ // XXX: Requires switching from stub to AST
+ final PyExpression value = annotation.getValue();
+ if (value != null) {
+ return getTypingType(value, context);
+ }
+ }
+ final PyType constructorType = getGenericConstructorType(function, context);
+ if (constructorType != null) {
+ return constructorType;
+ }
+ }
+ return null;
+ }
+
+ @Nullable
+ private static PyType getGenericConstructorType(@NotNull PyFunction function, @NotNull TypeEvalContext context) {
+ if (PyUtil.isInit(function)) {
+ final PyClass cls = function.getContainingClass();
+ if (cls != null) {
+ final List<PyGenericType> genericTypes = collectGenericTypes(cls, context);
+
+ final PyType elementType;
+ if (genericTypes.size() == 1) {
+ elementType = genericTypes.get(0);
+ }
+ else if (genericTypes.size() > 1) {
+ elementType = PyTupleType.create(cls, genericTypes.toArray(new PyType[genericTypes.size()]));
+ }
+ else {
+ elementType = null;
+ }
+
+ if (elementType != null) {
+ return new PyCollectionTypeImpl(cls, false, elementType);
+ }
+ }
+ }
+ return null;
+ }
+
+ @NotNull
+ private static List<PyGenericType> collectGenericTypes(@NotNull PyClass cls, @NotNull TypeEvalContext context) {
+ boolean isGeneric = false;
+ for (PyClass ancestor : cls.getAncestorClasses(context)) {
+ if (GENERIC_CLASSES.contains(ancestor.getQualifiedName())) {
+ isGeneric = true;
+ break;
+ }
+ }
+ if (isGeneric) {
+ final ArrayList<PyGenericType> results = new ArrayList<PyGenericType>();
+ // XXX: Requires switching from stub to AST
+ for (PyExpression expr : cls.getSuperClassExpressions()) {
+ if (expr instanceof PySubscriptionExpression) {
+ final PyExpression indexExpr = ((PySubscriptionExpression)expr).getIndexExpression();
+ if (indexExpr != null) {
+ final PyGenericType genericType = getGenericType(indexExpr, context);
+ if (genericType != null) {
+ results.add(genericType);
+ }
+ }
+ }
+ }
+ return results;
+ }
+ return Collections.emptyList();
+ }
+
+ @Nullable
+ private static PyType getTypingType(@NotNull PyExpression expression, @NotNull TypeEvalContext context) {
+ final PyType unionType = getUnionType(expression, context);
+ if (unionType != null) {
+ return unionType;
+ }
+ final PyType parameterizedType = getParameterizedType(expression, context);
+ if (parameterizedType != null) {
+ return parameterizedType;
+ }
+ final PyType builtinCollection = getBuiltinCollection(expression, context);
+ if (builtinCollection != null) {
+ return builtinCollection;
+ }
+ final PyType genericType = getGenericType(expression, context);
+ if (genericType != null) {
+ return genericType;
+ }
+ final PyType functionType = getFunctionType(expression, context);
+ if (functionType != null) {
+ return functionType;
+ }
+ final PyType stringBasedType = getStringBasedType(expression, context);
+ if (stringBasedType != null) {
+ return stringBasedType;
+ }
+ return null;
+ }
+
+ @Nullable
+ private static PyType getStringBasedType(@NotNull PyExpression expression, @NotNull TypeEvalContext context) {
+ if (expression instanceof PyStringLiteralExpression) {
+ // XXX: Requires switching from stub to AST
+ final String contents = ((PyStringLiteralExpression)expression).getStringValue();
+ final Project project = expression.getProject();
+ final PyExpressionCodeFragmentImpl codeFragment = new PyExpressionCodeFragmentImpl(project, "dummy.py", contents, false);
+ codeFragment.setContext(expression.getContainingFile());
+ final PsiElement element = codeFragment.getFirstChild();
+ if (element instanceof PyExpressionStatement) {
+ final PyExpression dummyExpr = ((PyExpressionStatement)element).getExpression();
+ return getType(dummyExpr, context);
+ }
+ }
+ return null;
+ }
+
+ @Nullable
+ private static PyType getFunctionType(@NotNull PyExpression expression, @NotNull TypeEvalContext context) {
+ if (expression instanceof PySubscriptionExpression) {
+ final PySubscriptionExpression subscriptionExpr = (PySubscriptionExpression)expression;
+ final PyExpression operand = subscriptionExpr.getOperand();
+ final String operandName = resolveToQualifiedName(operand, context);
+ if ("typing.Function".equals(operandName)) {
+ final PyExpression indexExpr = subscriptionExpr.getIndexExpression();
+ if (indexExpr instanceof PyTupleExpression) {
+ final PyTupleExpression tupleExpr = (PyTupleExpression)indexExpr;
+ final PyExpression[] elements = tupleExpr.getElements();
+ if (elements.length == 2) {
+ final PyExpression parametersExpr = elements[0];
+ if (parametersExpr instanceof PyListLiteralExpression) {
+ final List<PyCallableParameter> parameters = new ArrayList<PyCallableParameter>();
+ final PyListLiteralExpression listExpr = (PyListLiteralExpression)parametersExpr;
+ for (PyExpression argExpr : listExpr.getElements()) {
+ parameters.add(new PyCallableParameterImpl(null, getType(argExpr, context)));
+ }
+ final PyExpression returnTypeExpr = elements[1];
+ final PyType returnType = getType(returnTypeExpr, context);
+ return new PyCallableTypeImpl(parameters, returnType);
+ }
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ @Nullable
+ private static PyType getUnionType(@NotNull PyExpression expression, @NotNull TypeEvalContext context) {
+ if (expression instanceof PySubscriptionExpression) {
+ final PySubscriptionExpression subscriptionExpr = (PySubscriptionExpression)expression;
+ final PyExpression operand = subscriptionExpr.getOperand();
+ final String operandName = resolveToQualifiedName(operand, context);
+ if ("typing.Union".equals(operandName)) {
+ return PyUnionType.union(getIndexTypes(subscriptionExpr, context));
+ }
+ }
+ return null;
+ }
+
+ @Nullable
+ private static PyGenericType getGenericType(@NotNull PyExpression expression, @NotNull TypeEvalContext context) {
+ final PsiElement resolved = resolve(expression, context);
+ if (resolved instanceof PyTargetExpression) {
+ final PyTargetExpression targetExpr = (PyTargetExpression)resolved;
+ final QualifiedName calleeName = targetExpr.getCalleeName();
+ if (calleeName != null && "typevar".equals(calleeName.toString())) {
+ // XXX: Requires switching from stub to AST
+ final PyExpression assigned = targetExpr.findAssignedValue();
+ if (assigned instanceof PyCallExpression) {
+ final PyCallExpression assignedCall = (PyCallExpression)assigned;
+ final PyExpression callee = assignedCall.getCallee();
+ if (callee != null) {
+ final String calleeQName = resolveToQualifiedName(callee, context);
+ if ("typing.typevar".equals(calleeQName)) {
+ final PyExpression[] arguments = assignedCall.getArguments();
+ if (arguments.length > 0) {
+ final PyExpression firstArgument = arguments[0];
+ if (firstArgument instanceof PyStringLiteralExpression) {
+ final String name = ((PyStringLiteralExpression)firstArgument).getStringValue();
+ if (name != null) {
+ return new PyGenericType(name, getGenericTypeBound(arguments, context));
+ }
+ }
+ }
+ }
+
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ @Nullable
+ private static PyType getGenericTypeBound(@NotNull PyExpression[] typeVarArguments, @NotNull TypeEvalContext context) {
+ final List<PyType> types = new ArrayList<PyType>();
+ if (typeVarArguments.length > 1) {
+ final PyExpression secondArgument = typeVarArguments[1];
+ if (secondArgument instanceof PyKeywordArgument) {
+ final PyKeywordArgument valuesArgument = (PyKeywordArgument)secondArgument;
+ final PyExpression valueExpr = PyPsiUtils.flattenParens(valuesArgument.getValueExpression());
+ if (valueExpr instanceof PyTupleExpression) {
+ final PyTupleExpression tupleExpr = (PyTupleExpression)valueExpr;
+ for (PyExpression expr : tupleExpr.getElements()) {
+ types.add(getType(expr, context));
+ }
+ }
+ }
+ }
+ return PyUnionType.union(types);
+ }
+
+ @NotNull
+ private static List<PyType> getIndexTypes(@NotNull PySubscriptionExpression expression, @NotNull TypeEvalContext context) {
+ final List<PyType> types = new ArrayList<PyType>();
+ final PyExpression indexExpr = expression.getIndexExpression();
+ if (indexExpr instanceof PyTupleExpression) {
+ final PyTupleExpression tupleExpr = (PyTupleExpression)indexExpr;
+ for (PyExpression expr : tupleExpr.getElements()) {
+ types.add(getType(expr, context));
+ }
+ }
+ return types;
+ }
+
+ @Nullable
+ private static PyType getParameterizedType(@NotNull PyExpression expression, @NotNull TypeEvalContext context) {
+ if (expression instanceof PySubscriptionExpression) {
+ final PySubscriptionExpression subscriptionExpr = (PySubscriptionExpression)expression;
+ final PyExpression operand = subscriptionExpr.getOperand();
+ final PyExpression indexExpr = subscriptionExpr.getIndexExpression();
+ final PyType operandType = getType(operand, context);
+ if (operandType instanceof PyClassType) {
+ final PyClass cls = ((PyClassType)operandType).getPyClass();
+ if (PyNames.TUPLE.equals(cls.getQualifiedName())) {
+ final List<PyType> indexTypes = getIndexTypes(subscriptionExpr, context);
+ return PyTupleType.create(expression, indexTypes.toArray(new PyType[indexTypes.size()]));
+ }
+ else if (indexExpr != null) {
+ final PyType indexType = context.getType(indexExpr);
+ return new PyCollectionTypeImpl(cls, false, indexType);
+ }
+ }
+ }
+ return null;
+ }
+
+ @Nullable
+ private static PyType getBuiltinCollection(@NotNull PyExpression expression, @NotNull TypeEvalContext context) {
+ final String collectionName = resolveToQualifiedName(expression, context);
+ final String builtinName = BUILTIN_COLLECTIONS.get(collectionName);
+ return builtinName != null ? PyTypeParser.getTypeByName(expression, builtinName) : null;
+ }
+
+ @Nullable
+ private static PyType getType(@NotNull PyExpression expression, @NotNull TypeEvalContext context) {
+ // It is possible to replace PyAnnotation.getType() with this implementation
+ final PyType typingType = getTypingType(expression, context);
+ if (typingType != null) {
+ return typingType;
+ }
+ final PyType type = context.getType(expression);
+ if (type instanceof PyClassLikeType) {
+ final PyClassLikeType classType = (PyClassLikeType)type;
+ if (classType.isDefinition()) {
+ return classType.toInstance();
+ }
+ }
+ else if (type instanceof PyNoneType) {
+ return type;
+ }
+ return null;
+ }
+
+ @Nullable
+ private static PsiElement resolve(@NotNull PyExpression expression, @NotNull TypeEvalContext context) {
+ if (expression instanceof PyReferenceOwner) {
+ final PyReferenceOwner referenceOwner = (PyReferenceOwner)expression;
+ final PyResolveContext resolveContext = PyResolveContext.noImplicits().withTypeEvalContext(context);
+ final PsiPolyVariantReference reference = referenceOwner.getReference(resolveContext);
+ final PsiElement element = reference.resolve();
+ if (element instanceof PyFunction) {
+ final PyFunction function = (PyFunction)element;
+ if (PyUtil.isInit(function)) {
+ final PyClass cls = function.getContainingClass();
+ if (cls != null) {
+ return cls;
+ }
+ }
+ }
+ return element;
+ }
+ return null;
+ }
+
+ @Nullable
+ private static String resolveToQualifiedName(@NotNull PyExpression expression, @NotNull TypeEvalContext context) {
+ final PsiElement element = resolve(expression, context);
+ if (element instanceof PyQualifiedNameOwner) {
+ final PyQualifiedNameOwner qualifiedNameOwner = (PyQualifiedNameOwner)element;
+ return qualifiedNameOwner.getQualifiedName();
+ }
+ return null;
+ }
+}
diff --git a/python/src/com/jetbrains/python/codeInsight/highlighting/PyHighlightExitPointsHandlerFactory.java b/python/src/com/jetbrains/python/codeInsight/highlighting/PyHighlightExitPointsHandlerFactory.java
index d0bc9dcbc7ca..27522d6e7f53 100644
--- a/python/src/com/jetbrains/python/codeInsight/highlighting/PyHighlightExitPointsHandlerFactory.java
+++ b/python/src/com/jetbrains/python/codeInsight/highlighting/PyHighlightExitPointsHandlerFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,30 +15,26 @@
*/
package com.jetbrains.python.codeInsight.highlighting;
-import com.intellij.codeInsight.TargetElementUtilBase;
import com.intellij.codeInsight.highlighting.HighlightUsagesHandlerBase;
-import com.intellij.codeInsight.highlighting.HighlightUsagesHandlerFactory;
+import com.intellij.codeInsight.highlighting.HighlightUsagesHandlerFactoryBase;
import com.intellij.openapi.editor.Editor;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiTreeUtil;
import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.psi.PyReturnStatement;
+import org.jetbrains.annotations.NotNull;
/**
* @author oleg
*/
-public class PyHighlightExitPointsHandlerFactory implements HighlightUsagesHandlerFactory {
- public HighlightUsagesHandlerBase createHighlightUsagesHandler(final Editor editor, final PsiFile file) {
- int offset = TargetElementUtilBase.adjustOffset(file, editor.getDocument(), editor.getCaretModel().getOffset());
- PsiElement target = file.findElementAt(offset);
- if (target != null) {
- final PyReturnStatement returnStatement = PsiTreeUtil.getParentOfType(target, PyReturnStatement.class);
- if (returnStatement != null) {
- final PyExpression returnExpr = returnStatement.getExpression();
- if (returnExpr == null || !PsiTreeUtil.isAncestor(returnExpr, target, false)) {
- return new PyHighlightExitPointsHandler(editor, file, target);
- }
+public class PyHighlightExitPointsHandlerFactory extends HighlightUsagesHandlerFactoryBase {
+ public HighlightUsagesHandlerBase createHighlightUsagesHandler(@NotNull Editor editor, @NotNull PsiFile file, @NotNull PsiElement target) {
+ final PyReturnStatement returnStatement = PsiTreeUtil.getParentOfType(target, PyReturnStatement.class);
+ if (returnStatement != null) {
+ final PyExpression returnExpr = returnStatement.getExpression();
+ if (returnExpr == null || !PsiTreeUtil.isAncestor(returnExpr, target, false)) {
+ return new PyHighlightExitPointsHandler(editor, file, target);
}
}
return null;
diff --git a/python/src/com/jetbrains/python/codeInsight/intentions/ImportToImportFromIntention.java b/python/src/com/jetbrains/python/codeInsight/intentions/ImportToImportFromIntention.java
index fc35833473f8..e76240cefb1f 100644
--- a/python/src/com/jetbrains/python/codeInsight/intentions/ImportToImportFromIntention.java
+++ b/python/src/com/jetbrains/python/codeInsight/intentions/ImportToImportFromIntention.java
@@ -57,10 +57,11 @@ public class ImportToImportFromIntention implements IntentionAction {
private PsiElement myReferee = null;
private PyImportElement myImportElement = null;
private Collection<PsiReference> myReferences = null;
- private boolean myHasModuleReference = false; // is anything that resolves to our imported module is just an exact reference to that module
+ private boolean myHasModuleReference = false;
+ // is anything that resolves to our imported module is just an exact reference to that module
private int myRelativeLevel; // true if "from ... import"
- public IntentionState(Editor editor, PsiFile file) {
+ public IntentionState(@NotNull Editor editor, @NotNull PsiFile file) {
boolean available = false;
myImportElement = findImportElement(editor, file);
if (myImportElement != null) {
@@ -70,10 +71,10 @@ public class ImportToImportFromIntention implements IntentionAction {
available = true;
}
else if (parent instanceof PyFromImportStatement) {
- PyFromImportStatement from_import = (PyFromImportStatement)parent;
- final int relative_level = from_import.getRelativeLevel();
- if (from_import.isValid() && relative_level > 0 && from_import.getImportSource() == null) {
- myRelativeLevel = relative_level;
+ final PyFromImportStatement fromImport = (PyFromImportStatement)parent;
+ final int relativeLevel = fromImport.getRelativeLevel();
+ if (fromImport.isValid() && relativeLevel > 0 && fromImport.getImportSource() == null) {
+ myRelativeLevel = relativeLevel;
available = true;
}
}
@@ -92,25 +93,27 @@ public class ImportToImportFromIntention implements IntentionAction {
assert myImportElement != null : "isAvailable() must have returned true, but myImportElement is null";
// usages of imported name are qualifiers; what they refer to?
- PyReferenceExpression reference = myImportElement.getImportReferenceExpression();
- if (reference != null) {
- myModuleName = PyPsiUtils.toPath(reference);
+ final PyReferenceExpression importReference = myImportElement.getImportReferenceExpression();
+ if (importReference != null) {
+ myModuleName = PyPsiUtils.toPath(importReference);
myQualifierName = myImportElement.getVisibleName();
- myReferee = reference.getReference().resolve();
+ myReferee = importReference.getReference().resolve();
myHasModuleReference = false;
if (myReferee != null && myModuleName != null && myQualifierName != null) {
final Collection<PsiReference> references = new ArrayList<PsiReference>();
PsiTreeUtil.processElements(file, new PsiElementProcessor() {
public boolean execute(@NotNull PsiElement element) {
if (element instanceof PyReferenceExpression && PsiTreeUtil.getParentOfType(element, PyImportElement.class) == null) {
- PyReferenceExpression ref = (PyReferenceExpression)element;
+ final PyReferenceExpression ref = (PyReferenceExpression)element;
if (myQualifierName.equals(PyPsiUtils.toPath(ref))) { // filter out other names that might resolve to our target
- PsiElement parent_elt = ref.getParent();
- if (parent_elt instanceof PyQualifiedExpression) { // really qualified by us, not just referencing?
- PsiElement resolved = ref.getReference().resolve();
+ final PsiElement parentElt = ref.getParent();
+ if (parentElt instanceof PyQualifiedExpression) { // really qualified by us, not just referencing?
+ final PsiElement resolved = ref.getReference().resolve();
if (resolved == myReferee) references.add(ref.getReference());
}
- else myHasModuleReference = true;
+ else {
+ myHasModuleReference = true;
+ }
}
}
return true;
@@ -123,68 +126,70 @@ public class ImportToImportFromIntention implements IntentionAction {
public void invoke() {
assert myImportElement != null : "isAvailable() must have returned true, but myImportElement is null";
- PyUtil.sure(myImportElement.getImportReferenceExpression());
- Project project = myImportElement.getProject();
+ sure(myImportElement.getImportReferenceExpression());
+ final Project project = myImportElement.getProject();
+
+ final PyElementGenerator generator = PyElementGenerator.getInstance(project);
+ final LanguageLevel languageLevel = LanguageLevel.forElement(myImportElement);
// usages of imported name are qualifiers; what they refer to?
try {
// remember names and make them drop qualifiers
- Set<String> used_names = new HashSet<String>();
+ final Set<String> usedNames = new HashSet<String>();
for (PsiReference ref : myReferences) {
- PsiElement elt = ref.getElement();
- PsiElement parent_elt = elt.getParent();
- used_names.add(sure(PyUtil.sure(parent_elt).getLastChild()).getText()); // TODO: find ident node more properly
+ final PsiElement elt = ref.getElement();
+ final PsiElement parentElt = elt.getParent();
+ // TODO: find ident node more properly
+ final String nameUsed = sure(sure(parentElt).getLastChild()).getText();
+ usedNames.add(nameUsed);
if (!FileModificationService.getInstance().preparePsiElementForWrite(elt)) {
return;
}
- PsiElement next_elt = elt.getNextSibling();
- if (next_elt != null && ".".equals(next_elt.getText())) next_elt.delete();
- elt.delete();
+ assert parentElt instanceof PyReferenceExpression;
+ final PyElement newReference = generator.createExpressionFromText(languageLevel, nameUsed);
+ parentElt.replace(newReference);
}
// create a separate import stmt for the module
- PsiElement importer = myImportElement.getParent();
- PyStatement import_statement;
- PyImportElement[] import_elements;
+ final PsiElement importer = myImportElement.getParent();
+ final PyStatement importStatement;
+ final PyImportElement[] importElements;
if (importer instanceof PyImportStatement) {
- import_statement = (PyImportStatement)importer;
- import_elements = ((PyImportStatement)import_statement).getImportElements();
+ importStatement = (PyImportStatement)importer;
+ importElements = ((PyImportStatement)importStatement).getImportElements();
}
else if (importer instanceof PyFromImportStatement) {
- import_statement = (PyFromImportStatement)importer;
- import_elements = ((PyFromImportStatement)import_statement).getImportElements();
+ importStatement = (PyFromImportStatement)importer;
+ importElements = ((PyFromImportStatement)importStatement).getImportElements();
}
else {
throw new IncorrectOperationException("Not an import at all");
}
- PyElementGenerator generator = PyElementGenerator.getInstance(project);
- StringBuilder builder = new StringBuilder("from ").append(getDots()).append(myModuleName).append(" import ");
- builder.append(StringUtil.join(used_names, ", "));
- PyFromImportStatement from_import_stmt =
- generator.createFromText(LanguageLevel.getDefault(), PyFromImportStatement.class, builder.toString());
- PsiElement parent = import_statement.getParent();
+ final PyFromImportStatement newImportStatement =
+ generator.createFromImportStatement(languageLevel, getDots() + myModuleName, StringUtil.join(usedNames, ", "), null);
+ final PsiElement parent = importStatement.getParent();
sure(parent);
sure(parent.isValid());
- if (import_elements.length == 1) {
+ if (importElements.length == 1) {
if (myHasModuleReference) {
- parent.addAfter(from_import_stmt, import_statement); // add 'import from': we need the module imported as is
+ parent.addAfter(newImportStatement, importStatement); // add 'import from': we need the module imported as is
}
else { // replace entire existing import
- sure(parent.getNode()).replaceChild(sure(import_statement.getNode()), sure(from_import_stmt.getNode()));
+ sure(parent.getNode()).replaceChild(sure(importStatement.getNode()), sure(newImportStatement.getNode()));
// import_statement.replace(from_import_stmt);
}
}
else {
if (!myHasModuleReference) {
// cut the module out of import, add a from-import.
- for (PyImportElement pie : import_elements) {
+ for (PyImportElement pie : importElements) {
if (pie == myImportElement) {
PyUtil.removeListNode(pie);
break;
}
}
}
- parent.addAfter(from_import_stmt, import_statement);
+ parent.addAfter(newImportStatement, importStatement);
}
}
catch (IncorrectOperationException ignored) {
@@ -193,18 +198,24 @@ public class ImportToImportFromIntention implements IntentionAction {
}
+ @NotNull
public String getText() {
- String module_name = "?";
+ String moduleName = "?";
if (myImportElement != null) {
- PyReferenceExpression reference = myImportElement.getImportReferenceExpression();
- if (reference != null) module_name = PyPsiUtils.toPath(reference);
+ final PyReferenceExpression reference = myImportElement.getImportReferenceExpression();
+ if (reference != null) {
+ moduleName = PyPsiUtils.toPath(reference);
+ }
}
- return PyBundle.message("INTN.convert.to.from.$0.import.$1", getDots()+module_name, "...");
+ return PyBundle.message("INTN.convert.to.from.$0.import.$1", getDots() + moduleName, "...");
}
+ @NotNull
private String getDots() {
String dots = "";
- for (int i=0; i<myRelativeLevel; i+=1) dots += "."; // this generally runs 1-2 times, so it's cheaper than allocating a StringBuilder
+ for (int i = 0; i < myRelativeLevel; i += 1) {
+ dots += "."; // this generally runs 1-2 times, so it's cheaper than allocating a StringBuilder
+ }
return dots;
}
}
@@ -222,10 +233,15 @@ public class ImportToImportFromIntention implements IntentionAction {
}
@Nullable
- private static PyImportElement findImportElement(Editor editor, PsiFile file) {
- PyImportElement import_elt = PsiTreeUtil.getParentOfType(file.findElementAt(editor.getCaretModel().getOffset()), PyImportElement.class);
- if (import_elt != null && import_elt.isValid()) return import_elt;
- else return null;
+ private static PyImportElement findImportElement(@NotNull Editor editor, @NotNull PsiFile file) {
+ final PsiElement elementAtCaret = file.findElementAt(editor.getCaretModel().getOffset());
+ final PyImportElement importElement = PsiTreeUtil.getParentOfType(elementAtCaret, PyImportElement.class);
+ if (importElement != null && importElement.isValid()) {
+ return importElement;
+ }
+ else {
+ return null;
+ }
}
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
@@ -233,7 +249,7 @@ public class ImportToImportFromIntention implements IntentionAction {
return false;
}
- IntentionState state = new IntentionState(editor, file);
+ final IntentionState state = new IntentionState(editor, file);
if (state.isAvailable()) {
myText = state.getText();
return true;
@@ -242,7 +258,7 @@ public class ImportToImportFromIntention implements IntentionAction {
}
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
- IntentionState state = new IntentionState(editor, file);
+ final IntentionState state = new IntentionState(editor, file);
state.invoke();
}
diff --git a/python/src/com/jetbrains/python/codeInsight/intentions/PyGenerateDocstringIntention.java b/python/src/com/jetbrains/python/codeInsight/intentions/PyGenerateDocstringIntention.java
index 7acfc9716fea..ca7ec65f9908 100644
--- a/python/src/com/jetbrains/python/codeInsight/intentions/PyGenerateDocstringIntention.java
+++ b/python/src/com/jetbrains/python/codeInsight/intentions/PyGenerateDocstringIntention.java
@@ -69,6 +69,7 @@ public class PyGenerateDocstringIntention extends BaseIntentionAction {
if (function == null || statementList != null) {
return false;
}
+ if (!elementAt.equals(function.getNameNode())) return false;
return isAvailableForFunction(project, function);
}
diff --git a/python/src/com/jetbrains/python/codeInsight/override/PyOverrideImplementUtil.java b/python/src/com/jetbrains/python/codeInsight/override/PyOverrideImplementUtil.java
index 48a42753ebe5..e11f3e01e916 100644
--- a/python/src/com/jetbrains/python/codeInsight/override/PyOverrideImplementUtil.java
+++ b/python/src/com/jetbrains/python/codeInsight/override/PyOverrideImplementUtil.java
@@ -143,7 +143,7 @@ public class PyOverrideImplementUtil {
return;
}
new WriteCommandAction(pyClass.getProject(), pyClass.getContainingFile()) {
- protected void run(final Result result) throws Throwable {
+ protected void run(@NotNull final Result result) throws Throwable {
write(pyClass, membersToOverride, editor, implement);
}
}.execute();
@@ -173,9 +173,7 @@ public class PyOverrideImplementUtil {
PyPsiUtils.removeRedundantPass(statementList);
if (element != null) {
final PyStatementList targetStatementList = element.getStatementList();
- final int start = targetStatementList != null
- ? targetStatementList.getTextRange().getStartOffset()
- : element.getTextRange().getStartOffset();
+ final int start = targetStatementList.getTextRange().getStartOffset();
editor.getCaretModel().moveToOffset(start);
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
editor.getSelectionModel().setSelection(start, element.getTextRange().getEndOffset());
@@ -238,7 +236,7 @@ public class PyOverrideImplementUtil {
PsiElement outerClass = PsiTreeUtil.getParentOfType(pyClass, PyClass.class, true, PyFunction.class);
String className = pyClass.getName();
final List<String> nameResult = Lists.newArrayList(className);
- while(outerClass instanceof PyClass) {
+ while(outerClass != null) {
nameResult.add(0, ((PyClass)outerClass).getName());
outerClass = PsiTreeUtil.getParentOfType(outerClass, PyClass.class, true, PyFunction.class);
}