Repository: intellij-rust/intellij-rust
Issue: Downloading debugger fails: Total weight must be a positive number: 0

## Environment

* **IntelliJ Rust plugin version:** 0.3.128.3278-202
* **Rust toolchain version:** 1.42.0-x86_64-unknown-linux-gnu
* **IDE name and version:** IntelliJ IDEA 2020.2  Build #IU-202.6397.94
* **Operating system:** Linux 5.7.11-arch1-1

## Problem description

Downloading the debugger fails.

Log:
```
2020-08-12 11:53:01,687 [  28457]  ERROR - pplication.impl.LaterInvocator - Total weight must be a positive number: 0 
java.lang.IllegalArgumentException: Total weight must be a positive number: 0
	at com.intellij.util.progress.ConcurrentTasksProgressManager.<init>(ConcurrentTasksProgressManager.java:24)
	at com.intellij.util.download.impl.FileDownloaderImpl.download(FileDownloaderImpl.java:201)
	at org.rust.debugger.RsDebuggerToolchainService.downloadAndUnarchive(RsDebuggerToolchainService.kt:146)
	at org.rust.debugger.RsDebuggerToolchainService.downloadDebuggerSynchronously(RsDebuggerToolchainService.kt:95)
	at org.rust.debugger.RsDebuggerToolchainService.access$downloadDebuggerSynchronously(RsDebuggerToolchainService.kt:34)
	at org.rust.debugger.RsDebuggerToolchainService$downloadDebugger$result$1.compute(RsDebuggerToolchainService.kt:67)
	at org.rust.debugger.RsDebuggerToolchainService$downloadDebugger$result$1.compute(RsDebuggerToolchainService.kt:34)
	at com.intellij.openapi.progress.impl.CoreProgressManager$1.run(CoreProgressManager.java:245)
	at com.intellij.openapi.progress.impl.CoreProgressManager$TaskRunnable.run(CoreProgressManager.java:935)
	at com.intellij.openapi.progress.impl.CoreProgressManager$4.run(CoreProgressManager.java:490)
	at com.intellij.openapi.progress.impl.ProgressRunner.lambda$new$0(ProgressRunner.java:79)
	at com.intellij.openapi.progress.impl.ProgressRunner.lambda$submit$3(ProgressRunner.java:235)
	at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$runProcess$2(CoreProgressManager.java:170)
	at com.intellij.openapi.progress.impl.CoreProgressManager.registerIndicatorAndRun(CoreProgressManager.java:629)
	at com.intellij.openapi.progress.impl.CoreProgressManager.executeProcessUnderProgress(CoreProgressManager.java:581)
	at com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:60)
	at com.intellij.openapi.progress.impl.CoreProgressManager.runProcess(CoreProgressManager.java:157)
	at com.intellij.openapi.progress.impl.ProgressRunner.lambda$submit$4(ProgressRunner.java:235)
	at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1700)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1$1.run(Executors.java:668)
	at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1$1.run(Executors.java:665)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1.run(Executors.java:665)
	at java.base/java.lang.Thread.run(Thread.java:834)
2020-08-12 11:53:01,689 [  28459]  ERROR - pplication.impl.LaterInvocator - IntelliJ IDEA 2020.2  Build #IU-202.6397.94 
2020-08-12 11:53:01,689 [  28459]  ERROR - pplication.impl.LaterInvocator - JDK: 11.0.7; VM: OpenJDK 64-Bit Server VM; Vendor: JetBrains s.r.o. 
2020-08-12 11:53:01,689 [  28459]  ERROR - pplication.impl.LaterInvocator - OS: Linux 
2020-08-12 11:53:01,690 [  28460]  ERROR - pplication.impl.LaterInvocator - Plugin to blame: Rust version: 0.3.128.3278-202 
2020-08-12 11:53:01,690 [  28460]  ERROR - pplication.impl.LaterInvocator - Last Action: Debug 
```


## Steps to reproduce

1. Click "debug" icon
2. Prompt about downloading debugger appears, click "download"
3. Debug icon goes grey, nothing happens

Changed files:
debugger/src/test/kotlin/org/rust/debugger/RsDebuggerToolchainServiceTest.kt, debugger/src/main/kotlin/org/rust/debugger/RsDebuggerToolchainService.kt

diff --git a/debugger/src/main/kotlin/org/rust/debugger/RsDebuggerToolchainService.kt b/debugger/src/main/kotlin/org/rust/debugger/RsDebuggerToolchainService.kt
index cbd9179b7..3d8c1ed6e 100644
--- a/debugger/src/main/kotlin/org/rust/debugger/RsDebuggerToolchainService.kt
+++ b/debugger/src/main/kotlin/org/rust/debugger/RsDebuggerToolchainService.kt
@@ -5,6 +5,7 @@
 
 package org.rust.debugger
 
+import com.google.common.annotations.VisibleForTesting
 import com.intellij.notification.Notification
 import com.intellij.notification.NotificationType
 import com.intellij.notification.Notifications
