Skip to content

Commit

Permalink
Merge pull request #2347 from continuedev/nate/jetbrains-updates
Browse files Browse the repository at this point in the history
JetBrains Updates
  • Loading branch information
sestinj authored Sep 22, 2024
2 parents 9a550ef + 89a02e2 commit dd17b56
Show file tree
Hide file tree
Showing 31 changed files with 395 additions and 476 deletions.
7 changes: 7 additions & 0 deletions .changes/extensions/intellij/0.0.69.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
## 0.0.69 - 2024-09-22
### Added
* Support for the "search" context provider
### Fixed
* Fixed bug where only first module would be recognized
* Improved concurrency handling to avoid freezes
* Made compatible with latest JetBrains versions
4 changes: 0 additions & 4 deletions .changes/unreleased/Added-20240915-163755.yaml

This file was deleted.

4 changes: 0 additions & 4 deletions .changes/unreleased/Fixed-20240915-163641.yaml

This file was deleted.

5 changes: 3 additions & 2 deletions .github/workflows/jetbrains-release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ jobs:
ls
echo "---"
FILENAME=`ls continue-intellij-extension-*.zip`
echo "Filename=${FILENAME}"
unzip "$FILENAME" -d content
echo "filename=${FILENAME%.????}" >> $GITHUB_OUTPUT
Expand Down Expand Up @@ -330,10 +331,10 @@ jobs:
- name: Upload logs
if: ${{ always() }}
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: core-logs-${{ matrix.platform }}-${{ matrix.arch }}
path: binary/.continue/logs/core.log
path: ~/.continue/logs/core.log

