Merge branch 'python-fixes'

This commit is contained in:
Andrey Vlasovskikh
2014-05-27 20:13:00 +04:00
10 changed files with 65 additions and 11 deletions
+13
View File
@@ -4,8 +4,21 @@
<variable name="method" expression="pyFunctionName()" defaultValue="" alwaysStopAt="false" />
<variable name="end" expression="" defaultValue="" alwaysStopAt="true" />
<context>
<option name="HTML_TEXT" value="false" />
<option name="HTML" value="false" />
<option name="XSL_TEXT" value="false" />
<option name="XML" value="false" />
<option name="Python" value="true" />
<option name="Django" value="false" />
<option name="CSS_PROPERTY_VALUE" value="false" />
<option name="CSS_DECLARATION_BLOCK" value="false" />
<option name="CSS_RULESET_LIST" value="false" />
<option name="CSS" value="false" />
<option name="JAVA_SCRIPT" value="false" />
<option name="TypeScript" value="false" />
<option name="SQL" value="false" />
<option name="CoffeeScript" value="false" />
<option name="OTHER" value="false" />
</context>
</template>
<template name="main" value="if __name__ == '__main__':&#10; $END$" description="if __name__ == '__main__'" toReformat="false" toShortenFQNames="true">
@@ -17,11 +17,15 @@ package com.jetbrains.python.codeInsight.liveTemplates;
import com.intellij.codeInsight.template.FileTypeBasedContextType;
import com.intellij.patterns.PsiElementPattern;
import com.intellij.psi.PsiComment;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ProcessingContext;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.PythonFileType;
import com.jetbrains.python.psi.PyParameterList;
import com.jetbrains.python.psi.PyStringLiteralExpression;
import org.jetbrains.annotations.NotNull;
import static com.intellij.patterns.PlatformPatterns.psiElement;
@@ -39,16 +43,20 @@ public class PythonTemplateContextType extends FileTypeBasedContextType {
if (super.isInContext(file, offset)) {
final PsiElement element = file.findElementAt(offset);
if (element != null) {
return !isAfterDot(element);
return !(isAfterDot(element) || element instanceof PsiComment || element instanceof PyStringLiteralExpression ||
isInsideParameterList(element));
}
}
return false;
}
private static boolean isInsideParameterList(@NotNull PsiElement element) {
return PsiTreeUtil.getParentOfType(element, PyParameterList.class) != null;
}
private static boolean isAfterDot(@NotNull PsiElement element) {
ProcessingContext context = new ProcessingContext();
final PsiElementPattern.Capture<PsiElement> capture = psiElement().afterLeafSkipping(psiElement().whitespace(),
psiElement().withElementType(PyTokenTypes.DOT));
return capture.accepts(element, context);
return capture.accepts(element, new ProcessingContext());
}
}
@@ -195,7 +195,7 @@ public class PyTypeModelBuilder {
}
else if (type instanceof PyUnionType && allowUnions) {
if (type instanceof PyDynamicallyEvaluatedType || PyTypeChecker.isUnknown(type)) {
result = new UnknownType(build(((PyUnionType)type).excludeNull(), true));
result = new UnknownType(build(((PyUnionType)type).excludeNull(myContext), true));
}
else {
result = new OneOf(
@@ -1521,7 +1521,7 @@ public class PyUtil {
public static List<PyParameter> getParameters(@NotNull Callable callable, @NotNull TypeEvalContext context) {
PyType type = context.getType(callable);
if (type instanceof PyUnionType) {
type = ((PyUnionType)type).excludeNull();
type = ((PyUnionType)type).excludeNull(context);
}
if (type instanceof PyCallableType) {
final PyCallableType callableType = (PyCallableType)type;
@@ -239,7 +239,7 @@ public class PyNamedParameterImpl extends PyPresentableElementImpl<PyNamedParame
final PyType type = context.getType(defaultValue);
if (type != null && !(type instanceof PyNoneType)) {
if (type instanceof PyTupleType) {
return PyTypeParser.getTypeByName(this, "collections.Iterable");
return PyUnionType.createWeakType(type);
}
return type;
}
@@ -208,7 +208,7 @@ public class PyTargetExpressionImpl extends PyPresentableElementImpl<PyTargetExp
final PyAssignmentStatement assignment = (PyAssignmentStatement)nextParent;
final PyExpression value = assignment.getAssignedValue();
if (value != null) {
final PyType assignedType = context.getType(value);
final PyType assignedType = PyTypeChecker.toNonWeakType(context.getType(value), context);
if (assignedType instanceof PyTupleType) {
final PyType t = getTypeFromTupleAssignment((PyTupleExpression)parent, (PyTupleType)assignedType);
if (t != null) {
@@ -386,6 +386,14 @@ public class PyTargetExpressionImpl extends PyPresentableElementImpl<PyTargetExp
}
}
}
else if (iterableType instanceof PyTupleType) {
final PyTupleType tupleType = (PyTupleType)iterableType;
final List<PyType> memberTypes = new ArrayList<PyType>();
for (int i = 0; i < tupleType.getElementCount(); i++) {
memberTypes.add(tupleType.getElementType(i));
}
return PyUnionType.union(memberTypes);
}
else if (iterableType instanceof PyUnionType) {
final Collection<PyType> members = ((PyUnionType)iterableType).getMembers();
final List<PyType> iterationTypes = new ArrayList<PyType>();
@@ -49,7 +49,7 @@ public class PyDynamicallyEvaluatedType extends PyUnionType {
@Override
public String getName() {
PyType res = excludeNull();
PyType res = excludeNull(TypeEvalContext.codeInsightFallback());
return res != null ? res.getName() : PyNames.UNKNOWN_TYPE;
}
}
@@ -215,6 +215,17 @@ public class PyTypeChecker {
return false;
}
@Nullable
public static PyType toNonWeakType(@Nullable PyType type, @NotNull TypeEvalContext context) {
if (type instanceof PyUnionType) {
final PyUnionType unionType = (PyUnionType)type;
if (unionType.isWeak()) {
return unionType.excludeNull(context);
}
}
return type;
}
public static boolean hasGenerics(@Nullable PyType type, @NotNull TypeEvalContext context) {
final Set<PyGenericType> collected = new HashSet<PyGenericType>();
collectGenerics(type, context, collected, new HashSet<PyType>());
@@ -184,7 +184,7 @@ public class PyUnionType implements PyType {
* @return union with excluded types
*/
@Nullable
public PyType exclude(PyType type, TypeEvalContext context) {
public PyType exclude(@Nullable PyType type, @NotNull TypeEvalContext context) {
final List<PyType> members = new ArrayList<PyType>();
for (PyType m : getMembers()) {
if (type == null) {
@@ -202,8 +202,8 @@ public class PyUnionType implements PyType {
}
@Nullable
public PyType excludeNull() {
return exclude(null, null);
public PyType excludeNull(@NotNull TypeEvalContext context) {
return exclude(null, context);
}
private static PyType unit(@Nullable PyType type) {
@@ -805,6 +805,20 @@ public class PyTypeTest extends PyTestCase {
"expr = iter(xs).next()\n");
}
// PY-10967
public void testDefaultTupleParameterMember() {
doTest("int",
"def foo(xs=(1, 2)):\n" +
" expr, foo = xs\n");
}
public void testTupleIterationType() {
doTest("int | str",
"xs = (1, 'a')\n" +
"for expr in xs:\n" +
" pass\n");
}
private static TypeEvalContext getTypeEvalContext(@NotNull PyExpression element) {
return TypeEvalContext.userInitiated(element.getContainingFile()).withTracing();
}