@@ -121,30 +122,18 @@ class RsDebuggerToolchainService {
         val service = DownloadableFileService.getInstance()
 
         val lldbDir = lldbPath().toFile()
+        lldbDir.deleteRecursively()
 
-        val versions = loadLLDBVersions()
-        val descriptions = mutableListOf<DownloadableFileDescription>()
-        var cleanDebuggerDir = false
-
-        fun addFileDescriptorIfNeeded(propertyName: String, url: String) {
-            val version = versions[propertyName]?.toString()
-            if (version != fileNameWithoutExtension(url)) {
-                descriptions += service.createFileDescription(url)
-                cleanDebuggerDir = true
-            }
-        }
-
-        addFileDescriptorIfNeeded(LLDB_FRAMEWORK_PROPERTY_NAME, lldbFrameworkUrl)
-        addFileDescriptorIfNeeded(LLDB_FRONTEND_PROPERTY_NAME, lldbFrontendUrl)
-
-        if (cleanDebuggerDir) {
-            lldbDir.deleteRecursively()
-        }
+        val descriptions = listOf(
+            service.createFileDescription(lldbFrameworkUrl),
+            service.createFileDescription(lldbFrontendUrl)
+        )
 
         val downloader = service.createDownloader(descriptions, "Debugger downloading")
         val downloadDirectory = downloadPath().toFile()
         val downloadResults = downloader.download(downloadDirectory)
 
+        val versions = Properties()
         for (result in downloadResults) {
             val downloadUrl = result.second.downloadUrl
             val propertyName = if (downloadUrl == lldbFrameworkUrl) LLDB_FRAMEWORK_PROPERTY_NAME else LLDB_FRONTEND_PROPERTY_NAME
@@ -168,7 +157,8 @@ class RsDebuggerToolchainService {
         return url.substringAfterLast("/").removeSuffix(".zip").removeSuffix(".tar.gz")
     }
 
-    private fun loadLLDBVersions(): Properties {
+    @VisibleForTesting
+    fun loadLLDBVersions(): Properties {
         val versions = Properties()
         val versionsFile = lldbPath().resolve(LLDB_VERSIONS).toFile()
 
@@ -183,7 +173,8 @@ class RsDebuggerToolchainService {
         return versions
     }
 
-    private fun saveLLDBVersions(versions: Properties) {
+    @VisibleForTesting
+    fun saveLLDBVersions(versions: Properties) {
         try {
             versions.store(lldbPath().resolve(LLDB_VERSIONS).toFile().bufferedWriter(), "")
         } catch (e: IOException) {
@@ -196,8 +187,8 @@ class RsDebuggerToolchainService {
 
         private const val LLDB_VERSIONS: String = "versions.properties"
 
-        private const val LLDB_FRONTEND_PROPERTY_NAME = "lldbFrontend"
-        private const val LLDB_FRAMEWORK_PROPERTY_NAME = "lldbFramework"
+        const val LLDB_FRONTEND_PROPERTY_NAME = "lldbFrontend"
+        const val LLDB_FRAMEWORK_PROPERTY_NAME = "lldbFramework"
 
         const val RUST_DEBUGGER_GROUP_ID = "Rust Debugger"
 
diff --git a/debugger/src/test/kotlin/org/rust/debugger/RsDebuggerToolchainServiceTest.kt b/debugger/src/test/kotlin/org/rust/debugger/RsDebuggerToolchainServiceTest.kt
index 032480af2..b0e8bcc09 100644
--- a/debugger/src/test/kotlin/org/rust/debugger/RsDebuggerToolchainServiceTest.kt
+++ b/debugger/src/test/kotlin/org/rust/debugger/RsDebuggerToolchainServiceTest.kt
@@ -27,14 +27,35 @@ class RsDebuggerToolchainServiceTest : RsTestBase() {
         super.tearDown()
     }
 
-    fun `test lldb loading`() {
+    fun `test lldb loading and update`() {
         val toolchainService = RsDebuggerToolchainService.getInstance()
         assertEquals(LLDBStatus.NeedToDownload, toolchainService.getLLDBStatus())
 
-        val result = toolchainService.downloadDebugger()
+        downloadDebugger()
+
+        val version = toolchainService.loadLLDBVersions()
+        version[RsDebuggerToolchainService.LLDB_FRONTEND_PROPERTY_NAME] = "lldbfrontend-1234567890-mac-x64"
+        toolchainService.saveLLDBVersions(version)
+
+        assertEquals(LLDBStatus.NeedToUpdate, toolchainService.getLLDBStatus(lldbDir?.absolutePath))
+
+        downloadDebugger()
+    }
 
+    private fun downloadDebugger() {
+        val toolchainService = RsDebuggerToolchainService.getInstance()
+        val result = toolchainService.downloadDebugger()
         check(result is RsDebuggerToolchainService.DownloadResult.Ok) { "Failed to load debugger" }
         lldbDir = result.lldbDir
-        check(toolchainService.getLLDBStatus(result.lldbDir.absolutePath) is LLDBStatus.Binaries)
+        val lldbStatus = toolchainService.getLLDBStatus(result.lldbDir.absolutePath)
+        check(lldbStatus is LLDBStatus.Binaries) {
+            "Unexpected lldb status after downloading: $lldbStatus"
+        }
+
+        fun checkFileExist(file: File) {
+            check(file.exists()) { "Failed to find `${file.absoluteFile}`" }
+        }
+        checkFileExist(lldbStatus.frontendFile)
+        checkFileExist(lldbStatus.frameworkFile)
     }
 }