Skip to content

Commit

Permalink
Allow clients to redefine untitled files protocol during their creati…
Browse files Browse the repository at this point in the history
…on (#1903)

Closes
https://linear.app/sourcegraph/issue/CODY-2004/bug-cody-recreates-the-file-that-was-created-by-generate-unit-tests

## Changes

Some IDEs (maybe even most IDEs except VSC) does not have notion of
unsaved files.
Keeping two different models in IDE and in the agent is problematic and
leads to hard to track errors.
It is easier to let client be honest and notify agent about real
protocol which it is using (most likely `file://` instead of
`untitled://`).

As a result that change slightly modifies behaviour of the
`openTextDocument`.
One could now call `openTextDocument` with `untitled://abc` parameter,
and as a result get a `TextDocument` which uri points to `file://abc`
(or any other path, really).

## Test plan

1. Build JetBrains with this PR using CODY_DIR env var and [this
PR](sourcegraph/cody#4841)
2. Ask cody to generate tests for some file which does not have tests
yet
3. Accept the changes
4. Delete that newly created file
5. Perform autocomplete in some other file
6. Make sure test file was not recreated
  • Loading branch information
pkukielka authored Jul 31, 2024
1 parent 1cdb753 commit 395e971
Show file tree
Hide file tree
Showing 5 changed files with 18 additions and 34 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,4 @@ kotlin.stdlib.default.dependency=false
nodeBinaries.commit=8755ae4c05fd476cd23f2972049111ba436c86d4
nodeBinaries.version=v20.12.2
cody.autocomplete.enableFormatting=true
cody.commit=280a91999947fb7829d56163d3a13f9910b0ac05
cody.commit=6443a0b6eccb4aa1442f9c5a2b09f2755a3d89da
4 changes: 2 additions & 2 deletions src/main/java/com/sourcegraph/cody/agent/CodyAgentClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public class CodyAgentClient {
@Nullable Function<TextDocumentShowParams, Boolean> onTextDocumentShow;

// Callback for the "textDocument/openUntitledDocument" request from the agent.
@Nullable Function<UntitledTextDocument, Boolean> onOpenUntitledDocument;
@Nullable Function<UntitledTextDocument, ProtocolTextDocument> onOpenUntitledDocument;

// Callback for the "workspace/edit" request from the agent.
@Nullable Function<WorkspaceEditParams, Boolean> onWorkspaceEdit;
Expand Down Expand Up @@ -108,7 +108,7 @@ public CompletableFuture<Boolean> textDocumentShow(TextDocumentShowParams params
}

@JsonRequest("textDocument/openUntitledDocument")
public CompletableFuture<Boolean> openUntitledDocument(UntitledTextDocument params) {
public CompletableFuture<ProtocolTextDocument> openUntitledDocument(UntitledTextDocument params) {
if (onOpenUntitledDocument == null) {
return CompletableFuture.failedFuture(
new Exception("No callback registered for textDocument/openUntitledDocument"));
Expand Down
12 changes: 5 additions & 7 deletions src/main/kotlin/com/sourcegraph/cody/agent/CodyAgentService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.progress.ProcessCanceledException
import com.intellij.openapi.project.Project
import com.intellij.util.net.HttpConfigurable
import com.sourcegraph.cody.agent.protocol.ProtocolTextDocument
import com.sourcegraph.cody.chat.AgentChatSessionService
import com.sourcegraph.cody.config.CodyApplicationSettings
import com.sourcegraph.cody.context.RemoteRepoSearcher
Expand Down Expand Up @@ -100,14 +101,11 @@ class CodyAgentService(private val project: Project) : Disposable {
}

agent.client.onOpenUntitledDocument = Function { params ->
val result = CompletableFuture<Boolean>()
val result = CompletableFuture<ProtocolTextDocument?>()
ApplicationManager.getApplication().invokeAndWait {
val vf = CodyEditorUtil.createFileOrScratch(project, params.uri, params.content)
if (vf == null) {
result.complete(false)
return@invokeAndWait
}
result.complete(true)
val vf =
CodyEditorUtil.createFileOrScratchFromUntitled(project, params.uri, params.content)
result.complete(if (vf == null) null else ProtocolTextDocument.fromVirtualFile(vf))
}
result.get()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import com.sourcegraph.cody.agent.protocol_extensions.Position
import com.sourcegraph.cody.agent.protocol_generated.Range
import java.awt.Point
import java.nio.file.FileSystems
import java.util.*
import java.util.Locale
import kotlin.math.max
import kotlin.math.min

Expand Down
32 changes: 9 additions & 23 deletions src/main/kotlin/com/sourcegraph/utils/CodyEditorUtil.kt
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
package com.sourcegraph.utils

import com.intellij.application.options.CodeStyle
import com.intellij.ide.scratch.ScratchFileService
import com.intellij.ide.scratch.ScratchRootType
import com.intellij.injected.editor.EditorWindow
import com.intellij.lang.Language
import com.intellij.lang.LanguageUtil
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.application.ReadAction
import com.intellij.openapi.command.WriteCommandAction
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.editor.Document
Expand All @@ -28,15 +26,13 @@ import com.intellij.openapi.util.TextRange
import com.intellij.openapi.vfs.LocalFileSystem
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.ex.temp.TempFileSystem
import com.intellij.psi.codeStyle.CommonCodeStyleSettings
import com.intellij.util.concurrency.annotations.RequiresEdt
import com.intellij.util.withScheme
import com.sourcegraph.cody.agent.protocol_extensions.*
import com.sourcegraph.cody.agent.protocol_generated.Range
import com.sourcegraph.config.ConfigUtil
import java.net.URI
import java.net.URISyntaxException
import java.util.*
import kotlin.io.path.createDirectories
import kotlin.io.path.createFile
import kotlin.io.path.exists
Expand All @@ -62,19 +58,6 @@ object CodyEditorUtil {
*/
@JvmStatic val KEY_EDITOR_WANTS_AUTOCOMPLETE = Key.create<Boolean>("cody.editorWantsAutocomplete")

/**
* @param editor given editor
* @return code style settings for the given editor, if null defaults to default app code style
* settings
*/
@JvmStatic
fun codeStyleSettings(editor: Editor): CommonCodeStyleSettings {
return ReadAction.compute<CommonCodeStyleSettings, RuntimeException> {
Optional.ofNullable(CodeStyle.getLanguageSettings(editor))
.orElse(CodeStyle.getDefaultSettings())
}
}

@JvmStatic
fun getTextRange(document: Document, range: Range): TextRange {
val start = range.start.toOffset(document)
Expand Down Expand Up @@ -216,18 +199,21 @@ object CodyEditorUtil {
}
}

fun createFileOrScratch(
fun createFileOrScratchFromUntitled(
project: Project,
uriString: String,
content: String? = null
): VirtualFile? {
try {
val uri = URI.create(uriString).withScheme("file")
if (!uri.toPath().exists()) {
uri.toPath().parent?.createDirectories()
uri.toPath().createFile()
val uri = URI.create(uriString)

val fileUri = uri.withScheme("file")
if (!fileUri.toPath().exists()) {
fileUri.toPath().parent?.createDirectories()
fileUri.toPath().createFile()
}
val vf = LocalFileSystem.getInstance().refreshAndFindFileByNioFile(uri.toPath())

val vf = LocalFileSystem.getInstance().refreshAndFindFileByNioFile(fileUri.toPath())
content?.let {
WriteCommandAction.runWriteCommandAction(project) { vf?.setBinaryContent(it.toByteArray()) }
}
Expand Down

0 comments on commit 395e971

Please sign in to comment.