#viewer/common/tokens

    Binary token values and the contiguous syntactic store shared by model tokenization, view-line projection, tokenized Markdown, and HTML rendering.

    A rendered line can carry hundreds of tokens, and a document can carry hundreds of thousands of lines. Nothing here allocates a struct per token: one token is two UInt words in a flat array, and every read is an index computation.

    #Public boundary

    The public callable surface is consumer-driven. Every public value or operation in pkg.generated.mbti has a non-test cross-package caller. Representation details, full-versus-sliced variants, metadata decoders used only inside this package, and conformance-only helpers are private. TokenMetadata(UInt) remains the deliberate scalar-construction boundary introduced by the typed-metadata port. LineTokens deliberately retains derive(Debug) for diagnostics even though production code does not invoke it. Its promoted to_repr convenience method is deprecated and hidden in extends.mbt; callers use Debug through the trait or Repr(value). No future-only export is currently reserved; if one is deliberately staged later, it belongs in exports.mbt until a production caller lands.

    classDiagram direction TB class TokenMetadata { <<typed scalar>> +TokenMetadata(raw) TokenMetadata +to_uint() UInt +get_class_name() String } class LineTokens { <<opaque>> +LineTokens(words, text, codec) LineTokens +convert_to_end_offset(words, text_length) +default_token_metadata() TokenMetadata +get_count() Int +get_line_content() String +get_metadata(index) TokenMetadata +get_start_offset(index) Int +inflate() ViewLineTokens +slice_and_inflate(start, end, delta) ViewLineTokens +with_inserted(tokens) LineTokens } class ViewLineTokens { <<opaque full-or-sliced view>> +get_count() Int +get_line_content() String +get_end_offset(index) Int +get_class_name(index) String +get_inline_style(index, color_map) String +get_token_text(index) String } class InsertedToken { <<opaque>> +InsertedToken(offset, text, metadata) InsertedToken } class ContiguousMultilineTokensBuilder { <<opaque>> +ContiguousMultilineTokensBuilder() +add(line_number, words) +finalize() Array~ContiguousMultilineTokens~ } class ContiguousMultilineTokens { <<opaque batch>> } class ContiguousTokensStore { <<opaque>> +ContiguousTokensStore(codec) +get_tokens(language_id, line_index, text) LineTokens +set_multiline_tokens(batches, language_id, get_length) ContiguousTokensStoreUpdate +flush() } class ContiguousTokensStoreUpdate { +changes Array~ContiguousTokensStoreChange~ } class ContiguousTokensStoreChange { +from_line_number Int +to_line_number Int } LineTokens ..> TokenMetadata : decodes metadata with LineTokens ..> InsertedToken : splices LineTokens --> ViewLineTokens : creates ContiguousMultilineTokensBuilder --> ContiguousMultilineTokens : builds ContiguousTokensStore --> ContiguousMultilineTokens : applies ContiguousTokensStore --> LineTokens : reads ContiguousTokensStore --> ContiguousTokensStoreUpdate : reports ContiguousTokensStoreUpdate *-- ContiguousTokensStoreChange

    The namespaces and concrete full/slice distinction used by Monaco are not public MoonBit representation contracts. Callers receive opaque values and use only the operations they need.

    #Packed metadata

    One metadata word uses Monaco's 32-bit layout:

    bbbb bbbb ffff ffff fFFF FBTT LLLL LLLL

    L is the language id, T the standard token type, B the balanced-bracket bit, F the font style, f the foreground id, and b the background id. Metadata is UInt because the background occupies the high byte.

    The model theme packer consumes the public language, token-type, font-style, foreground, and background offsets plus the standard token-type and default color constants. Rendering consumes the public class-name decoder.

    ///|
    test "a production-shaped metadata word resolves to its token class" {
    let metadata = (2U << @tokens.METADATA_LANGUAGEID_OFFSET) |
    (
    @tokens.STANDARD_TOKEN_TYPE_COMMENT.reinterpret_as_uint() <<
    @tokens.METADATA_TOKEN_TYPE_OFFSET
    ) |
    (
    @tokens.FONT_STYLE_NONE.reinterpret_as_uint() <<
    @tokens.METADATA_FONT_STYLE_OFFSET
    ) |
    (7U << @tokens.METADATA_FOREGROUND_OFFSET) |
    (
    @tokens.COLOR_ID_DEFAULT_BACKGROUND.reinterpret_as_uint() <<
    @tokens.METADATA_BACKGROUND_OFFSET
    )
    inspect(@tokens.TokenMetadata(metadata).get_class_name(), content="mtk7")
    }

    #Line tokens and views

    LineTokens combines one UTF-16 line with an interleaved word array:

    [end_0, metadata_0, end_1, metadata_1, ...]

    Ends are exclusive. Token zero starts at offset zero; every later token starts at the preceding end. A complete nonempty line therefore ends with its UTF-16 length. Some tokenizers emit start offsets instead, so convert_to_end_offset shifts the starts in place before construction.

    ///|
    test "line tokens expose their consumer-facing full view" {
    let codec = @services.language_id_codec
    let keyword = 3U << @tokens.METADATA_FOREGROUND_OFFSET
    let plain = 1U << @tokens.METADATA_FOREGROUND_OFFSET
    let line = @tokens.LineTokens(
    [3U, keyword, 4U, plain, 5U, keyword],
    "let x",
    codec,
    )
    assert_true(Repr(line).to_string().contains("tokens_count: 3"))
    let view = line.inflate()
    debug_inspect(
    (
    line.get_count(),
    line.get_line_content(),
    [
    for i in 0..<view.get_count() => {
    (
    line.get_start_offset(i),
    view.get_end_offset(i),
    view.get_token_text(i),
    view.get_class_name(i),
    )
    }
    ],
    ),
    content=(
    #|(
    #| 3,
    #| "let x",
    #| [(0, 3, "let", "mtk3"), (3, 4, " ", "mtk1"), (4, 5, "x", "mtk3")],
    #|)
    ),
    )
    }

    slice_and_inflate is the wrapping seam. It retains the source words while presenting segment-local end offsets. delta accounts for a continuation line's synthetic indent.

    ///|
    test "a sliced view exposes segment-local offsets" {
    let codec = @services.language_id_codec
    let line = @tokens.LineTokens([5U, 1U, 6U, 0U, 11U, 2U], "hello world", codec)
    let view = line.slice_and_inflate(6, 11, 2)
    debug_inspect(
    (view.get_line_content(), view.get_end_offset(0), view.get_token_text(0)),
    content=(
    #|("world", 7, "world")
    ),
    )
    }

    with_inserted is how view-model inline text joins a copied line without changing model source.

    ///|
    test "injected text splices a new token" {
    let codec = @services.language_id_codec
    let line = @tokens.LineTokens([5U, 1U], "value", codec)
    let with_hint = line.with_inserted([
    InsertedToken(5, " : Int", TokenMetadata(3U)),
    ])
    let view = with_hint.inflate()
    debug_inspect(
    (
    line.get_line_content(),
    with_hint.get_line_content(),
    [
    for i in 0..<view.get_count() => view.get_token_text(i)
    ],
    ),
    content=(
    #|("value", "value : Int", ["value", " : Int"])
    ),
    )
    }

    #Per-model store

    ContiguousMultilineTokensBuilder groups adjacent one-based line results into opaque batches. ContiguousTokensStore applies those batches to its per-model cache and reports inclusive changed ranges. Reads are passive: an absent line returns one default token and never invokes a lexer.

    ///|
    test "contiguous batches apply and report changed lines" {
    let codec = @services.language_id_codec
    let builder = @tokens.ContiguousMultilineTokensBuilder()
    builder.add(1, [4U, 1U])
    builder.add(2, [4U, 2U])
    let batches = builder.finalize()
    let store = @tokens.ContiguousTokensStore(codec)
    let update = store.set_multiline_tokens(batches, "moonbit", _ => 4)
    debug_inspect(
    (
    batches.length(),
    update.changes.map(change => {
    (change.from_line_number, change.to_line_number)
    }),
    store.get_tokens("moonbit", 0, "abcd").get_metadata(0).to_uint(),
    ),
    content=(
    #|(1, [(1, 2)], 1)
    ),
    )
    }

    flush discards every stored line. The next read again produces the default top-level-language token.

    ///|
    test "flush restores passive fallback reads" {
    let codec = @services.language_id_codec
    let builder = @tokens.ContiguousMultilineTokensBuilder()
    builder.add(1, [4U, 1U])
    let store = @tokens.ContiguousTokensStore(codec)
    store.set_multiline_tokens(builder.finalize(), "moonbit", _ => 4) |> ignore
    let before = store.get_tokens("moonbit", 0, "abcd").get_metadata(0)
    store.flush()
    let after = store.get_tokens("moonbit", 0, "abcd").get_metadata(0)
    assert_true(before != after)
    }

    #UTF-16 boundary

    All token offsets and slices are raw UTF-16 code-unit offsets. A sliced view may retain a lone surrogate or either half of a valid pair, matching Monaco's string semantics.

    ///|
    test "a slice may split a surrogate pair" {
    let codec = @services.language_id_codec
    let line = @tokens.LineTokens([2U, 1U, 3U, 2U], "😀x", codec)
    let split = line.slice_and_inflate(1, 3, 0)
    debug_inspect(
    (line.get_line_content().length(), split.get_line_content().length()),
    content=(
    #|(3, 2)
    ),
    )
    }

    #Boundaries and checks

    The behavior port is scoped to vs/editor/common/tokens/{lineTokens,contiguousTokensStore,contiguousMultilineTokens,contiguousMultilineTokensBuilder}.ts and vs/editor/common/encodedTokenAttributes.ts. Typed-array versus ArrayBuffer identity, worker serialization, incremental token edits, the TokenArray family, and sparse semantic merging remain outside the readonly in-process boundary.

    This package may depend only on base/common and viewer/common/services; it must not import model, view-model, syntax, DOM, or host packages. The generated interface is the exact supported surface.

    moon test --target js viewer/common/tokens

    ContiguousMultilineTokens

    type ContiguousMultilineTokens

    Encoded tokens for one contiguous inclusive interval of one-based lines. Each inner array contains [endOffset, metadata] pairs for one line. Source: contiguousMultilineTokens.ts:17,35-46.

    ContiguousMultilineTokensBuilder

    type ContiguousMultilineTokensBuilder

    Collects adjacent one-based lines into ordered contiguous batches. Source: contiguousMultilineTokensBuilder.ts:9,21.

    ContiguousMultilineTokensBuilder::ContiguousMultilineTokensBuilder

    fn ContiguousMultilineTokensBuilder::ContiguousMultilineTokensBuilder() -> ContiguousMultilineTokensBuilder

    Creates an empty collector. Source: contiguousMultilineTokensBuilder.ts:23-25.

    ContiguousMultilineTokensBuilder::add

    fn ContiguousMultilineTokensBuilder::add(self : ContiguousMultilineTokensBuilder, line_number : Int, line_tokens : Array[UInt]) -> Unit

    Appends to the final batch only when line_number is its exact successor; gaps and out-of-order lines begin a new batch. Source: contiguousMultilineTokensBuilder.ts:27-37.

    ContiguousMultilineTokensBuilder::finalize

    Returns the accumulated batches in insertion order without copying them. Source: contiguousMultilineTokensBuilder.ts:39-41.

    ContiguousTokensStore

    type ContiguousTokensStore

    Per-model contiguous syntactic token storage. Source: contiguousTokensStore.ts:19-22.

    ContiguousTokensStore::ContiguousTokensStore

    Creates an empty store retaining the shared language-id codec. Source: contiguousTokensStore.ts:24-28.

    ContiguousTokensStore::flush

    Drops every initialized slot and resets the logical initialized prefix. Source: contiguousTokensStore.ts:30-33.

    ContiguousTokensStore::get_tokens

    fn ContiguousTokensStore::get_tokens(self : ContiguousTokensStore, top_level_language_id : String, line_index : Int, line_text : String) -> LineTokens

    Passively reads stored words or returns one top-level-language fallback token. This operation never invokes a tokenizer. Source: contiguousTokensStore.ts:39-53.

    ContiguousTokensStore::set_multiline_tokens

    fn ContiguousTokensStore::set_multiline_tokens(self : ContiguousTokensStore, tokens : Array[ContiguousMultilineTokens], top_level_language_id : String, get_line_length : (Int) -> Int) -> ContiguousTokensStoreUpdate

    Applies batches in order. Within each batch it checks equality only through the first changed line, then writes the remaining suffix unchecked and returns one inclusive min/max interval. Source: contiguousTokensStore.ts:213-244.

    ContiguousTokensStoreChange

    pub struct ContiguousTokensStoreChange {
    from_line_number : Int
    to_line_number : Int
    }

    Inclusive changed-line interval produced by one contiguous batch. Source: contiguousTokensStore.ts:213-244.

    ContiguousTokensStoreUpdate

    pub struct ContiguousTokensStoreUpdate {
    changes : Array[ContiguousTokensStoreChange]
    }

    Ordered changed intervals from set_multiline_tokens. Source: contiguousTokensStore.ts:213-244.

    InsertedToken

    type InsertedToken

    A token to splice into the line. insert_tokens must be sorted by offset.

    InsertedToken::InsertedToken

    fn InsertedToken::InsertedToken(offset : Int, text : String, token_metadata : TokenMetadata) -> InsertedToken

    LineTokens

    type LineTokens derive(
    Debug
    )

    A token sequence backed by interleaved end-offset and metadata words.

    For token i, tokens[i << 1] is its exclusive UTF-16 end offset and tokens[(i << 1) + 1] is its packed metadata. Its start offset is 0 for the first token and the previous token's end offset otherwise. For example, [3U, a, 4U, b, 5U, c] over "let x" describes "let" at [0, 3), a space at [3, 4), and "x" at [4, 5).

    Direct-constructor callers must supply an even number of words with nondecreasing end offsets. For a complete line with at least one token, the last end offset is the text's UTF-16 length.

    LineTokens::LineTokens

    LineTokens::convert_to_end_offset

    fn LineTokens::convert_to_end_offset(tokens : Array[UInt], line_text_length : Int) -> Unit

    Rewrites tokens start-offset slots in place to be end offsets.

    LineTokens::default_token_metadata

    fn LineTokens::default_token_metadata() -> TokenMetadata

    The default metadata value (no font style, default fg/bg colors).

    LineTokens::get_count

    fn LineTokens::get_count(self : LineTokens) -> Int

    LineTokens::get_line_content

    fn LineTokens::get_line_content(self : LineTokens) -> String

    LineTokens::get_metadata

    fn LineTokens::get_metadata(self : LineTokens, token_index : Int) -> TokenMetadata

    LineTokens::get_start_offset

    fn LineTokens::get_start_offset(self : LineTokens, token_index : Int) -> Int

    LineTokens::inflate

    fn LineTokens::inflate(self : LineTokens) -> ViewLineTokens

    inflate() returns the tokens unchanged — already a view.

    LineTokens::slice_and_inflate

    fn LineTokens::slice_and_inflate(self : LineTokens, start_offset : Int, end_offset : Int, delta_offset : Int) -> ViewLineTokens

    LineTokens::with_inserted

    fn LineTokens::with_inserted(self : LineTokens, insert_tokens : Array[InsertedToken]) -> LineTokens

    Returns a new LineTokens with insert_tokens spliced into the text and token boundaries. Pure; the receiver is unchanged.

    TokenMetadata

    pub(all) struct TokenMetadata(UInt) derive(Eq)

    One packed 32-bit token metadata word. The distinct type keeps semantic APIs from accidentally accepting offsets or unrelated UInt values while its public scalar representation remains available at raw storage seams.

    TokenMetadata::equal

    TokenMetadata::get_class_name

    fn TokenMetadata::get_class_name(self : TokenMetadata) -> String

    Returns the Monaco-compatible token CSS class list.

    TokenMetadata::not_equal

    fn TokenMetadata::not_equal(x : TokenMetadata, y : TokenMetadata) -> Bool

    TokenMetadata::to_uint

    fn TokenMetadata::to_uint(self : TokenMetadata) -> UInt

    Returns the raw word for flat encoded-token storage or transport.

    ViewLineTokens

    type ViewLineTokens

    A line's full or sliced token view. Package consumers see an abstract type and use the common read operations below.

    ViewLineTokens::get_class_name

    fn ViewLineTokens::get_class_name(self : ViewLineTokens, token_index : Int) -> String

    ViewLineTokens::get_count

    fn ViewLineTokens::get_count(self : ViewLineTokens) -> Int

    ViewLineTokens::get_end_offset

    fn ViewLineTokens::get_end_offset(self : ViewLineTokens, token_index : Int) -> Int

    ViewLineTokens::get_inline_style

    fn ViewLineTokens::get_inline_style(self : ViewLineTokens, token_index : Int, color_map : Array[String]) -> String

    ViewLineTokens::get_line_content

    fn ViewLineTokens::get_line_content(self : ViewLineTokens) -> String

    ViewLineTokens::get_token_text

    fn ViewLineTokens::get_token_text(self : ViewLineTokens, token_index : Int) -> String

    COLOR_ID_DEFAULT_BACKGROUND

    let COLOR_ID_DEFAULT_BACKGROUND : Int

    COLOR_ID_DEFAULT_FOREGROUND

    let COLOR_ID_DEFAULT_FOREGROUND : Int

    ColorId — open ended at runtime.

    FONT_STYLE_NONE

    let FONT_STYLE_NONE : Int

    FontStyle — values are 2^x so a bit mask can be used.

    METADATA_BACKGROUND_OFFSET

    let METADATA_BACKGROUND_OFFSET : Int

    METADATA_FONT_STYLE_OFFSET

    let METADATA_FONT_STYLE_OFFSET : Int

    METADATA_FOREGROUND_OFFSET

    let METADATA_FOREGROUND_OFFSET : Int

    METADATA_LANGUAGEID_OFFSET

    let METADATA_LANGUAGEID_OFFSET : Int

    METADATA_TOKEN_TYPE_OFFSET

    let METADATA_TOKEN_TYPE_OFFSET : Int

    STANDARD_TOKEN_TYPE_COMMENT

    let STANDARD_TOKEN_TYPE_COMMENT : Int

    STANDARD_TOKEN_TYPE_OTHER

    let STANDARD_TOKEN_TYPE_OTHER : Int

    StandardTokenType.

    STANDARD_TOKEN_TYPE_REGEX

    let STANDARD_TOKEN_TYPE_REGEX : Int

    STANDARD_TOKEN_TYPE_STRING

    let STANDARD_TOKEN_TYPE_STRING : Int

    Powered by MoonBit

    Site sourceReport issueModulesSkillsCLIBuild queueStatistics

    © 2026 mooncakes.io