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:
@@ -34,7 +34,8 @@ public class PyJavaClassType implements PyClassLikeType {
|
||||
public List<? extends RatedResolveResult> resolveMember(@NotNull final String name,
|
||||
PyExpression location,
|
||||
AccessDirection direction,
|
||||
PyResolveContext resolveContext) {
|
||||
PyResolveContext resolveContext,
|
||||
boolean inherited) {
|
||||
final PsiMethod[] methods = myClass.findMethodsByName(name, true);
|
||||
if (methods.length > 0) {
|
||||
ResolveResultList resultList = new ResolveResultList();
|
||||
|
||||
@@ -43,7 +43,8 @@ public class PyJavaMethodType implements PyCallableType {
|
||||
public List<? extends RatedResolveResult> resolveMember(@NotNull String name,
|
||||
@Nullable PyExpression location,
|
||||
AccessDirection direction,
|
||||
PyResolveContext resolveContext) {
|
||||
PyResolveContext resolveContext,
|
||||
boolean inherited) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,8 @@ public class PyJavaPackageType implements PyType {
|
||||
public List<? extends RatedResolveResult> resolveMember(@NotNull String name,
|
||||
@Nullable PyExpression location,
|
||||
AccessDirection direction,
|
||||
PyResolveContext resolveContext) {
|
||||
PyResolveContext resolveContext,
|
||||
boolean inherited) {
|
||||
Project project = myPackage.getProject();
|
||||
JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
|
||||
String childName = myPackage.getQualifiedName() + "." + name;
|
||||
|
||||
@@ -22,18 +22,18 @@ public interface PyType {
|
||||
/**
|
||||
* Resolves an attribute of type.
|
||||
*
|
||||
*
|
||||
* @param name attribute name
|
||||
* @param location the expression of type qualifierType on which the member is being resolved (optional)
|
||||
* @param direction
|
||||
* @param resolveContext
|
||||
* @param inherited look up inherited members and members provided by class providers
|
||||
* @return null if name definitely cannot be found (e.g. in a qualified reference),
|
||||
* or an empty list if name is not found but other contexts are worth looking at,
|
||||
* or a list of elements that define the name, a la multiResolve().
|
||||
*/
|
||||
@Nullable
|
||||
List<? extends RatedResolveResult> resolveMember(@NotNull final String name, @Nullable PyExpression location, AccessDirection direction,
|
||||
PyResolveContext resolveContext);
|
||||
PyResolveContext resolveContext, boolean inherited);
|
||||
|
||||
/**
|
||||
* Proposes completion variants from type's attributes.
|
||||
|
||||
@@ -299,15 +299,43 @@ public class PyControlFlowBuilder extends PyRecursiveElementVisitor {
|
||||
});
|
||||
myBuilder.addPendingEdge(node, myBuilder.prevInstruction);
|
||||
}
|
||||
boolean noPendingInScopeEdges = false;
|
||||
if (!assertionEvaluator.getDefinitions().isEmpty()) {
|
||||
final Ref<Boolean> pendingInScopeEdges = Ref.create(false);
|
||||
myBuilder.processPending(new ControlFlowBuilder.PendingProcessor() {
|
||||
@Override
|
||||
public void process(PsiElement pendingScope, Instruction instruction) {
|
||||
if (pendingScope != null && PsiTreeUtil.isAncestor(node, pendingScope, false)) {
|
||||
pendingInScopeEdges.set(true);
|
||||
}
|
||||
myBuilder.addPendingEdge(pendingScope, instruction);
|
||||
}
|
||||
});
|
||||
noPendingInScopeEdges = !pendingInScopeEdges.get();
|
||||
}
|
||||
final PyTypeAssertionEvaluator negativeAssertionEvaluator = new PyTypeAssertionEvaluator(false);
|
||||
final PyExpression ifCondition = ifPart.getCondition();
|
||||
// TODO: Add support for 'elif'
|
||||
if (ifCondition != null) {
|
||||
ifCondition.accept(negativeAssertionEvaluator);
|
||||
}
|
||||
final PyElsePart elseBranch = node.getElsePart();
|
||||
if (elseBranch != null) {
|
||||
// Set the head as the false branch
|
||||
myBuilder.prevInstruction = lastBranchingPoint;
|
||||
myBuilder.startConditionalNode(elseBranch, lastCondition, false);
|
||||
InstructionBuilder.addAssertInstructions(myBuilder, negativeAssertionEvaluator);
|
||||
elseBranch.accept(this);
|
||||
myBuilder.addPendingEdge(node, myBuilder.prevInstruction);
|
||||
} else {
|
||||
myBuilder.addPendingEdge(node, lastBranchingPoint);
|
||||
if (noPendingInScopeEdges) {
|
||||
myBuilder.prevInstruction = lastBranchingPoint;
|
||||
InstructionBuilder.addAssertInstructions(myBuilder, negativeAssertionEvaluator);
|
||||
myBuilder.addPendingEdge(node, myBuilder.prevInstruction);
|
||||
}
|
||||
else {
|
||||
myBuilder.addPendingEdge(node, lastBranchingPoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+14
-4
@@ -16,7 +16,15 @@ import java.util.Stack;
|
||||
*/
|
||||
public class PyTypeAssertionEvaluator extends PyRecursiveElementVisitor {
|
||||
private Stack<Assertion> myStack = new Stack<Assertion>();
|
||||
private boolean myPositive = true;
|
||||
private boolean myPositive;
|
||||
|
||||
public PyTypeAssertionEvaluator() {
|
||||
this(true);
|
||||
}
|
||||
|
||||
public PyTypeAssertionEvaluator(boolean positive) {
|
||||
myPositive = positive;
|
||||
}
|
||||
|
||||
public List<Assertion> getDefinitions() {
|
||||
return myStack;
|
||||
@@ -24,7 +32,7 @@ public class PyTypeAssertionEvaluator extends PyRecursiveElementVisitor {
|
||||
|
||||
@Override
|
||||
public void visitPyPrefixExpression(PyPrefixExpression node) {
|
||||
if (myPositive && node.getOperator() == PyTokenTypes.NOT_KEYWORD) {
|
||||
if (node.getOperator() == PyTokenTypes.NOT_KEYWORD) {
|
||||
myPositive = !myPositive;
|
||||
super.visitPyPrefixExpression(node);
|
||||
myPositive = !myPositive;
|
||||
@@ -74,12 +82,13 @@ public class PyTypeAssertionEvaluator extends PyRecursiveElementVisitor {
|
||||
@Override
|
||||
public void visitPyReferenceExpression(final PyReferenceExpression node) {
|
||||
if (node.getParent() instanceof PyIfPart) {
|
||||
final boolean positive = myPositive;
|
||||
pushAssertion(node, new InstructionTypeCallback() {
|
||||
@Override
|
||||
public PyType getType(TypeEvalContext context, PsiElement anchor) {
|
||||
final List<PyType> types = new ArrayList<PyType>();
|
||||
types.add(PyNoneType.INSTANCE);
|
||||
return createAssertionType(context.getType(node), types, false, context);
|
||||
return createAssertionType(context.getType(node), types, !positive, context);
|
||||
}
|
||||
});
|
||||
return;
|
||||
@@ -95,12 +104,13 @@ public class PyTypeAssertionEvaluator extends PyRecursiveElementVisitor {
|
||||
if (lhs instanceof PyReferenceExpression && rhs instanceof PyReferenceExpression) {
|
||||
final PyReferenceExpression target = (PyReferenceExpression)lhs;
|
||||
if (PyNames.NONE.equals(rhs.getName())) {
|
||||
final boolean positive = myPositive;
|
||||
pushAssertion(target, new InstructionTypeCallback() {
|
||||
@Override
|
||||
public PyType getType(TypeEvalContext context, @Nullable PsiElement anchor) {
|
||||
final List<PyType> types = new ArrayList<PyType>();
|
||||
types.add(PyNoneType.INSTANCE);
|
||||
return createAssertionType(context.getType(target), types, false, context);
|
||||
return createAssertionType(context.getType(target), types, !positive, context);
|
||||
}
|
||||
});
|
||||
return;
|
||||
|
||||
@@ -45,8 +45,9 @@ public class PyNamedTupleType extends PyClassTypeImpl implements PyCallableType
|
||||
public List<? extends RatedResolveResult> resolveMember(@NotNull String name,
|
||||
@Nullable PyExpression location,
|
||||
AccessDirection direction,
|
||||
PyResolveContext resolveContext) {
|
||||
final List<? extends RatedResolveResult> classMembers = super.resolveMember(name, location, direction, resolveContext);
|
||||
PyResolveContext resolveContext,
|
||||
boolean inherited) {
|
||||
final List<? extends RatedResolveResult> classMembers = super.resolveMember(name, location, direction, resolveContext, inherited);
|
||||
if (classMembers != null && !classMembers.isEmpty()) {
|
||||
return classMembers;
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ public class PyStatementEffectInspection extends PyInspection {
|
||||
PyType type = myTypeEvalContext.getType(binary.getLeftExpression());
|
||||
if (type != null &&
|
||||
!type.isBuiltin(myTypeEvalContext) &&
|
||||
type.resolveMember(method, null, AccessDirection.READ, resolveWithoutImplicits()) != null) {
|
||||
type.resolveMember(method, null, AccessDirection.READ, resolveWithoutImplicits(), true) != null) {
|
||||
return true;
|
||||
}
|
||||
final PyExpression rhs = binary.getRightExpression();
|
||||
@@ -131,7 +131,8 @@ public class PyStatementEffectInspection extends PyInspection {
|
||||
type = myTypeEvalContext.getType(rhs);
|
||||
if (type != null) {
|
||||
String rmethod = "__r" + method.substring(2); // __add__ -> __radd__
|
||||
if (!type.isBuiltin(myTypeEvalContext) && type.resolveMember(rmethod, null, AccessDirection.READ, resolveWithoutImplicits()) != null) {
|
||||
if (!type.isBuiltin(myTypeEvalContext) && type.resolveMember(rmethod, null, AccessDirection.READ, resolveWithoutImplicits(),
|
||||
true) != null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -805,7 +805,8 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
|
||||
final PyType type = context.getType(cls);
|
||||
if (type != null) {
|
||||
final List<? extends RatedResolveResult> results = type.resolveMember(name, null, AccessDirection.READ,
|
||||
PyResolveContext.noImplicits().withTypeEvalContext(context));
|
||||
PyResolveContext.noImplicits().withTypeEvalContext(context),
|
||||
true);
|
||||
if (results != null && !results.isEmpty()) {
|
||||
return results.get(0).getElement();
|
||||
}
|
||||
|
||||
@@ -1091,11 +1091,6 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
|
||||
@NotNull
|
||||
@Override
|
||||
public List<PyClassLikeType> getAncestorTypes(@NotNull TypeEvalContext context) {
|
||||
return calculateAncestorTypes(context);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private List<PyClassLikeType> calculateAncestorTypes(@NotNull TypeEvalContext context) {
|
||||
myCachedAncestorsProvider.setTypeEvalContext(context);
|
||||
try {
|
||||
// TODO: Return different cached copies depending on the type eval context parameters
|
||||
|
||||
@@ -135,7 +135,10 @@ public class PyTargetExpressionImpl extends PyPresentableElementImpl<PyTargetExp
|
||||
final PsiElement parent = getParent();
|
||||
if (parent instanceof PyAssignmentStatement) {
|
||||
final PyAssignmentStatement assignmentStatement = (PyAssignmentStatement)parent;
|
||||
final PyExpression assignedValue = assignmentStatement.getAssignedValue();
|
||||
PyExpression assignedValue = assignmentStatement.getAssignedValue();
|
||||
if (assignedValue instanceof PyParenthesizedExpression) {
|
||||
assignedValue = ((PyParenthesizedExpression)assignedValue).getContainedExpression();
|
||||
}
|
||||
if (assignedValue != null) {
|
||||
if (assignedValue instanceof PyReferenceExpressionImpl) {
|
||||
final PyReferenceExpressionImpl refex = (PyReferenceExpressionImpl)assignedValue;
|
||||
@@ -447,7 +450,7 @@ public class PyTargetExpressionImpl extends PyPresentableElementImpl<PyTargetExp
|
||||
final PyType type = TypeEvalContext.fastStubOnly(null).getType((PyClass)parent);
|
||||
if (type != null) {
|
||||
final List<? extends RatedResolveResult> results = type.resolveMember(name, null, AccessDirection.READ,
|
||||
PyResolveContext.noImplicits());
|
||||
PyResolveContext.noImplicits(), true);
|
||||
if (results != null && !results.isEmpty()) {
|
||||
return results.get(0).getElement();
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ public class PyOperatorReference extends PyReferenceImpl {
|
||||
final PyType type = typeEvalContext.getType(object);
|
||||
typeEvalContext.trace("Side text is %s, type is %s", object.getText(), type);
|
||||
if (type != null && !(type instanceof PyTypeReference)) {
|
||||
List<? extends RatedResolveResult> res = type.resolveMember(name, object, AccessDirection.of(myElement), myContext);
|
||||
List<? extends RatedResolveResult> res = type.resolveMember(name, object, AccessDirection.of(myElement), myContext, true);
|
||||
if (res != null && res.size() > 0) {
|
||||
results.addAll(res);
|
||||
}
|
||||
@@ -141,7 +141,7 @@ public class PyOperatorReference extends PyReferenceImpl {
|
||||
final PyClass pyClass = ((PyClassType)type).getPyClass();
|
||||
vFile = pyClass.getContainingFile().getVirtualFile();
|
||||
}
|
||||
type.resolveMember(name, object, AccessDirection.of(myElement), myContext);
|
||||
type.resolveMember(name, object, AccessDirection.of(myElement), myContext, true);
|
||||
typeEvalContext.trace("Could not resolve member %s in type %s from file %s", name, type, vFile);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +71,8 @@ public class PyQualifiedReference extends PyReferenceImpl {
|
||||
qualifierType.assertValid("qualifier: " + qualifier);
|
||||
// resolve within the type proper
|
||||
AccessDirection ctx = AccessDirection.of(myElement);
|
||||
final List<? extends RatedResolveResult> membersOfQualifier = qualifierType.resolveMember(referencedName, qualifier, ctx, myContext);
|
||||
final List<? extends RatedResolveResult> membersOfQualifier = qualifierType.resolveMember(referencedName, qualifier, ctx, myContext,
|
||||
true);
|
||||
if (membersOfQualifier == null) {
|
||||
return ret; // qualifier is positive that such name cannot exist in it
|
||||
}
|
||||
@@ -238,8 +239,13 @@ public class PyQualifiedReference extends PyReferenceImpl {
|
||||
@NotNull
|
||||
@Override
|
||||
public Object[] getVariants() {
|
||||
PyExpression qualifier = CompletionUtil.getOriginalOrSelf(myElement.getQualifier());
|
||||
assert qualifier != null;
|
||||
PyExpression qualifier = myElement.getQualifier();
|
||||
if (qualifier != null) {
|
||||
qualifier = CompletionUtil.getOriginalOrSelf(qualifier);
|
||||
}
|
||||
if (qualifier == null) {
|
||||
return EMPTY_ARRAY;
|
||||
}
|
||||
final PyQualifiedExpression element = CompletionUtil.getOriginalOrSelf(myElement);
|
||||
|
||||
PyType qualifierType = TypeEvalContext.slow().getType(qualifier);
|
||||
|
||||
@@ -302,7 +302,7 @@ public class PyReferenceImpl implements PsiReferenceEx, PsiPolyVariantReference
|
||||
if (PyModuleType.MODULE_MEMBERS.contains(name)) {
|
||||
PyType otype = builtins_cache.getObjectType(); // "object" as a closest kin to "module"
|
||||
if (otype != null && name != null) {
|
||||
ret.addAll(otype.resolveMember(name, null, AccessDirection.READ, myContext));
|
||||
ret.addAll(otype.resolveMember(name, null, AccessDirection.READ, myContext, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -274,7 +274,7 @@ public class ResolveImportUtil {
|
||||
PyType refType = PyReferenceExpressionImpl.getReferenceTypeFromProviders(parent, TypeEvalContext.fast(), null);
|
||||
if (refType != null) {
|
||||
final List<? extends RatedResolveResult> result = refType.resolveMember(referencedName, null, AccessDirection.READ,
|
||||
PyResolveContext.defaultContext());
|
||||
PyResolveContext.defaultContext(), true);
|
||||
if (result != null && !result.isEmpty()) {
|
||||
return result.get(0).getElement();
|
||||
}
|
||||
|
||||
@@ -102,7 +102,8 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
|
||||
public List<? extends RatedResolveResult> resolveMember(@NotNull final String name,
|
||||
@Nullable PyExpression location,
|
||||
AccessDirection direction,
|
||||
PyResolveContext resolveContext) {
|
||||
PyResolveContext resolveContext,
|
||||
boolean inherited) {
|
||||
final Set<Pair<PyClass, String>> resolving = ourResolveMemberStack.get();
|
||||
final Pair<PyClass, String> key = Pair.create(myClass, name);
|
||||
if (resolving.contains(key)) {
|
||||
@@ -110,7 +111,7 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
|
||||
}
|
||||
resolving.add(key);
|
||||
try {
|
||||
return doResolveMember(name, location, direction, resolveContext);
|
||||
return doResolveMember(name, location, direction, resolveContext, inherited);
|
||||
}
|
||||
finally {
|
||||
resolving.remove(key);
|
||||
@@ -121,7 +122,8 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
|
||||
private List<? extends RatedResolveResult> doResolveMember(@NotNull String name,
|
||||
@Nullable PyExpression location,
|
||||
@NotNull AccessDirection direction,
|
||||
@NotNull PyResolveContext resolveContext) {
|
||||
@NotNull PyResolveContext resolveContext,
|
||||
boolean inherited) {
|
||||
final TypeEvalContext context = resolveContext.getTypeEvalContext();
|
||||
PsiElement classMember = resolveByOverridingMembersProviders(this, name); //overriding members provers have priority to normal resolve
|
||||
if (classMember != null) {
|
||||
@@ -157,7 +159,7 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
|
||||
PyClass derived_class = ((PyClassType)first_arg_type).getPyClass();
|
||||
final Iterator<PyClass> base_it = derived_class.getAncestorClasses(context).iterator();
|
||||
if (base_it.hasNext()) {
|
||||
return new PyClassTypeImpl(base_it.next(), true).resolveMember(name, location, direction, resolveContext);
|
||||
return new PyClassTypeImpl(base_it.next(), true).resolveMember(name, location, direction, resolveContext, true);
|
||||
}
|
||||
else {
|
||||
return null; // no base classes = super() cannot proxy anything meaningful from a base class
|
||||
@@ -171,17 +173,19 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
|
||||
return ResolveResultList.to(classMember);
|
||||
}
|
||||
|
||||
for (PyClassLikeType type : myClass.getAncestorTypes(context)) {
|
||||
if (type instanceof PyClassType) {
|
||||
PsiElement superMember = resolveClassMember(((PyClassType)type).getPyClass(), myIsDefinition, name, null);
|
||||
if (superMember != null) {
|
||||
return ResolveResultList.to(superMember);
|
||||
if (inherited) {
|
||||
for (PyClassLikeType type : myClass.getAncestorTypes(context)) {
|
||||
if (type instanceof PyClassType) {
|
||||
PsiElement superMember = resolveClassMember(((PyClassType)type).getPyClass(), myIsDefinition, name, null);
|
||||
if (superMember != null) {
|
||||
return ResolveResultList.to(superMember);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (type != null) {
|
||||
final List<? extends RatedResolveResult> results = type.resolveMember(name, location, direction, resolveContext);
|
||||
if (results != null && !results.isEmpty()) {
|
||||
return results;
|
||||
else if (type != null) {
|
||||
final List<? extends RatedResolveResult> results = type.resolveMember(name, location, direction, resolveContext, false);
|
||||
if (results != null && !results.isEmpty()) {
|
||||
return results;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -189,27 +193,31 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
|
||||
if (isDefinition() && myClass.isNewStyleClass()) {
|
||||
PyClassType typeType = getMetaclassType();
|
||||
if (typeType != null) {
|
||||
List<? extends RatedResolveResult> typeMembers = typeType.resolveMember(name, location, direction, resolveContext);
|
||||
List<? extends RatedResolveResult> typeMembers = typeType.resolveMember(name, location, direction, resolveContext, true);
|
||||
if (typeMembers != null && !typeMembers.isEmpty()) {
|
||||
return typeMembers;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
classMember = resolveByMembersProviders(this, name); //ask providers after real class introspection as providers have less priority
|
||||
if (inherited) {
|
||||
classMember = resolveByMembersProviders(this, name); //ask providers after real class introspection as providers have less priority
|
||||
}
|
||||
|
||||
if (classMember != null) {
|
||||
return ResolveResultList.to(classMember);
|
||||
}
|
||||
|
||||
for (PyClassLikeType type : myClass.getAncestorTypes(context)) {
|
||||
if (type instanceof PyClassType) {
|
||||
final PyClass pyClass = ((PyClassType)type).getPyClass();
|
||||
if (pyClass != null) {
|
||||
PsiElement superMember = resolveByMembersProviders(new PyClassTypeImpl(pyClass, isDefinition()), name);
|
||||
if (inherited) {
|
||||
for (PyClassLikeType type : myClass.getAncestorTypes(context)) {
|
||||
if (type instanceof PyClassType) {
|
||||
final PyClass pyClass = ((PyClassType)type).getPyClass();
|
||||
if (pyClass != null) {
|
||||
PsiElement superMember = resolveByMembersProviders(new PyClassTypeImpl(pyClass, isDefinition()), name);
|
||||
|
||||
if (superMember != null) {
|
||||
return ResolveResultList.to(superMember);
|
||||
if (superMember != null) {
|
||||
return ResolveResultList.to(superMember);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ public class PyFunctionType implements PyCallableType {
|
||||
public List<? extends RatedResolveResult> resolveMember(@NotNull String name,
|
||||
@Nullable PyExpression location,
|
||||
AccessDirection direction,
|
||||
PyResolveContext resolveContext) {
|
||||
PyResolveContext resolveContext, boolean inherited) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ public class PyGenericType implements PyType {
|
||||
public List<? extends RatedResolveResult> resolveMember(@NotNull String name,
|
||||
@Nullable PyExpression location,
|
||||
AccessDirection direction,
|
||||
PyResolveContext resolveContext) {
|
||||
PyResolveContext resolveContext, boolean inherited) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,11 +38,11 @@ public class PyImportedModuleType implements PyType {
|
||||
public List<? extends RatedResolveResult> resolveMember(@NotNull String name,
|
||||
PyExpression location,
|
||||
AccessDirection direction,
|
||||
PyResolveContext resolveContext) {
|
||||
PyResolveContext resolveContext, boolean inherited) {
|
||||
final PsiElement resolved = myImportedModule.resolve();
|
||||
if (resolved instanceof PyFile) {
|
||||
final PyFile file = (PyFile)resolved;
|
||||
return new PyModuleType(file, myImportedModule).resolveMember(name, location, direction, resolveContext);
|
||||
return new PyModuleType(file, myImportedModule).resolveMember(name, location, direction, resolveContext, true);
|
||||
}
|
||||
else if (resolved instanceof PsiDirectory) {
|
||||
final List<PsiElement> elements = Collections.singletonList(ResolveImportUtil.resolveChild(resolved, name, null, true, true));
|
||||
|
||||
@@ -62,7 +62,7 @@ public class PyModuleType implements PyType { // Modules don't descend from obje
|
||||
public List<? extends RatedResolveResult> resolveMember(@NotNull final String name,
|
||||
@Nullable PyExpression location,
|
||||
AccessDirection direction,
|
||||
PyResolveContext resolveContext) {
|
||||
PyResolveContext resolveContext, boolean inherited) {
|
||||
for (PyModuleMembersProvider provider : Extensions.getExtensions(PyModuleMembersProvider.EP_NAME)) {
|
||||
final PsiElement element = provider.resolveMember(myModule, name);
|
||||
if (element != null) {
|
||||
|
||||
@@ -24,7 +24,7 @@ public class PyNoneType implements PyType { // TODO must extend ClassType. It's
|
||||
public List<? extends RatedResolveResult> resolveMember(@NotNull final String name,
|
||||
PyExpression location,
|
||||
AccessDirection direction,
|
||||
PyResolveContext resolveContext) {
|
||||
PyResolveContext resolveContext, boolean inherited) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ import com.intellij.psi.ResolveResult;
|
||||
import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.codeInsight.stdlib.PyStdlibTypeProvider;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.impl.PyBuiltinCache;
|
||||
import com.jetbrains.python.psi.resolve.PyResolveContext;
|
||||
import com.jetbrains.python.psi.resolve.RatedResolveResult;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -465,7 +464,8 @@ public class PyTypeChecker {
|
||||
for (PyType member : unionType.getMembers()) {
|
||||
if (member != null) {
|
||||
final PyResolveContext resolveContext = PyResolveContext.noImplicits().withTypeEvalContext(context);
|
||||
final List<? extends RatedResolveResult> results = member.resolveMember(name, callee, AccessDirection.READ, resolveContext);
|
||||
final List<? extends RatedResolveResult> results = member.resolveMember(name, callee, AccessDirection.READ, resolveContext,
|
||||
true);
|
||||
if (results != null && !results.isEmpty()) {
|
||||
sameNameCount++;
|
||||
}
|
||||
|
||||
@@ -241,7 +241,7 @@ public class PyTypeParser {
|
||||
final String shortName = classRange.substring(qName);
|
||||
if (moduleType != null) {
|
||||
final PyResolveContext context = PyResolveContext.defaultContext();
|
||||
final List<? extends RatedResolveResult> results = moduleType.resolveMember(shortName, null, AccessDirection.READ, context);
|
||||
final List<? extends RatedResolveResult> results = moduleType.resolveMember(shortName, null, AccessDirection.READ, context, true);
|
||||
if (results != null && !results.isEmpty()) {
|
||||
final RatedResolveResult result = results.get(0);
|
||||
final PsiElement resolved = result.getElement();
|
||||
|
||||
@@ -23,7 +23,7 @@ public abstract class PyTypeReferenceImpl implements PyTypeReference {
|
||||
public List<? extends RatedResolveResult> resolveMember(@NotNull String name,
|
||||
PyExpression location,
|
||||
AccessDirection direction,
|
||||
PyResolveContext resolveContext) {
|
||||
PyResolveContext resolveContext, boolean inherited) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
@@ -27,12 +27,12 @@ public class PyUnionType implements PyType {
|
||||
public List<? extends RatedResolveResult> resolveMember(@NotNull String name,
|
||||
PyExpression location,
|
||||
AccessDirection direction,
|
||||
PyResolveContext resolveContext) {
|
||||
PyResolveContext resolveContext, boolean inherited) {
|
||||
SmartList<RatedResolveResult> ret = new SmartList<RatedResolveResult>();
|
||||
boolean all_nulls = true;
|
||||
for (PyType member : myMembers) {
|
||||
if (member != null) {
|
||||
List<? extends RatedResolveResult> result = member.resolveMember(name, null, direction, resolveContext);
|
||||
List<? extends RatedResolveResult> result = member.resolveMember(name, null, direction, resolveContext, true);
|
||||
if (result != null) {
|
||||
all_nulls = false;
|
||||
ret.addAll(result);
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
0(1) element: null
|
||||
1(2) element: PyWhileStatement
|
||||
2(3,10) READ ACCESS: foo
|
||||
2(3,11) READ ACCESS: foo
|
||||
3(4) element: PyStatementList. Condition: foo:true
|
||||
4(5) element: PyIfStatement
|
||||
5(6,9) READ ACCESS: condition
|
||||
6(7) element: PyStatementList. Condition: condition:true
|
||||
7(8) ASSERTTYPE ACCESS: condition
|
||||
8(10) element: PyBreakStatement
|
||||
9(1) element: PyPrintStatement
|
||||
10() element: null
|
||||
8(11) element: PyBreakStatement
|
||||
9(10) ASSERTTYPE ACCESS: condition
|
||||
10(1) element: PyPrintStatement
|
||||
11() element: null
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
0(1) element: null
|
||||
1(2) element: PyWhileStatement
|
||||
2(3,10) READ ACCESS: foo
|
||||
2(3,11) READ ACCESS: foo
|
||||
3(4) element: PyStatementList. Condition: foo:true
|
||||
4(5) element: PyIfStatement
|
||||
5(6,9) READ ACCESS: condition
|
||||
6(7) element: PyStatementList. Condition: condition:true
|
||||
7(8) ASSERTTYPE ACCESS: condition
|
||||
8(1) element: PyContinueStatement
|
||||
9(1) element: PyPrintStatement
|
||||
10() element: null
|
||||
9(10) ASSERTTYPE ACCESS: condition
|
||||
10(1) element: PyPrintStatement
|
||||
11() element: null
|
||||
|
||||
@@ -6,12 +6,13 @@
|
||||
5(6) element: PyTryExceptStatement
|
||||
6(7,9) element: PyTryPart
|
||||
7(8,9) element: PyReturnStatement
|
||||
8(9,16) READ ACCESS: renderer
|
||||
8(9,17) READ ACCESS: renderer
|
||||
9(10) element: PyExceptPart
|
||||
10(11) READ ACCESS: KeyError
|
||||
11(12) element: PyRaiseStatement
|
||||
12(16) READ ACCESS: Error
|
||||
12(17) READ ACCESS: Error
|
||||
13(14) element: PyElsePart. Condition: markup:false
|
||||
14(15) element: PyReturnStatement
|
||||
15(16) READ ACCESS: body
|
||||
16() element: null
|
||||
14(15) ASSERTTYPE ACCESS: markup
|
||||
15(16) element: PyReturnStatement
|
||||
16(17) READ ACCESS: body
|
||||
17() element: null
|
||||
|
||||
@@ -9,9 +9,10 @@
|
||||
8(9) ASSERTTYPE ACCESS: s
|
||||
9(10) element: PyAssignmentStatement
|
||||
10(11) READ ACCESS: s
|
||||
11(16) WRITE ACCESS: s2
|
||||
11(17) WRITE ACCESS: s2
|
||||
12(13) element: PyElsePart. Condition: (isinstance(s, basestring)):false
|
||||
13(14) element: PyAssignmentStatement
|
||||
14(15) READ ACCESS: s
|
||||
15(16) WRITE ACCESS: x
|
||||
16() element: null
|
||||
13(14) ASSERTTYPE ACCESS: s
|
||||
14(15) element: PyAssignmentStatement
|
||||
15(16) READ ACCESS: s
|
||||
16(17) WRITE ACCESS: x
|
||||
17() element: null
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
0(1) element: null
|
||||
1(2) element: PyWhileStatement
|
||||
2(3,10) READ ACCESS: foo
|
||||
2(3,11) READ ACCESS: foo
|
||||
3(4) element: PyStatementList. Condition: foo:true
|
||||
4(5) element: PyIfStatement
|
||||
5(6,9) READ ACCESS: condition
|
||||
6(7) element: PyStatementList. Condition: condition:true
|
||||
7(8) ASSERTTYPE ACCESS: condition
|
||||
8(10) element: PyReturnStatement
|
||||
9(1) element: PyPrintStatement
|
||||
10() element: null
|
||||
8(11) element: PyReturnStatement
|
||||
9(10) ASSERTTYPE ACCESS: condition
|
||||
10(1) element: PyPrintStatement
|
||||
11() element: null
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
16(17) element: PyAssignmentStatement
|
||||
17(18) WRITE ACCESS: c
|
||||
18(19) element: PyWhileStatement
|
||||
19(20,30) READ ACCESS: c3
|
||||
19(20,31) READ ACCESS: c3
|
||||
20(21) element: PyStatementList. Condition: c3:true
|
||||
21(22) element: PyAssignmentStatement
|
||||
22(23) WRITE ACCESS: m
|
||||
@@ -25,9 +25,10 @@
|
||||
24(25,28) READ ACCESS: m
|
||||
25(26) element: PyStatementList. Condition: m:true
|
||||
26(27) ASSERTTYPE ACCESS: m
|
||||
27(32) element: PyBreakStatement
|
||||
28(29) element: PyAssignmentStatement
|
||||
29(18) WRITE ACCESS: n
|
||||
30(31) element: PyAssignmentStatement
|
||||
31(32) WRITE ACCESS: o
|
||||
32() element: null
|
||||
27(33) element: PyBreakStatement
|
||||
28(29) ASSERTTYPE ACCESS: m
|
||||
29(30) element: PyAssignmentStatement
|
||||
30(18) WRITE ACCESS: n
|
||||
31(32) element: PyAssignmentStatement
|
||||
32(33) WRITE ACCESS: o
|
||||
33() element: null
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
def method_a():
|
||||
"""
|
||||
:rtype: dict or int
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def method_b(d):
|
||||
"""
|
||||
:type d: dict
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def f():
|
||||
var = method_a()
|
||||
if isinstance(var, int):
|
||||
return var
|
||||
method_b(var) # pass
|
||||
@@ -0,0 +1,5 @@
|
||||
def f(c):
|
||||
x = 'foo' if c else ['f', 'o', 'o']
|
||||
if not isinstance(x, str):
|
||||
raise TypeError('foo')
|
||||
return x.<warning descr="Unresolved attribute reference 'pop' for class 'str'">pop</warning>() # should warn about using 'pop()' on a 'str' instance
|
||||
@@ -0,0 +1,4 @@
|
||||
def f(x):
|
||||
if x:
|
||||
return x
|
||||
return x.upper(), 2 + x
|
||||
@@ -340,6 +340,15 @@ public class PyTypeTest extends PyTestCase {
|
||||
assertNull(actual);
|
||||
}
|
||||
|
||||
// PY-9590
|
||||
public void testYieldParensType() {
|
||||
PyExpression expr = parseExpr("def f():\n" +
|
||||
" expr = (yield 2)\n");
|
||||
TypeEvalContext context = TypeEvalContext.slow().withTracing();
|
||||
PyType actual = context.getType(expr);
|
||||
assertNull(actual);
|
||||
}
|
||||
|
||||
// PY-6702
|
||||
public void testYieldFromType() {
|
||||
PythonLanguageLevelPusher.setForcedLanguageLevel(myFixture.getProject(), LanguageLevel.PYTHON33);
|
||||
@@ -477,6 +486,17 @@ public class PyTypeTest extends PyTestCase {
|
||||
"expr = f()\n");
|
||||
}
|
||||
|
||||
// PY-5084
|
||||
public void testIfIsInstanceElse() {
|
||||
doTest("str",
|
||||
"def test(c):\n" +
|
||||
" x = 'foo' if c else 42\n" +
|
||||
" if isinstance(x, int):\n" +
|
||||
" print(x)\n" +
|
||||
" else:\n" +
|
||||
" expr = x\n");
|
||||
}
|
||||
|
||||
private PyExpression parseExpr(String text) {
|
||||
myFixture.configureByText(PythonFileType.INSTANCE, text);
|
||||
return myFixture.findElementByText("expr", PyExpression.class);
|
||||
|
||||
@@ -160,4 +160,9 @@ public class PyTypeCheckerInspectionTest extends PyTestCase {
|
||||
public void testBytesSubclassAsStr() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-9118
|
||||
public void testNegativeIsInstance() {
|
||||
doTest();
|
||||
}
|
||||
}
|
||||
|
||||
+9
@@ -267,6 +267,15 @@ public class PyUnresolvedReferencesInspectionTest extends PyTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-7694
|
||||
public void testNegativeAssertType() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testNegativeIf() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
myFixture.configureByFile(TEST_DIRECTORY + getTestName(true) + ".py");
|
||||
myFixture.enableInspections(PyUnresolvedReferencesInspection.class);
|
||||
|
||||
Reference in New Issue
Block a user