in plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/cwc/editor/context/focusArea/FocusAreaContextExtractor.kt [27:159]
suspend fun extract(): FocusAreaContext? {
val editor = computeOnEdt {
FileEditorManager.getInstance(project).selectedTextEditor
} ?: return null
if (editor.document.text.isBlank()) return null
// Get 10k characters around the cursor
val (trimmedFileText, trimmedFileTextSelection) = computeOnEdt {
val (start, end) = getOffsetRangeAtCursor(MAX_LENGTH, editor)
val fileTextStartPos = editor.offsetToLogicalPosition(start)
val fileTextEndPos = editor.offsetToLogicalPosition(end)
val trimmedFileText = getTextAtOffsets(fileTextStartPos, fileTextEndPos, editor)
val trimmedFileTextSelection = UICodeSelectionRange(
start = UICodeSelectionLineRange(
row = fileTextStartPos.line,
column = fileTextStartPos.column,
),
end = UICodeSelectionLineRange(
row = fileTextEndPos.line,
column = fileTextEndPos.column,
),
)
Pair(trimmedFileText, trimmedFileTextSelection)
}
// Get user selected code or visible text area
val (codeSelection, codeSelectionRange) = computeOnEdt {
val selectionModel: SelectionModel = editor.selectionModel
val selectedText = selectionModel.selectedText
if (selectedText == null) {
// Get visible area text
val visibleArea = editor.scrollingModel.visibleArea
val startOffset = editor.xyToLogicalPosition(Point(visibleArea.x, visibleArea.y))
val endOffset = editor.xyToLogicalPosition(Point(visibleArea.x + visibleArea.width, visibleArea.y + visibleArea.height))
// Get text of visible area
val visibleAreaText = getTextAtOffsets(startOffset, endOffset, editor)
// If visible area text too big use trimmedSurroundingText
if (visibleAreaText.length > MAX_LENGTH) {
Pair(trimmedFileText, trimmedFileTextSelection)
} else {
// Ensure end line isn't beyond the end of the document
val endLine = min(endOffset.line, editor.document.lineCount - 1)
val endColumn = min(endOffset.column, visibleAreaText.lengthOfLastLine() - 1)
val codeSelectionRange = UICodeSelectionRange(
start = UICodeSelectionLineRange(
row = startOffset.line,
column = startOffset.column,
),
end = UICodeSelectionLineRange(
row = endLine,
column = endColumn,
),
)
Pair(visibleAreaText, codeSelectionRange)
}
} else if (selectedText.length > MAX_LENGTH) {
Pair(trimmedFileText, trimmedFileTextSelection)
} else {
// Use selected text ranges
val selectedStartPos = editor.offsetToLogicalPosition(selectionModel.selectionStart)
val selectedEndPos = editor.offsetToLogicalPosition(selectionModel.selectionEnd)
val codeSelectionRange = UICodeSelectionRange(
start = UICodeSelectionLineRange(
row = selectedStartPos.line,
column = selectedStartPos.column,
),
end = UICodeSelectionLineRange(
row = selectedEndPos.line,
column = selectedEndPos.column,
),
)
Pair(selectedText, codeSelectionRange)
}
}
// Retrieve <codeNames> from trimmedFileText
val fileLanguage = computeOnEdt {
languageExtractor.extractLanguageNameFromCurrentFile(editor)
}
val fileText = editor.document.text
val fileName = FileEditorManager.getInstance(project).selectedFiles.first().name
// Offset the selection range to the start of the trimmedFileText
val selectionInsideTrimmedFileTextRange = codeSelectionRange.let {
UICodeSelectionRange(
start = UICodeSelectionLineRange(
row = it.start.row - trimmedFileTextSelection.start.row,
column = it.start.column
),
end = UICodeSelectionLineRange(
row = it.end.row - trimmedFileTextSelection.start.row,
column = it.end.column
),
)
}
var codeNames: CodeNames? = null
if (fileLanguage != null) {
val extractNamesRequest = ExtractNamesRequest(
language = fileLanguage,
fileContent = fileText,
codeSelection = UICodeSelection(
selectedCode = trimmedFileText,
file = UICodeSelectionFile(
name = fileName,
range = selectionInsideTrimmedFileTextRange,
),
),
)
val requestString = ChatController.objectMapper.writeValueAsString(extractNamesRequest)
codeNames = try {
fqnWebviewAdapter?.let {
ChatController.objectMapper.readValue(it.extractNames(requestString), CodeNamesImpl::class.java)
} ?: CodeNamesImpl(simpleNames = emptyList(), fullyQualifiedNames = FullyQualifiedNames(used = emptyList()))
} catch (e: Exception) {
getLogger<FocusAreaContextExtractor>().warn(e) { "Failed to extract names from file" }
null
}
}
return FocusAreaContext(
codeSelection = codeSelection,
codeSelectionRange = selectionInsideTrimmedFileTextRange,
trimmedSurroundingFileText = trimmedFileText,
codeNames = codeNames,
)
}