diff --git a/codegpt-treesitter/src/main/java/ee/carlrobert/codegpt/treesitter/CodeCompletionParserFactory.java b/codegpt-treesitter/src/main/java/ee/carlrobert/codegpt/treesitter/CodeCompletionParserFactory.java index a957ed7d..d7efd2c4 100644 --- a/codegpt-treesitter/src/main/java/ee/carlrobert/codegpt/treesitter/CodeCompletionParserFactory.java +++ b/codegpt-treesitter/src/main/java/ee/carlrobert/codegpt/treesitter/CodeCompletionParserFactory.java @@ -36,9 +36,13 @@ import org.treesitter.TreeSitterYaml; public class CodeCompletionParserFactory { - public static CodeCompletionParser getParserForFileExtension(String extension) - throws IllegalArgumentException { - return new CodeCompletionParser(getLanguageForExtension(extension)); + public static CodeCompletionParser getParserForFileExtension(String extension) { + var language = getLanguageForExtension(extension); + if (language == null) { + return null; + } + + return new CodeCompletionParser(language); } private static TSLanguage getLanguageForExtension(String extension) { @@ -75,7 +79,7 @@ public class CodeCompletionParserFactory { case "svelte" -> new TreeSitterSvelte(); case "swift" -> new TreeSitterSwift(); case "yml", "yaml" -> new TreeSitterYaml(); - default -> throw new IllegalArgumentException("Unsupported file extension: " + extension); + default -> null; }; } } diff --git a/src/main/kotlin/ee/carlrobert/codegpt/codecompletions/CodeCompletionRequestFactory.kt b/src/main/kotlin/ee/carlrobert/codegpt/codecompletions/CodeCompletionRequestFactory.kt index 58f38297..f71d4570 100644 --- a/src/main/kotlin/ee/carlrobert/codegpt/codecompletions/CodeCompletionRequestFactory.kt +++ b/src/main/kotlin/ee/carlrobert/codegpt/codecompletions/CodeCompletionRequestFactory.kt @@ -24,7 +24,7 @@ import java.nio.charset.StandardCharsets object CodeCompletionRequestFactory { - private const val MAX_TOKENS = 80 + private const val MAX_TOKENS = 128 @JvmStatic fun buildCodeGPTRequest(details: InfillRequest): CodeCompletionRequest { diff --git a/src/main/kotlin/ee/carlrobert/codegpt/codecompletions/InfillRequestUtil.kt b/src/main/kotlin/ee/carlrobert/codegpt/codecompletions/InfillRequestUtil.kt index b793c549..aea72abc 100644 --- a/src/main/kotlin/ee/carlrobert/codegpt/codecompletions/InfillRequestUtil.kt +++ b/src/main/kotlin/ee/carlrobert/codegpt/codecompletions/InfillRequestUtil.kt @@ -4,14 +4,17 @@ import com.intellij.codeInsight.inline.completion.InlineCompletionRequest import com.intellij.openapi.application.readAction import com.intellij.openapi.components.service import com.intellij.openapi.diagnostic.thisLogger -import com.intellij.openapi.fileEditor.FileEditorManager +import com.intellij.openapi.diff.impl.patch.IdeaTextPatchBuilder +import com.intellij.openapi.diff.impl.patch.UnifiedDiffWriter import com.intellij.openapi.vcs.VcsException +import com.intellij.openapi.vcs.changes.ChangeListManager import com.intellij.refactoring.suggested.startOffset import ee.carlrobert.codegpt.EncodingManager import ee.carlrobert.codegpt.codecompletions.psi.CompletionContextService import ee.carlrobert.codegpt.codecompletions.psi.readText import ee.carlrobert.codegpt.settings.configuration.ConfigurationSettings import ee.carlrobert.codegpt.util.GitUtil +import java.io.StringWriter object InfillRequestUtil { private val logger = thisLogger() @@ -30,22 +33,25 @@ object InfillRequestUtil { ) val project = request.editor.project ?: return infillRequestBuilder.build() - val repository = GitUtil.getProjectRepository(project) - if (repository != null && service().state.codeCompletionSettings.gitDiffEnabled) { - try { - val unstagedDiff = GitUtil.getUnstagedDiff(project, repository) - if (unstagedDiff.isNotEmpty()) { - val openedEditorFileNames = - FileEditorManager.getInstance(project).openFiles.map { it.name } - val additionalContext = unstagedDiff - .filter { - it.fileName != request.file.virtualFile.name && it.fileName in openedEditorFileNames - } - .joinToString("\n") { "${it.fileName}\n${it.content}" } + if (service().state.codeCompletionSettings.gitDiffEnabled) { + GitUtil.getProjectRepository(project)?.let { repository -> + try { + val repoRootPath = repository.root.toNioPath() + val changes = ChangeListManager.getInstance(project).allChanges + .sortedBy { it.virtualFile?.timeStamp } + val patches = IdeaTextPatchBuilder.buildPatch( + project, changes, repoRootPath, false, true + ) + val diffWriter = StringWriter() + UnifiedDiffWriter.write( + null, repoRootPath, patches, diffWriter, "\n\n", null, null + ) + val additionalContext = + diffWriter.toString().cleanDiff().truncateText(1024, false) infillRequestBuilder.additionalContext(additionalContext) + } catch (e: VcsException) { + logger.error("Failed to get git context", e) } - } catch (e: VcsException) { - logger.error("Failed to get git context", e) } } @@ -56,6 +62,18 @@ object InfillRequestUtil { return infillRequestBuilder.build() } + private fun String.cleanDiff(showContext: Boolean = false): String = + lineSequence() + .filterNot { line -> + line.startsWith("index ") || + line.startsWith("diff --git") || + line.startsWith("---") || + line.startsWith("+++") || + line.startsWith("===") || + (!showContext && line.startsWith(" ")) + } + .joinToString("\n") + private fun getInfillContext( request: InlineCompletionRequest, caretOffset: Int diff --git a/src/main/kotlin/ee/carlrobert/codegpt/util/GitUtil.kt b/src/main/kotlin/ee/carlrobert/codegpt/util/GitUtil.kt index 63fc04ea..ff852c6f 100644 --- a/src/main/kotlin/ee/carlrobert/codegpt/util/GitUtil.kt +++ b/src/main/kotlin/ee/carlrobert/codegpt/util/GitUtil.kt @@ -17,41 +17,6 @@ object GitUtil { private val logger = thisLogger() - @Throws(VcsException::class) - @JvmStatic - fun getUnstagedDiff( - project: Project, - gitRepository: GitRepository, - filePaths: List = emptyList(), - ): List { - val handler = GitLineHandler(project, gitRepository.root, GitCommand.DIFF) - handler.addParameters( - "--unified=1", - "--diff-filter=AM", - "--no-prefix", - "--no-color", - ) - - filePaths.forEach { path -> - handler.addParameters(path) - } - - return Git.getInstance().runCommand(handler).outputAsJoinedString - .split("(?=(diff --git [^\n]+))".toRegex()) - .filter { it.isNotEmpty() } - .map { diffLine -> - val lines = diffLine.lines() - val fileName = lines.first().split(" ").last().substringAfterLast("/") - val content = lines - .filter { line -> line.isNotEmpty() && !line.startsWith("+++") && !line.startsWith("---") } - .joinToString("\n") - GitDiffDetails(fileName, content) - } - .filter { it.content.isNotEmpty() } - } - - data class GitDiffDetails(val fileName: String, val content: String) - @Throws(VcsException::class) @JvmStatic fun getProjectRepository(project: Project): GitRepository? { diff --git a/src/test/kotlin/ee/carlrobert/codegpt/codecompletions/CodeCompletionServiceTest.kt b/src/test/kotlin/ee/carlrobert/codegpt/codecompletions/CodeCompletionServiceTest.kt index 9635805a..9a0b2a52 100644 --- a/src/test/kotlin/ee/carlrobert/codegpt/codecompletions/CodeCompletionServiceTest.kt +++ b/src/test/kotlin/ee/carlrobert/codegpt/codecompletions/CodeCompletionServiceTest.kt @@ -82,7 +82,7 @@ class CodeCompletionServiceTest : IntegrationTest() { assertThat(request.method).isEqualTo("POST") assertThat(request.body) .extracting("model", "prompt", "suffix", "max_tokens") - .containsExactly("gpt-3.5-turbo-instruct", prefix, suffix, 80) + .containsExactly("gpt-3.5-turbo-instruct", prefix, suffix, 128) listOf( jsonMapResponse("choices", jsonArray(jsonMap("text", "ublic "))), jsonMapResponse("choices", jsonArray(jsonMap("text", "void"))),