/* * Copyright 2025 the original author or authors. *

* Licensed under the Moderne Source Available License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *

* https://docs.moderne.io/licensing/moderne-source-available-license *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {Cursor, SourceFile, Tree} from "./tree"; import {TreeVisitor} from "./visitor"; import {PrintOutputCapture, TreePrinters} from "./print"; import {RpcCodecs, RpcReceiveQueue, RpcSendQueue} from "./rpc"; import {updateIfChanged} from "./util"; export const ParseErrorKind = "org.openrewrite.tree.ParseError"; export interface ParseError extends SourceFile { readonly kind: typeof ParseErrorKind; readonly text: string; readonly erroneous?: SourceFile; } export function isParseError(tree: any): tree is ParseError { return tree["kind"] === ParseErrorKind; } export class ParseErrorVisitor

extends TreeVisitor { async isAcceptable(sourceFile: SourceFile, p: P): Promise { return isParseError(sourceFile); } protected async accept(t: Tree, p: P): Promise { if (t.kind === ParseErrorKind) { return this.visitParseError(t as ParseError, p); } throw new Error("Unexpected tree kind: " + t.kind); } protected async visitParseError(e: ParseError, p: P): Promise { return this.produceTree(e, p); } } TreePrinters.register(ParseErrorKind, () => new class extends ParseErrorVisitor { protected async visitParseError(e: ParseError, p: PrintOutputCapture): Promise { for (let marker of e.markers.markers) { p.append(p.markerPrinter.beforePrefix(marker, new Cursor(marker, this.cursor), it => it)) } await this.visitMarkers(e.markers, p); for (let marker of e.markers.markers) { p.append(p.markerPrinter.beforeSyntax(marker, new Cursor(marker, this.cursor), it => it)) } p.append(e.text); for (let marker of e.markers.markers) { p.append(p.markerPrinter.afterSyntax(marker, new Cursor(marker, this.cursor), it => it)) } return e; } }) RpcCodecs.registerCodec(ParseErrorKind, { async rpcReceive(before: ParseError, q: RpcReceiveQueue): Promise { return updateIfChanged(before, { id: await q.receive(before.id), markers: await q.receive(before.markers), sourcePath: await q.receive(before.sourcePath), charsetName: await q.receive(before.charsetName), charsetBomMarked: await q.receive(before.charsetBomMarked), checksum: await q.receive(before.checksum), fileAttributes: await q.receive(before.fileAttributes), text: await q.receive(before.text), }); }, async rpcSend(after: ParseError, q: RpcSendQueue): Promise { await q.getAndSend(after, p => p.id); await q.getAndSend(after, p => p.markers); await q.getAndSend(after, p => p.sourcePath); await q.getAndSend(after, p => p.charsetName); await q.getAndSend(after, p => p.charsetBomMarked); await q.getAndSend(after, p => p.checksum); await q.getAndSend(after, p => p.fileAttributes); await q.getAndSend(after, p => p.text); } });