# Run tests and upload a code coverage report
test:
Expand Down
83 changes: 68 additions & 15 deletions binary/test/binary.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ import FileSystemIde from "core/util/filesystem";
import { IMessenger } from "core/util/messenger";
import { ReverseMessageIde } from "core/util/reverseMessageIde";
import fs from "fs";
import { ChildProcessWithoutNullStreams, spawn } from "node:child_process";
import {
ChildProcessWithoutNullStreams,
execSync,
spawn,
} from "node:child_process";
import path from "path";
import {
CoreBinaryMessenger,
Expand Down Expand Up @@ -59,21 +63,66 @@ describe("Test Suite", () => {

beforeAll(async () => {
const [platform, arch] = autodetectPlatformAndArch();
const binaryPath = path.join(
__dirname,
"..",
"bin",
`${platform}-${arch}`,
`continue-binary${platform === "win32" ? ".exe" : ""}`,
);
expect(fs.existsSync(binaryPath)).toBe(true);
const binaryDir = path.join(__dirname, "..", "bin", `${platform}-${arch}`);
const exe = platform === "win32" ? ".exe" : "";
const binaryPath = path.join(binaryDir, `continue-binary${exe}`);
const expectedItems = [
`continue-binary${exe}`,
`esbuild${exe}`,
"index.node",
"package.json",
"build/Release/node_sqlite3.node",
];
expectedItems.forEach((item) => {
expect(fs.existsSync(path.join(binaryDir, item))).toBe(true);
});

// Set execute permissions and remove quarantine attribute if on macOS
if (platform !== "win32") {
try {
fs.chmodSync(binaryPath, 0o755);
console.log("Execute permissions set for the binary");

if (platform === "darwin") {
const indexNodePath = path.join(binaryDir, "index.node");
const filesToUnquarantine = [binaryPath, indexNodePath];

for (const file of filesToUnquarantine) {
try {
execSync(`xattr -d com.apple.quarantine "${file}"`, {
stdio: "ignore",
});
console.log(
`Quarantine attribute removed from ${path.basename(file)}`,
);
} catch (error) {
console.warn(
`Failed to remove quarantine attribute from ${path.basename(file)}:`,
error,
);
}
}
}
} catch (error) {
console.error(
"Error setting permissions or removing quarantine:",
error,
);
}
}

if (USE_TCP) {
messenger = new CoreBinaryTcpMessenger<ToIdeProtocol, FromIdeProtocol>();
} else {
subprocess = spawn(binaryPath, {
env: { ...process.env, CONTINUE_GLOBAL_DIR },
});
try {
subprocess = spawn(binaryPath, {
env: { ...process.env, CONTINUE_GLOBAL_DIR },
});
console.log("Successfully spawned subprocess");
} catch (error) {
console.error("Error spawning subprocess:", error);
throw error;
}
messenger = new CoreBinaryMessenger<ToIdeProtocol, FromIdeProtocol>(
subprocess,
);
Expand Down Expand Up @@ -123,13 +172,17 @@ describe("Test Suite", () => {
"package.json",
"logs/core.log",
"index/autocompleteCache.sqlite",
"out/config.js",
"types/core/index.d.ts",
];

for (const file of expectedFiles) {
const missingFiles = expectedFiles.filter((file) => {
const filePath = path.join(CONTINUE_GLOBAL_DIR, file);
expect(fs.existsSync(filePath)).toBe(true);
return !fs.existsSync(filePath);
});

expect(missingFiles).toEqual([]);
if (missingFiles.length > 0) {
console.log("Missing files:", missingFiles);
}
});

Expand Down
7 changes: 3 additions & 4 deletions extensions/intellij/.run/Run Verifications.run.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<log_file alias="idea.log" path="$PROJECT_DIR$/build/idea-sandbox/system/log/idea.log" />
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalProjectPath" value="$PROJECT_DIR$/extensions/intellij" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
Expand All @@ -19,8 +19,7 @@
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2">
<option name="Gradle.BeforeRunTask" enabled="true" tasks="clean" externalProjectPath="$PROJECT_DIR$" vmOptions="" scriptParameters="" />
</method>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
4 changes: 3 additions & 1 deletion extensions/intellij/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html),
and is generated by [Changie](https://github.com/miniscruff/changie).


Pre-release Changes
## 0.0.69 - 2024-09-22
### Added
* Support for the "search" context provider
### Fixed
* Fixed bug where only first module would be recognized
* Improved concurrency handling to avoid freezes
* Made compatible with latest JetBrains versions

## 0.0.54 - 2024-07-13
### Added
Expand Down
1 change: 1 addition & 0 deletions extensions/intellij/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ dependencies {
}
implementation("com.posthog.java:posthog:1.+")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0")
// implementation("com.jetbrains.jsonSchema")
}


Expand Down
2 changes: 1 addition & 1 deletion extensions/intellij/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pluginGroup = com.github.continuedev.continueintellijextension
pluginName = continue-intellij-extension
pluginRepositoryUrl = https://github.com/continuedev/continue
# SemVer format -> https://semver.org
pluginVersion = 0.0.68
pluginVersion = 0.0.69

# Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
pluginSinceBuild = 223
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ import com.github.continuedev.continueintellijextension.listeners.ContinuePlugin
import com.github.continuedev.continueintellijextension.services.ContinueExtensionSettings
import com.github.continuedev.continueintellijextension.services.ContinuePluginService
import com.github.continuedev.continueintellijextension.services.SettingsListener
import com.github.continuedev.continueintellijextension.services.TelemetryService
import com.github.continuedev.continueintellijextension.services.TerminalActivityTrackingService
import com.github.continuedev.continueintellijextension.utils.isNotAvailable
import com.intellij.openapi.Disposable
import com.intellij.openapi.actionSystem.KeyboardShortcut
import com.intellij.openapi.application.ApplicationManager
Expand All @@ -27,18 +24,11 @@ import com.intellij.openapi.vfs.LocalFileSystem
import kotlinx.coroutines.*
import java.io.*
import java.nio.charset.StandardCharsets
import java.nio.file.Files
import java.nio.file.Paths
import javax.swing.*
import com.intellij.ide.plugins.PluginManager
import com.intellij.openapi.components.service
import com.intellij.openapi.extensions.PluginId
import com.intellij.openapi.module.ModuleManager
import com.intellij.openapi.roots.ModuleRootManager
import com.intellij.openapi.wm.ToolWindowManager
import com.intellij.openapi.wm.ex.ToolWindowManagerListener
import org.jetbrains.plugins.terminal.TerminalToolWindowFactory
import org.jetbrains.plugins.terminal.TerminalView

fun showTutorial(project: Project) {
ContinuePluginStartupActivity::class.java.getClassLoader().getResourceAsStream("continue_tutorial.py").use { `is` ->
Expand Down Expand Up @@ -85,9 +75,7 @@ class ContinuePluginStartupActivity : StartupActivity, Disposable, DumbAware {
// }
// )

ApplicationManager.getApplication().executeOnPooledThread {
initializePlugin(project)
}
initializePlugin(project)
}

private fun getPlatformSpecificKeyStroke(key: String): String {
Expand Down Expand Up @@ -182,33 +170,31 @@ class ContinuePluginStartupActivity : StartupActivity, Disposable, DumbAware {
}
})

GlobalScope.async(Dispatchers.IO) {
val listener =
ContinuePluginSelectionListener(
ideProtocolClient,
coroutineScope
)

// Reload the WebView
continuePluginService?.let { pluginService ->
val allModulePaths = ModuleManager.getInstance(project).modules
.flatMap { module -> ModuleRootManager.getInstance(module).contentRoots.map { it.path } }
.map { Paths.get(it).normalize() }
val listener =
ContinuePluginSelectionListener(
ideProtocolClient,
coroutineScope
)

val topLevelModulePaths = allModulePaths
.filter { modulePath -> allModulePaths.none { it != modulePath && modulePath.startsWith(it) } }
.map { it.toString() }
// Reload the WebView
continuePluginService?.let { pluginService ->
val allModulePaths = ModuleManager.getInstance(project).modules
.flatMap { module -> ModuleRootManager.getInstance(module).contentRoots.map { it.path } }
.map { Paths.get(it).normalize() }

pluginService.workspacePaths = topLevelModulePaths.toTypedArray()
}
val topLevelModulePaths = allModulePaths
.filter { modulePath -> allModulePaths.none { it != modulePath && modulePath.startsWith(it) } }
.map { it.toString() }

EditorFactory.getInstance().eventMulticaster.addSelectionListener(
listener,
this@ContinuePluginStartupActivity
)
pluginService.workspacePaths = topLevelModulePaths.toTypedArray()
}

val coreMessengerManager = CoreMessengerManager(project, ideProtocolClient)
EditorFactory.getInstance().eventMulticaster.addSelectionListener(
listener,
this@ContinuePluginStartupActivity
)

val coreMessengerManager = CoreMessengerManager(project, ideProtocolClient, coroutineScope)
continuePluginService.coreMessengerManager = coreMessengerManager
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import com.intellij.openapi.components.Service
import com.intellij.openapi.components.service
import com.intellij.openapi.project.Project
import com.intellij.remoteServer.util.CloudConfigurationUtil.createCredentialAttributes
import kotlinx.coroutines.CoroutineScope
import java.awt.Desktop
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
Expand All @@ -22,6 +23,8 @@ import java.net.URL

@Service
class ContinueAuthService {
private val coroutineScope = CoroutineScope(Dispatchers.IO)

companion object {
fun getInstance(): ContinueAuthService = service<ContinueAuthService>()
private const val CREDENTIALS_USER = "ContinueAuthUser"
Expand Down Expand Up @@ -61,7 +64,7 @@ class ContinueAuthService {

private fun updateRefreshToken(token: String) {
// Launch a coroutine to call the suspend function
kotlinx.coroutines.GlobalScope.launch {
coroutineScope.launch {
try {
val response = refreshToken(token)
val accessToken = response["accessToken"] as? String
Expand Down Expand Up @@ -89,7 +92,7 @@ class ContinueAuthService {

private fun setupRefreshTokenInterval() {
// Launch a coroutine to refresh the token every 30 minutes
kotlinx.coroutines.GlobalScope.launch {
coroutineScope.launch {
while (true) {
val refreshToken = getRefreshToken()
if (refreshToken != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class AutocompleteDocumentListener(private val editorManager: FileEditorManager,

// Invoke later is important, otherwise the completion will be triggered before the document is updated
// causing the old caret offset to be used
// TODO: concurrency
invokeLater {
service.triggerCompletion(editor)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class AutocompleteSpinnerWidget(project: Project): EditorBasedWidget(project), S
)

init {
Disposer.register(project, this)
updateIcon()
}

Expand All @@ -49,7 +50,7 @@ class AutocompleteSpinnerWidget(project: Project): EditorBasedWidget(project), S

override fun getTooltipText(): String? {
val enabled = service<ContinueExtensionSettings>().state.enableTabAutocomplete
return if (enabled) "Continue Autocomplete Enabled" else "Continue Autocomplete Disabled"
return if (enabled) "Continue autocomplete enabled" else "Continue autocomplete disabled"
}

override fun getClickConsumer(): Consumer<MouseEvent>? {
Expand All @@ -70,7 +71,7 @@ class AutocompleteSpinnerWidget(project: Project): EditorBasedWidget(project), S

// Update the widget
val statusBar = WindowManager.getInstance().getStatusBar(project)
statusBar.updateWidget(ID())
statusBar?.updateWidget(ID())
}

override fun install(statusBar: StatusBar) {
Expand Down
Loading

0 comments on commit dd17b56

Please sign in to comment.