///|
fn source_path(raw : String) -> String {
match @workspace.SourcePath::normalize_root_relative_path(raw) {
ParsedSourcePath(path) => "ok:" + path.to_string()
SourcePathError(_) => "rejected"
}
}
///|
test "traversal, absolute, and drive paths are rejected" {
debug_inspect(
[
"src/main.mbt", "./src/main.mbt", "src//main.mbt", "../escape.mbt", "/etc/passwd",
"C:\\Windows\\system.ini", "src/\u{0}evil.mbt",
].map(source_path),
content=(
#|[
#| "ok:src/main.mbt",
#| "ok:src/main.mbt",
#| "ok:src/main.mbt",
#| "rejected",
#| "rejected",
#| "rejected",
#| "rejected",
#|]
),
)
}///|
test "language ids are inferred from the extension" {
debug_inspect(
["main.mbt", "data.json", "app.js", "README.md", "notes.mbt.md", "LICENSE"].map(
@workspace.infer_language_id,
),
content=(
#|["moonbit", "json", "javascript", "markdown", "moonbit", "moonbit"]
),
)
}///|
fn snapshot(text : String) -> @workspace.DocumentSnapshot raise {
DocumentSnapshot(
@base_common.Uri::parse("file:///workspace/src/main.mbt"),
"main.mbt",
"moonbit",
"rev-1",
text,
)
}
///|
test "line addressing handles all three terminators" {
let doc = snapshot("a\r\nbb\rccc\ndddd")
debug_inspect(
(
doc.line_count(),
[
for index in 0..<doc.line_count() => doc.line_text(index)
],
doc.length(),
),
content=(
#|(4, ["a", "bb", "ccc", "dddd"], 14)
),
)
}///|
test "offsets and 1-based positions convert both ways" {
let doc = snapshot("let x = 1\nlet y = 2\n")
let position = doc.position_at_offset(12)
debug_inspect(
(
position,
doc.offset_at_position(position),
doc.line_at_offset(12),
doc.slice(OffsetRange(10, 13)),
),
content=(
#|({ line_number: 2, column: 3 }, 12, 1, "let")
),
)
}///|
test "the revision is derived from the text" {
let first = @workspace.revision_from_text("let x = 1\n")
let same = @workspace.revision_from_text("let x = 1\n")
let different = @workspace.revision_from_text("let x = 2\n")
debug_inspect(
(first == same, first == different),
content=(
#|(true, false)
),
)
}pub(open) trait DocumentProvider {
async fn read(Self, Uri) -> DocumentReadResult
fn watch(Self, Uri, (DocumentChange) -> Unit) -> Disposable
fn close(Self, Uri) -> Unit
}pub(open) trait FileSystemProvider {
fn scheme(Self) -> String
async fn read_file(Self, Uri) -> FileReadResult
fn watch(Self, Uri, WatchOptions, (Array[FileChange]) -> Unit) -> FileWatch
}pub(open) trait WorkspaceTreeProvider {
fn root(Self) -> Uri
async fn resolve(Self, Uri) -> WorkspaceResolveResult
}pub(all) enum DocumentChange {
DocumentInvalidated(uri~ : Uri, known_revision~ : String?)
DocumentUpdated(DocumentSnapshot)
DocumentDeleted(Uri)
DocumentChangeFailed(uri~ : Uri, error~ : DocumentError)
} derive(Debug)fn DocumentContent::DocumentContent(text : String, display_name? : String, language_id? : String, revision? : String) -> DocumentContentpub struct DocumentError {
code : FileSystemProviderErrorCode
message : String
uri : Uri?
} derive(Debug)impl ToJson for DocumentErrorfn DocumentError::DocumentError(code : FileSystemProviderErrorCode, message : String, uri? : Uri) -> DocumentErrorpub(all) enum DocumentReadResult {
DocumentLoaded(DocumentSnapshot)
DocumentNotFound(Uri)
DocumentReadFailed(DocumentError)
} derive(Debug)impl ToJson for DocumentReadResultimpl ToJson for DocumentSnapshotfn DocumentSnapshot::DocumentSnapshot(uri : Uri, display_name : String, language_id : String, revision : String, text : String) -> DocumentSnapshotimpl ToJson for FileChangepub(all) enum FileReadResult {
FileReadOk(DocumentContent)
FileReadError(FileSystemProviderError)
} derive(Debug)pub struct FileSystemProviderError {
code : FileSystemProviderErrorCode
message : String
uri : Uri?
} derive(Debug)impl ToJson for FileSystemProviderErrorfn FileSystemProviderError::FileSystemProviderError(code : FileSystemProviderErrorCode, message : String, uri? : Uri) -> FileSystemProviderErrorfn FileSystemProviderErrorCode::equal(FileSystemProviderErrorCode, FileSystemProviderErrorCode) -> Boolfn FileSystemProviderErrorCode::not_equal(x : FileSystemProviderErrorCode, y : FileSystemProviderErrorCode) -> Boolpub(all) struct FileWatch {
dispose : () -> Unit
}pub enum SourcePathResult {
ParsedSourcePath(SourcePath)
SourcePathError(SourceError)
} derive(Eq, Debug)pub(all) enum WorkspaceResolveResult {
WorkspaceResolved(WorkspaceStat)
WorkspaceResolveError(FileSystemProviderError)
} derive(Debug)pub(all) struct WorkspaceStat {
uri : Uri
name : String
kind : WorkspaceEntryKind
children : Array[WorkspaceStat]?
} derive(Debug)fn infer_language_id(path_or_name : String) -> Stringfn revision_from_text(text : String) -> Stringfn watch_file(provider : &FileSystemProvider, uri : Uri, listener : (Array[FileChange]) -> Unit) -> FileWatchInstall
Download zipReadonly MoonBit code viewer harness inspired by Monaco and CodeMirror.