mirror of
https://github.com/enso-org/enso.git
synced 2024-12-23 07:12:20 +03:00
343a644051
- Synchronize Y.Js clients by AST (implements #8237). - Before committing an edit, insert any parentheses-nodes needed for the concrete syntax to reflect tree structure (fixes #8884). - Move `externalId` and all node metadata into a Y.Map owned by each `Ast`. This allows including metadata changes in an edit, enables Y.Js merging of changes to different metadata fields, and will enable the use of Y.Js objects in metadata. (Implements #8804.) ### Important Notes - Metadata is now set and retrieved through accessors on the `Ast` objects. - Since some metadata edits need to take effect in real time (e.g. node dragging), new lower-overhead APIs (`commitDirect`, `skipTreeRepair`) are provided for careful use in certain cases. - The client is now bundled as ESM. - The build script cleans up git-untracked generated files in an outdated location, which fixes lint errors related to `src/generated` that may occur when switching branches.
71 lines
2.0 KiB
TypeScript
71 lines
2.0 KiB
TypeScript
import * as random from 'lib0/random'
|
|
import type { ExternalId } from '../yjsModel'
|
|
import type { Module } from './mutableModule'
|
|
import type { SyncTokenId } from './token'
|
|
import type { AstId } from './tree'
|
|
import { Ast, MutableAst } from './tree'
|
|
|
|
export * from './mutableModule'
|
|
export * from './parse'
|
|
export * from './token'
|
|
export * from './tree'
|
|
|
|
declare const brandOwned: unique symbol
|
|
/** Used to mark references required to be unique.
|
|
*
|
|
* Note that the typesystem cannot stop you from copying an `Owned`,
|
|
* but that is an easy mistake to see (because it occurs locally).
|
|
*
|
|
* We can at least require *obtaining* an `Owned`,
|
|
* which statically prevents the otherwise most likely usage errors when rearranging ASTs.
|
|
*/
|
|
export type Owned<T = MutableAst> = T & { [brandOwned]: never }
|
|
/** @internal */
|
|
export function asOwned<T>(t: T): Owned<T> {
|
|
return t as Owned<T>
|
|
}
|
|
|
|
export type NodeChild<T = AstId | SyncTokenId> = { whitespace?: string | undefined; node: T }
|
|
|
|
export function newExternalId(): ExternalId {
|
|
return random.uuidv4() as ExternalId
|
|
}
|
|
|
|
/** @internal */
|
|
export function parentId(ast: Ast): AstId | undefined {
|
|
return ast.fields.get('parent')
|
|
}
|
|
|
|
/** Returns the given IDs, and the IDs of all their ancestors. */
|
|
export function subtrees(module: Module, ids: Iterable<AstId>) {
|
|
const subtrees = new Set<AstId>()
|
|
for (const id of ids) {
|
|
let ast = module.get(id)
|
|
while (ast != null && !subtrees.has(ast.id)) {
|
|
subtrees.add(ast.id)
|
|
ast = ast.parent()
|
|
}
|
|
}
|
|
return subtrees
|
|
}
|
|
|
|
/** Returns the IDs of the ASTs that are not descendants of any others in the given set. */
|
|
export function subtreeRoots(module: Module, ids: Set<AstId>) {
|
|
const roots = new Array<AstId>()
|
|
for (const id of ids) {
|
|
const astInModule = module.get(id)
|
|
if (!astInModule) continue
|
|
let ast = astInModule.parent()
|
|
let hasParentInSet
|
|
while (ast != null) {
|
|
if (ids.has(ast.id)) {
|
|
hasParentInSet = true
|
|
break
|
|
}
|
|
ast = ast.parent()
|
|
}
|
|
if (!hasParentInSet) roots.push(id)
|
|
}
|
|
return roots
|
|
}
|