Added go to symbol to ASM editor.

This commit is contained in:
Daan Vanden Bosch 2021-04-24 13:19:19 +02:00
parent 9494a70591
commit 2f0ebd9443
9 changed files with 151 additions and 23 deletions

View File

@ -112,6 +112,9 @@ class AssemblyWorker(private val sendMessage: (ServerMessage) -> Unit) {
is Request.GetDefinition ->
getDefinition(message.id, message.lineNo, message.col)
is Request.GetLabels ->
getLabels(message.id)
}
}
@ -448,18 +451,23 @@ class AssemblyWorker(private val sendMessage: (ServerMessage) -> Unit) {
.filter { label in it.labels }
.mapNotNull { segment ->
val labelIdx = segment.labels.indexOf(label)
segment.srcLoc.labels.getOrNull(labelIdx)?.toAsmRange()
}
.toList()
segment.srcLoc.labels.getOrNull(labelIdx)?.let { labelSrcLoc ->
AsmRange(
startLineNo = labelSrcLoc.lineNo,
startCol = labelSrcLoc.col,
endLineNo = labelSrcLoc.lineNo,
endCol = labelSrcLoc.col + labelSrcLoc.len,
)
private fun getLabels(requestId: Int) {
val result = bytecodeIr.segments.asSequence()
.flatMap { segment ->
segment.labels.mapIndexed { labelIdx, label ->
val range = segment.srcLoc.labels.getOrNull(labelIdx)?.toAsmRange()
Label(name = label, range)
}
}
.toList()
sendMessage(Response.GetLabels(requestId, result))
}
private fun positionInside(lineNo: Int, col: Int, srcLoc: SrcLoc?): Boolean =
if (srcLoc == null) {
false
@ -470,6 +478,14 @@ class AssemblyWorker(private val sendMessage: (ServerMessage) -> Unit) {
@Suppress("RedundantNullableReturnType") // Can return undefined.
private fun getLine(lineNo: Int): String? = asm[lineNo - 1]
private fun SrcLoc.toAsmRange(): AsmRange =
AsmRange(
startLineNo = lineNo,
startCol = col,
endLineNo = lineNo,
endCol = col + len,
)
companion object {
private val KEYWORD_REGEX = Regex("""^\s*\.[a-z]+${'$'}""")
private val KEYWORD_SUGGESTIONS: List<CompletionItem> =

View File

@ -48,6 +48,9 @@ sealed class Request : ClientMessage() {
@Serializable
class GetDefinition(override val id: Int, val lineNo: Int, val col: Int) : Request()
@Serializable
class GetLabels(override val id: Int) : Request()
}
@Serializable
@ -98,6 +101,12 @@ sealed class Response<T> : ServerMessage() {
override val id: Int,
override val result: List<AsmRange>,
) : Response<List<AsmRange>>()
@Serializable
class GetLabels(
override val id: Int,
override val result: List<Label>,
) : Response<List<Label>>()
}
@Serializable
@ -162,3 +171,9 @@ class AssemblyProblem(
val col: Int,
val len: Int,
)
@Serializable
class Label(
val name: Int,
val range: AsmRange?,
)

View File

@ -49,6 +49,11 @@ external fun registerDefinitionProvider(
*/
external fun registerHoverProvider(languageId: String, provider: HoverProvider): IDisposable
external fun registerDocumentSymbolProvider(
languageId: String,
provider: DocumentSymbolProvider,
): IDisposable
external interface CommentRule {
var lineComment: String?
get() = definedExternally
@ -669,3 +674,56 @@ external interface DefinitionProvider {
token: CancellationToken,
): Promise<Array<LocationLink>?>
}
external enum class SymbolKind {
File /* = 0 */,
Module /* = 1 */,
Namespace /* = 2 */,
Package /* = 3 */,
Class /* = 4 */,
Method /* = 5 */,
Property /* = 6 */,
Field /* = 7 */,
Constructor /* = 8 */,
Enum /* = 9 */,
Interface /* = 10 */,
Function /* = 11 */,
Variable /* = 12 */,
Constant /* = 13 */,
String /* = 14 */,
Number /* = 15 */,
Boolean /* = 16 */,
Array /* = 17 */,
Object /* = 18 */,
Key /* = 19 */,
Null /* = 20 */,
EnumMember /* = 21 */,
Struct /* = 22 */,
Event /* = 23 */,
Operator /* = 24 */,
TypeParameter /* = 25 */
}
external enum class SymbolTag {
Deprecated /* = 1 */
}
external interface DocumentSymbol {
var name: String
var detail: String
var kind: SymbolKind
var tags: Array<SymbolTag>
var containerName: String?
var range: IRange
var selectionRange: IRange
var children: Array<DocumentSymbol>?
}
external interface DocumentSymbolProvider {
val displayName: String?
fun provideDocumentSymbols(
model: ITextModel,
token: CancellationToken,
): Promise<Array<DocumentSymbol>>
}

View File

@ -66,6 +66,9 @@ class AsmAnalyser {
suspend fun getDefinition(lineNo: Int, col: Int): List<AsmRange> =
sendRequest { id -> Request.GetDefinition(id, lineNo, col) }
suspend fun getLabels(): List<Label> =
sendRequest { id -> Request.GetLabels(id) }
private suspend fun <T> sendRequest(createRequest: (id: Int) -> Request): T {
val id = nextRequestId.getAndIncrement()

View File

@ -17,16 +17,9 @@ class AsmDefinitionProvider(private val analyser: AsmAnalyser) : DefinitionProvi
val defs = analyser.getDefinition(position.lineNumber, position.column)
Array(defs.size) {
val def = defs[it]
obj {
uri = model.uri
range = obj {
startLineNumber = def.startLineNo
startColumn = def.startCol
endLineNumber = def.endLineNo
endColumn = def.endCol
}
range = defs[it].toIRange()
}
}
}

View File

@ -0,0 +1,32 @@
package world.phantasmal.web.questEditor.asm.monaco
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.promise
import world.phantasmal.web.externals.monacoEditor.CancellationToken
import world.phantasmal.web.externals.monacoEditor.DocumentSymbol
import world.phantasmal.web.externals.monacoEditor.DocumentSymbolProvider
import world.phantasmal.web.externals.monacoEditor.ITextModel
import world.phantasmal.web.questEditor.asm.AsmAnalyser
import world.phantasmal.webui.obj
import kotlin.js.Promise
class AsmDocumentSymbolProvider(private val asmAnalyser: AsmAnalyser) : DocumentSymbolProvider {
override val displayName: String? = null
override fun provideDocumentSymbols(
model: ITextModel,
token: CancellationToken
): Promise<Array<DocumentSymbol>> =
GlobalScope.promise {
val labels = asmAnalyser.getLabels()
Array(labels.size) { index ->
val label = labels[index]
obj {
name = label.name.toString()
label.range?.let { range = it.toIRange() }
}
}
}
}

View File

@ -1,7 +0,0 @@
package world.phantasmal.web.questEditor.asm.monaco
import world.phantasmal.core.disposable.Disposable
import world.phantasmal.core.disposable.disposable
import world.phantasmal.web.externals.monacoEditor.IDisposable
fun IDisposable.toDisposable(): Disposable = disposable { dispose() }

View File

@ -0,0 +1,18 @@
package world.phantasmal.web.questEditor.asm.monaco
import world.phantasmal.core.disposable.Disposable
import world.phantasmal.core.disposable.disposable
import world.phantasmal.web.externals.monacoEditor.IDisposable
import world.phantasmal.web.externals.monacoEditor.IRange
import world.phantasmal.web.shared.messages.AsmRange
import world.phantasmal.webui.obj
fun IDisposable.toDisposable(): Disposable = disposable { dispose() }
fun AsmRange.toIRange(): IRange =
obj {
startLineNumber = startLineNo
startColumn = startCol
endLineNumber = endLineNo
endColumn = endCol
}

View File

@ -171,7 +171,7 @@ class AsmStore(
registerSignatureHelpProvider(ASM_LANG_ID, AsmSignatureHelpProvider(asmAnalyser))
registerHoverProvider(ASM_LANG_ID, AsmHoverProvider(asmAnalyser))
registerDefinitionProvider(ASM_LANG_ID, AsmDefinitionProvider(asmAnalyser))
// TODO: Add symbol provider for go to symbol for labels.
registerDocumentSymbolProvider(ASM_LANG_ID, AsmDocumentSymbolProvider(asmAnalyser))
// TODO: Add semantic highlighting with registerDocumentSemanticTokensProvider (or
// registerDocumentRangeSemanticTokensProvider?).
// Enable when calling editor.create with 'semanticHighlighting.enabled': true.