Skip to content

Commit

Permalink
Adding fomratting to mulitline autocomplete (#141)
Browse files Browse the repository at this point in the history
It fixes [JetBrains: explore formatting multiline suggestions within
IntelliJ before rendering inlay
hint#72](#72)
## Test plan
* Trigger multiline autocompletion
* Change formatting style
* Trigger multiline autocompletion again and check if formatting is in
line with your settings


https://github.com/sourcegraph/jetbrains/assets/9321940/35ba1eea-7666-4474-aeaf-e953eccce8fc


<!-- All pull requests REQUIRE a test plan:
https://docs.sourcegraph.com/dev/background-information/testing_principles

Why does it matter? 

These test plans are there to demonstrate that are following industry
standards which are important or critical for our customers.
They might be read by customers or an auditor. There are meant be simple
and easy to read. Simply explain what you did to ensure
your changes are correct!

Here are a non exhaustive list of test plan examples to help you:

- Making changes on a given feature or component: 
- "Covered by existing tests" or "CI" for the shortest possible plan if
there is zero ambiguity
  - "Added new tests" 
- "Manually tested" (if non trivial, share some output, logs, or
screenshot)
- Updating docs: 
  - "previewed locally" 
  - share a screenshot if you want to be thorough
- Updating deps, that would typically fail immediately in CI if
incorrect
  - "CI" 
  - "locally tested" 
-->
  • Loading branch information
Sa1to authored Nov 23, 2023
1 parent 3d6f314 commit 016c031
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 9 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,13 @@ You can configure the plugin on three levels:
1. **Project-level** On the project level you are able to configure your default account, default branch name and remote url replacements
2. **Application-level** All other settings are stored here

## System Properties

### Autocomplete system properties
In order to disable newly introduced features we are giving an option to disable them via system properties:

1. **Disable formatting autocomplete elements** `cody.autocomplete.enableFormatting=false`

## Managing Custom Keymaps

![A screenshot of the JetBrains preferences panel inside the Keymap tab](docs/keymaps.png)
Expand Down
3 changes: 3 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,9 @@ tasks {
systemProperty("cody-agent.trace-path", "$buildDir/sourcegraph/cody-agent-trace.json")
systemProperty("cody-agent.directory", buildCodyDir.parent)
systemProperty("sourcegraph.verbose-logging", "true")
systemProperty(
"cody.autocomplete.enableFormatting",
project.property("cody.autocomplete.enableFormatting") ?: "true")
}

runPluginVerifier {
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ gradleVersion=8.1.1
# suppress inspection "UnusedProperty"
kotlin.stdlib.default.dependency=false
# See https://docs.gradle.org/current/userguide/build_cache.html#sec:build_cache_configure
org.gradle.caching=true
cody.autocomplete.enableFormatting=true
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import com.sourcegraph.utils.CodyEditorUtil.getTextRange
import com.sourcegraph.utils.CodyEditorUtil.isCommandExcluded
import com.sourcegraph.utils.CodyEditorUtil.isEditorValidForAutocomplete
import com.sourcegraph.utils.CodyEditorUtil.isImplicitAutocompleteEnabledForEditor
import com.sourcegraph.utils.CodyFormatter
import difflib.Delta
import difflib.DiffUtils
import difflib.Patch
Expand Down Expand Up @@ -322,7 +323,7 @@ class CodyAutocompleteManager {
clearAutocompleteSuggestions(editor)
currentAutocompleteTelemetry?.markCompletionDisplayed()

displayAgentAutocomplete(editor, offset, items, inlayModel, triggerKind, lookupString)
displayAgentAutocomplete(editor, offset, items, inlayModel, triggerKind)
}
}

Expand All @@ -338,8 +339,22 @@ class CodyAutocompleteManager {
items: List<InlineAutocompleteItem>,
inlayModel: InlayModel,
triggerKind: InlineCompletionTriggerKind,
lookupString: String?,
) {
val project = editor.project
if (project != null && System.getProperty("cody.autocomplete.enableFormatting") != "false") {
items.map { item ->
if (item.insertText.lines().size > 1) {
item.insertText =
item.insertText.lines()[0] +
CodyFormatter.formatStringBasedOnDocument(
item.insertText.lines().drop(1).joinToString(separator = "\n"),
project,
editor.document,
offset)
}
}
}

val defaultItem = items.firstOrNull() ?: return
val range = getTextRange(editor.document, defaultItem.range)
val originalText = editor.document.getText(range)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,7 @@ class CycleCodyAutocompleteActionHandler(private val cycleDirection: CycleDirect
CodyAutocompleteManager.instance.let {
it.clearAutocompleteSuggestions(editor)
it.displayAgentAutocomplete(
editor,
caret.offset,
newItems,
editor.inlayModel,
InlineCompletionTriggerKind.INVOKE,
null)
editor, caret.offset, newItems, editor.inlayModel, InlineCompletionTriggerKind.INVOKE)
}
autocompleteItemsCache[cacheKey] = newItems
}
Expand Down
47 changes: 47 additions & 0 deletions src/main/kotlin/com/sourcegraph/utils/CodyFormatter.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.sourcegraph.utils

import com.intellij.openapi.editor.Document
import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiFileFactory
import com.intellij.psi.codeStyle.CodeStyleManager
import com.intellij.refactoring.suggested.endOffset

class CodyFormatter {
companion object {
/**
* Formatting used to format inlay text inserted by Cody, based on the surrounding code style in
* the document.
*/
fun formatStringBasedOnDocument(
originalText: String,
project: Project,
document: Document,
offset: Int
): String {

val appendedString =
document.text.substring(0, offset) + originalText + document.text.substring(offset)

val file = FileDocumentManager.getInstance().getFile(document)!!
val psiFile =
PsiFileFactory.getInstance(project)
.createFileFromText("TEMP", file.fileType, appendedString)

val codeStyleManager = CodeStyleManager.getInstance(project)

var i = offset
var startRefactoringPosition = offset
while ((document.text.elementAt(i - 1) == ' ' ||
document.text.elementAt(i - 1) == '\n' ||
document.text.elementAt(i - 1) == '\t') && i > 0) {
startRefactoringPosition = i
i--
}
var endOffset = offset + psiFile.endOffset - document.textLength
codeStyleManager.reformatText(psiFile, startRefactoringPosition, endOffset)
endOffset = offset + psiFile.endOffset - document.textLength
return psiFile.text.substring(startRefactoringPosition, endOffset)
}
}
}

0 comments on commit 016c031

Please sign in to comment.