mirror of
https://github.com/DaanVandenBosch/phantasmal-world.git
synced 2025-04-04 22:58:29 +08:00
Added go to symbol to ASM editor.
This commit is contained in:
parent
9494a70591
commit
2f0ebd9443
@ -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> =
|
||||
|
@ -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?,
|
||||
)
|
||||
|
@ -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>>
|
||||
}
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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() }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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() }
|
@ -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
|
||||
}
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user