-
Notifications
You must be signed in to change notification settings - Fork 9
/
CompletionManager.kt
85 lines (71 loc) · 2.71 KB
/
CompletionManager.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package org.beeender.comradeneovim.completion
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.diagnostic.Logger
import org.beeender.comradeneovim.buffer.SyncBufferManager
import org.beeender.neovim.annotation.RequestHandler
import org.beeender.neovim.rpc.Request
private val log = Logger.getInstance(SyncBufferManager::class.java)
class CompletionManager(private val bufManager: SyncBufferManager) {
private class Results(@Volatile var isFinished: Boolean = false) {
private var candidates = mutableListOf<Map<String, String>>()
@Synchronized
fun add(candidate: Candidate) {
candidates.add(candidate.toMap())
}
@Synchronized
private fun retrieve() : List<Map<String, String>> {
val ret = candidates.toList()
candidates.clear()
return ret
}
fun toResponseArgs() : Map<Any, Any> {
return mapOf( "is_finished" to isFinished,
"candidates" to retrieve())
}
companion object {
val EMPTY = Results(true)
}
}
@Volatile
private var results: Results = Results.EMPTY
@RequestHandler("comrade_complete")
fun intellijComplete(req: Request) : Map<Any, Any> {
val map = req.args.first() as Map<*, *>
if (map["new_request"] as Boolean) {
val tmpResults = Results()
results = tmpResults
ApplicationManager.getApplication().invokeLater {
try {
doComplete(req, tmpResults)
}
catch (t : Throwable) {
log.warn("Completion failed.", t)
}
finally {
tmpResults.isFinished = true
}
}
}
return results.toResponseArgs()
}
private fun doComplete(req: Request, results: Results) {
val map = req.args.first() as Map<*, *>
val bufId = map["buf_id"] as Int
val row = map["row"] as Int
val col = map["col"] as Int
val syncedBuf = bufManager.findBufferById(bufId) ?: throw IllegalStateException()
syncedBuf.moveCaretToPosition(row, col)
// We need the real editor instead of the delegate here since the completion needs caret.
val editor = syncedBuf.editor.editor
val handler = CodeCompletionHandler {
it.forEach { lookupElement ->
log.debug("performCompletion: $lookupElement")
val can = Candidate(lookupElement)
if (can.valuable) {
results.add(can)
}
}
}
handler.invokeCompletion(syncedBuf.project, editor)
}
}