From 2e0cf4c6241d3c8e58731b9d334cfe6f637cd8e7 Mon Sep 17 00:00:00 2001 From: Semyon Proshev Date: Tue, 25 Oct 2016 17:51:47 +0300 Subject: [PATCH] PY-11208 Fixed: False positive for mock.patch.object Hardcode mock.patch members in PyStdlibClassMembersProvider because context.maySwitchToAST returns false in most cases and there is no stub for top-level assignments --- .../stdlib/PyStdlibClassMembersProvider.java | 46 ++++++------------- 1 file changed, 15 insertions(+), 31 deletions(-) diff --git a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibClassMembersProvider.java b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibClassMembersProvider.java index eb9c67bbdc71..a9bf3fcf231b 100644 --- a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibClassMembersProvider.java +++ b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibClassMembersProvider.java @@ -17,6 +17,7 @@ package com.jetbrains.python.codeInsight.stdlib; import com.intellij.openapi.util.Key; import com.intellij.psi.PsiElement; +import com.intellij.util.containers.ContainerUtil; import com.jetbrains.python.PyNames; import com.jetbrains.python.codeInsight.PyCustomMember; import com.jetbrains.python.psi.*; @@ -34,7 +35,12 @@ import java.util.*; * @author yole */ public class PyStdlibClassMembersProvider extends PyClassMembersProviderBase { - private Key> mySocketMembersKey = Key.create("socket.members"); + + @NotNull + private static final Key> SOCKET_MEMBERS_KEY = Key.create("socket.members"); + + @NotNull + private static final List MOCK_PATCH_MEMBERS = calcMockPatchMembers(); @NotNull @Override @@ -43,10 +49,10 @@ public class PyStdlibClassMembersProvider extends PyClassMembersProviderBase { final String qualifiedName = clazz.getQualifiedName(); if ("socket._socketobject".equals(qualifiedName)) { final PyFile socketFile = (PyFile)clazz.getContainingFile(); - List socketMembers = socketFile.getUserData(mySocketMembersKey); + List socketMembers = socketFile.getUserData(SOCKET_MEMBERS_KEY); if (socketMembers == null) { socketMembers = calcSocketMembers(socketFile); - socketFile.putUserData(mySocketMembersKey, socketMembers); + socketFile.putUserData(SOCKET_MEMBERS_KEY, socketMembers); } return socketMembers; } @@ -54,7 +60,7 @@ public class PyStdlibClassMembersProvider extends PyClassMembersProviderBase { if (location instanceof PyReferenceExpression) { final PyCallable mockPatchCallable = mockPatchCallable(classType, ((PyReferenceExpression)location).getQualifier(), typeEvalContext); if (mockPatchCallable != null) { - return calcMockPatchMembers(mockPatchCallable, typeEvalContext); + return MOCK_PATCH_MEMBERS; } } @@ -65,7 +71,7 @@ public class PyStdlibClassMembersProvider extends PyClassMembersProviderBase { public PsiElement resolveMember(PyClassType clazz, String name, PsiElement location, TypeEvalContext context) { final PyCallable mockPatchCallable = mockPatchCallable(clazz, location, context); if (mockPatchCallable != null) { - for (PyCustomMember member : calcMockPatchMembers(mockPatchCallable, context)) { + for (PyCustomMember member : MOCK_PATCH_MEMBERS) { if (name.equals(member.getName())) { return member.resolve(location); } @@ -98,33 +104,11 @@ public class PyStdlibClassMembersProvider extends PyClassMembersProviderBase { } @NotNull - private static List calcMockPatchMembers(@NotNull PyCallable callable, @NotNull TypeEvalContext context) { - if (!context.maySwitchToAST(callable)) { - return Collections.emptyList(); - } + private static List calcMockPatchMembers() { + final String[] members = new String[]{"object", "dict", "multiple", "stopall", "TEST_PREFIX"}; + final String moduleQName = "unittest.mock"; - final List result = new ArrayList<>(); - - callable.getContainingFile().acceptChildren( - new PyElementVisitor() { - @Override - public void visitPyElement(PyElement node) { - } - - @Override - public void visitPyAssignmentStatement(PyAssignmentStatement node) { - final PyTargetExpression lhs = PyUtil.as(node.getLeftHandSideExpression(), PyTargetExpression.class); - final PyExpression qualifier = lhs == null ? null : lhs.getQualifier(); - final String name = lhs == null ? null : lhs.getName(); - - if (lhs != null && qualifier != null && name != null && "patch".equals(qualifier.getName())) { - result.add(new PyCustomMember(name, lhs)); - } - } - } - ); - - return result; + return ContainerUtil.map(members, member -> new PyCustomMember(member).resolvesTo(moduleQName).toAssignment("patch." + member)); } private static void addMethodsFromAttr(PyFile socketFile, List result, final String attrName) {