From ba10b39b27e0b66b9e7d1ed3bc5a9bf43be4952b Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Tue, 21 Aug 2012 17:27:36 +0400 Subject: [PATCH 1/4] Follow assignments when looking for 'requires' arguments in setup.py (PY-5828) --- .../com/jetbrains/python/packaging/PyPackageUtil.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/python/src/com/jetbrains/python/packaging/PyPackageUtil.java b/python/src/com/jetbrains/python/packaging/PyPackageUtil.java index b6b083b7f6f9..e070d76b657b 100644 --- a/python/src/com/jetbrains/python/packaging/PyPackageUtil.java +++ b/python/src/com/jetbrains/python/packaging/PyPackageUtil.java @@ -8,12 +8,15 @@ import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; import com.intellij.util.Function; import com.jetbrains.python.PyNames; import com.jetbrains.python.codeInsight.controlflow.ScopeOwner; import com.jetbrains.python.psi.*; +import com.jetbrains.python.psi.resolve.PyResolveContext; +import com.jetbrains.python.psi.resolve.QualifiedResolveResult; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -87,6 +90,14 @@ public class PyPackageUtil { if (value instanceof PyListLiteralExpression) { return (PyListLiteralExpression)value; } + if (value instanceof PyReferenceExpression) { + final PyResolveContext resolveContext = PyResolveContext.defaultContext(); + final QualifiedResolveResult result = ((PyReferenceExpression)value).followAssignmentsChain(resolveContext); + final PsiElement element = result.getElement(); + if (element instanceof PyListLiteralExpression) { + return (PyListLiteralExpression)element; + } + } } } } From 249d6eba67eaf4fc8249970b38170412baab6f7b Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Tue, 21 Aug 2012 18:05:03 +0400 Subject: [PATCH 2/4] Fixed ISE in ScopeImpl.getNameDefiners (EA-38404) --- .../python/codeInsight/dataflow/scope/impl/ScopeImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/src/com/jetbrains/python/codeInsight/dataflow/scope/impl/ScopeImpl.java b/python/src/com/jetbrains/python/codeInsight/dataflow/scope/impl/ScopeImpl.java index 3b48330d3443..a5d8da6e94b8 100644 --- a/python/src/com/jetbrains/python/codeInsight/dataflow/scope/impl/ScopeImpl.java +++ b/python/src/com/jetbrains/python/codeInsight/dataflow/scope/impl/ScopeImpl.java @@ -108,7 +108,7 @@ public class ScopeImpl implements Scope { @NotNull @Override public List getNameDefiners() { - if (myNamedElements == null) { + if (myNameDefiners == null) { collectDeclarations(); } return myNameDefiners; From b25a6e0deb8a1e45cbed7a598b47005a78a35fb0 Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Tue, 21 Aug 2012 20:00:18 +0400 Subject: [PATCH 3/4] Clear installed packages cache if files under SDK paths had been modified (PY-6767) --- .../packaging/PyPackageManagerImpl.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java b/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java index c58e51fbb468..165eee2f38f6 100644 --- a/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java +++ b/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java @@ -16,16 +16,21 @@ import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.projectRoots.SdkAdditionalData; +import com.intellij.openapi.roots.OrderRootType; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; +import com.intellij.openapi.vfs.newvfs.BulkFileListener; +import com.intellij.openapi.vfs.newvfs.events.VFileEvent; import com.intellij.util.ArrayUtil; import com.intellij.util.Function; import com.intellij.util.SystemProperties; +import com.intellij.util.messages.MessageBusConnection; import com.intellij.util.net.HttpConfigurable; import com.jetbrains.python.PyNames; import com.jetbrains.python.PythonHelpersLocator; @@ -290,6 +295,28 @@ public class PyPackageManagerImpl extends PyPackageManager { PyPackageManagerImpl(@NotNull Sdk sdk) { mySdk = sdk; + final Application app = ApplicationManager.getApplication(); + final MessageBusConnection connection = app.getMessageBus().connect(); + connection.subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener() { + @Override + public void before(@NotNull List events) {} + + @Override + public void after(@NotNull List events) { + final VirtualFile[] roots = mySdk.getRootProvider().getFiles(OrderRootType.CLASSES); + for (VFileEvent event : events) { + final VirtualFile file = event.getFile(); + if (file != null) { + for (VirtualFile root : roots) { + if (VfsUtilCore.isAncestor(root, file, false)) { + clearCaches(); + return; + } + } + } + } + } + }); } public Sdk getSdk() { From 6065082ce0e47c2b46d75ac2e39899b0c80caffb Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Wed, 22 Aug 2012 20:35:49 +0400 Subject: [PATCH 4/4] Fixed refreshing SDK roots and updating current files after installing/uninstalling packages (PY-7250) --- .../python/packaging/PyPackageManager.java | 1 + .../packaging/PyPackageManagerImpl.java | 54 +++++++++++++------ .../python/packaging/ui/PyPackagesPanel.java | 2 +- 3 files changed, 41 insertions(+), 16 deletions(-) diff --git a/python/openapi/src/com/jetbrains/python/packaging/PyPackageManager.java b/python/openapi/src/com/jetbrains/python/packaging/PyPackageManager.java index 75f3da0232ad..f9afb731e0b9 100644 --- a/python/openapi/src/com/jetbrains/python/packaging/PyPackageManager.java +++ b/python/openapi/src/com/jetbrains/python/packaging/PyPackageManager.java @@ -14,4 +14,5 @@ public abstract class PyPackageManager { public abstract boolean hasPip(); public abstract void install(String requirementString) throws PyExternalProcessException; public abstract void showInstallationError(Project project, String title, String description); + public abstract void refresh(); } diff --git a/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java b/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java index 165eee2f38f6..88acf9fd3490 100644 --- a/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java +++ b/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java @@ -22,22 +22,22 @@ import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.openapi.vfs.newvfs.BulkFileListener; +import com.intellij.openapi.vfs.newvfs.NewVirtualFile; import com.intellij.openapi.vfs.newvfs.events.VFileEvent; import com.intellij.util.ArrayUtil; import com.intellij.util.Function; import com.intellij.util.SystemProperties; import com.intellij.util.messages.MessageBusConnection; import com.intellij.util.net.HttpConfigurable; -import com.jetbrains.python.PyNames; import com.jetbrains.python.PythonHelpersLocator; import com.jetbrains.python.psi.PyExpression; import com.jetbrains.python.psi.PyListLiteralExpression; import com.jetbrains.python.psi.PyStringLiteralExpression; -import com.jetbrains.python.psi.search.PyProjectScopeBuilder; import com.jetbrains.python.remote.PyRemoteInterpreterException; import com.jetbrains.python.remote.PythonRemoteInterpreterManager; import com.jetbrains.python.remote.PythonRemoteSdkAdditionalData; @@ -154,6 +154,7 @@ public class PyPackageManagerImpl extends PyPackageManager { exceptions.add(e); } } + manager.refresh(); return exceptions; } }, progressTitle, successTitle, "Installed packages: " + PyPackageUtil.requirementsToString(requirements), @@ -171,13 +172,17 @@ public class PyPackageManagerImpl extends PyPackageManager { run(new MultiExternalRunnable() { @Override public List run(@NotNull ProgressIndicator indicator) { + final PyPackageManagerImpl manager = (PyPackageManagerImpl)PyPackageManagers.getInstance().forSdk(mySdk); try { - ((PyPackageManagerImpl)PyPackageManagers.getInstance().forSdk(mySdk)).uninstall(packages); + manager.uninstall(packages); return list(); } catch (PyExternalProcessException e) { return list(e); } + finally { + manager.refresh(); + } } }, "Uninstalling packages", "Packages uninstalled successfully", "Uninstalled packages: " + packagesString, "Uninstall packages failed"); @@ -231,10 +236,6 @@ public class PyPackageManagerImpl extends PyPackageManager { if (myListener != null) { myListener.finished(exceptions); } - VirtualFileManager.getInstance().refreshWithoutFileWatcher(false); - if (exceptions.isEmpty()) { - PythonSdkType.getInstance().setupSdkPaths(mySdk); - } final Notification notification = notificationRef.get(); if (notification != null) { notification.notify(myProject); @@ -257,6 +258,36 @@ public class PyPackageManagerImpl extends PyPackageManager { } } + @Override + public void refresh() { + final Application application = ApplicationManager.getApplication(); + application.invokeLater(new Runnable() { + @Override + public void run() { + application.runWriteAction(new Runnable() { + @Override + public void run() { + syncFiles(mySdk.getRootProvider().getFiles(OrderRootType.CLASSES)); + } + }); + PythonSdkType.getInstance().setupSdkPaths(mySdk); + clearCaches(); + } + }); + } + + private void syncFiles(VirtualFile[] files) { + // Similar to LocalFileSystemImpl.syncFiles(), VirtualFile.refresh() doesn't run update index tasks immediately, so we get stale virtual + // files when we want to bind a stub to an AST. Another option is to use VirtualFileManager.refreshWithoutFileWatcher(), but it takes + // more time to refresh the whole local file system + for (VirtualFile root : files) { + if (root instanceof NewVirtualFile && root.getFileSystem() instanceof LocalFileSystem) { + ((NewVirtualFile)root).markDirtyRecursively(); + } + } + LocalFileSystem.getInstance().refreshFiles(Arrays.asList(files), false, true, null); + } + private void installManagement(String name) throws PyExternalProcessException { final File helperFile = PythonHelpersLocator.getHelperFile(name + ".tar.gz"); @@ -496,16 +527,9 @@ public class PyPackageManagerImpl extends PyPackageManager { return null; } - public void clearCaches() { + private void clearCaches() { myPackagesCache = null; myExceptionCache = null; - VirtualFile libDir = PyProjectScopeBuilder.findLibDir(mySdk); - if (libDir != null) { - VirtualFile sitePackages = libDir.findChild(PyNames.SITE_PACKAGES); - if (sitePackages != null) { - sitePackages.refresh(true, true); - } - } } private static List list(T... xs) { diff --git a/python/src/com/jetbrains/python/packaging/ui/PyPackagesPanel.java b/python/src/com/jetbrains/python/packaging/ui/PyPackagesPanel.java index 2d9cfd281776..070403435431 100644 --- a/python/src/com/jetbrains/python/packaging/ui/PyPackagesPanel.java +++ b/python/src/com/jetbrains/python/packaging/ui/PyPackagesPanel.java @@ -501,7 +501,7 @@ public class PyPackagesPanel extends JPanel { final String description = PyPackageManagerImpl.UI.createDescription(exceptions, firstLine); packageManager.showInstallationError(myProject, "Failed to install " + name, description); } - packageManager.clearCaches(); + packageManager.refresh(); updatePackages(sdk); for (Consumer listener : myPathChangedListeners) { listener.consume(sdk);