refactor(yaml): inline composeNode() (#5861)

* initial commit

* update
This commit is contained in:
Tim Reichen 2024-08-29 09:43:20 +02:00 committed by GitHub
parent 745c4a61ae
commit 0a71a4d3db
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -388,7 +388,7 @@ export class LoaderState {
}
line = this.line;
composeNode(this, nodeIndent, CONTEXT_BLOCK_IN, false, true);
this.composeNode(nodeIndent, CONTEXT_BLOCK_IN, false, true);
result.push(this.result);
this.skipSeparationSpace(true, -1);
@ -884,7 +884,7 @@ export class LoaderState {
}
line = this.line;
composeNode(this, nodeIndent, CONTEXT_FLOW_IN, false, true);
this.composeNode(nodeIndent, CONTEXT_FLOW_IN, false, true);
keyTag = this.tag || null;
keyNode = this.result;
this.skipSeparationSpace(true, nodeIndent);
@ -895,7 +895,7 @@ export class LoaderState {
isPair = true;
ch = this.next();
this.skipSeparationSpace(true, nodeIndent);
composeNode(this, nodeIndent, CONTEXT_FLOW_IN, false, true);
this.composeNode(nodeIndent, CONTEXT_FLOW_IN, false, true);
valueNode = this.result;
}
@ -1156,7 +1156,7 @@ export class LoaderState {
//
// Implicit notation case. Flow-style node as the key first, then ":", and the value.
//
} else if (composeNode(this, flowIndent, CONTEXT_FLOW_OUT, false, true)) {
} else if (this.composeNode(flowIndent, CONTEXT_FLOW_OUT, false, true)) {
if (this.line === line) {
ch = this.peek();
@ -1216,7 +1216,7 @@ export class LoaderState {
//
if (this.line === line || this.lineIndent > nodeIndent) {
if (
composeNode(this, nodeIndent, CONTEXT_BLOCK_OUT, true, allowCompact)
this.composeNode(nodeIndent, CONTEXT_BLOCK_OUT, true, allowCompact)
) {
if (atExplicitKey) {
keyNode = this.result;
@ -1431,6 +1431,171 @@ export class LoaderState {
return true;
}
composeNode(
parentIndent: number,
nodeContext: number,
allowToSeek: boolean,
allowCompact: boolean,
): boolean {
let allowBlockScalars: boolean;
let allowBlockCollections: boolean;
let indentStatus = 1; // 1: this>parent, 0: this=parent, -1: this<parent
let atNewLine = false;
let hasContent = false;
let type: Type<KindType>;
let flowIndent: number;
let blockIndent: number;
this.tag = null;
this.anchor = null;
this.kind = null;
this.result = null;
const allowBlockStyles = (allowBlockScalars =
allowBlockCollections =
CONTEXT_BLOCK_OUT === nodeContext || CONTEXT_BLOCK_IN === nodeContext);
if (allowToSeek) {
if (this.skipSeparationSpace(true, -1)) {
atNewLine = true;
if (this.lineIndent > parentIndent) {
indentStatus = 1;
} else if (this.lineIndent === parentIndent) {
indentStatus = 0;
} else if (this.lineIndent < parentIndent) {
indentStatus = -1;
}
}
}
if (indentStatus === 1) {
while (this.readTagProperty() || this.readAnchorProperty()) {
if (this.skipSeparationSpace(true, -1)) {
atNewLine = true;
allowBlockCollections = allowBlockStyles;
if (this.lineIndent > parentIndent) {
indentStatus = 1;
} else if (this.lineIndent === parentIndent) {
indentStatus = 0;
} else if (this.lineIndent < parentIndent) {
indentStatus = -1;
}
} else {
allowBlockCollections = false;
}
}
}
if (allowBlockCollections) {
allowBlockCollections = atNewLine || allowCompact;
}
if (indentStatus === 1 || CONTEXT_BLOCK_OUT === nodeContext) {
const cond = CONTEXT_FLOW_IN === nodeContext ||
CONTEXT_FLOW_OUT === nodeContext;
flowIndent = cond ? parentIndent : parentIndent + 1;
blockIndent = this.position - this.lineStart;
if (indentStatus === 1) {
if (
(allowBlockCollections &&
(this.readBlockSequence(blockIndent) ||
this.readBlockMapping(blockIndent, flowIndent))) ||
this.readFlowCollection(flowIndent)
) {
hasContent = true;
} else {
if (
(allowBlockScalars && this.readBlockScalar(flowIndent)) ||
this.readSingleQuotedScalar(flowIndent) ||
this.readDoubleQuotedScalar(flowIndent)
) {
hasContent = true;
} else if (this.readAlias()) {
hasContent = true;
if (this.tag !== null || this.anchor !== null) {
return this.throwError(
"Cannot compose node: alias node should not have any properties",
);
}
} else if (
this.readPlainScalar(flowIndent, CONTEXT_FLOW_IN === nodeContext)
) {
hasContent = true;
if (this.tag === null) {
this.tag = "?";
}
}
if (this.anchor !== null) {
this.anchorMap.set(this.anchor, this.result);
}
}
} else if (indentStatus === 0) {
// Special case: block sequences are allowed to have same indentation level as the parent.
// http://www.yaml.org/spec/1.2/spec.html#id2799784
hasContent = allowBlockCollections &&
this.readBlockSequence(blockIndent);
}
}
if (this.tag !== null && this.tag !== "!") {
if (this.tag === "?") {
for (
let typeIndex = 0;
typeIndex < this.implicitTypes.length;
typeIndex++
) {
type = this.implicitTypes[typeIndex]!;
// Implicit resolving is not allowed for non-scalar types, and '?'
// non-specific tag is only assigned to plain scalars. So, it isn't
// needed to check for 'kind' conformity.
if (type.resolve(this.result)) {
// `state.result` updated in resolver if matched
this.result = type.construct(this.result);
this.tag = type.tag;
if (this.anchor !== null) {
this.anchorMap.set(this.anchor, this.result);
}
break;
}
}
} else if (this.typeMap[this.kind ?? "fallback"].has(this.tag)) {
const map = this.typeMap[this.kind ?? "fallback"];
type = map.get(this.tag)!;
if (this.result !== null && type.kind !== this.kind) {
return this.throwError(
`Unacceptable node kind for !<${this.tag}> tag: it should be "${type.kind}", not "${this.kind}"`,
);
}
if (!type.resolve(this.result)) {
// `state.result` updated in resolver if matched
return this.throwError(
`Cannot resolve a node with !<${this.tag}> explicit tag`,
);
} else {
this.result = type.construct(this.result);
if (this.anchor !== null) {
this.anchorMap.set(this.anchor, this.result);
}
}
} else {
return this.throwError(`Cannot resolve unknown tag !<${this.tag}>`);
}
}
return this.tag !== null || this.anchor !== null || hasContent;
}
readDocument() {
const documentStart = this.position;
let position: number;
@ -1526,7 +1691,7 @@ export class LoaderState {
);
}
composeNode(this, this.lineIndent - 1, CONTEXT_BLOCK_OUT, false, true);
this.composeNode(this.lineIndent - 1, CONTEXT_BLOCK_OUT, false, true);
this.skipSeparationSpace(true, -1);
if (
@ -1558,169 +1723,3 @@ export class LoaderState {
}
}
}
function composeNode(
state: LoaderState,
parentIndent: number,
nodeContext: number,
allowToSeek: boolean,
allowCompact: boolean,
): boolean {
let allowBlockScalars: boolean;
let allowBlockCollections: boolean;
let indentStatus = 1; // 1: this>parent, 0: this=parent, -1: this<parent
let atNewLine = false;
let hasContent = false;
let type: Type<KindType>;
let flowIndent: number;
let blockIndent: number;
state.tag = null;
state.anchor = null;
state.kind = null;
state.result = null;
const allowBlockStyles = (allowBlockScalars =
allowBlockCollections =
CONTEXT_BLOCK_OUT === nodeContext || CONTEXT_BLOCK_IN === nodeContext);
if (allowToSeek) {
if (state.skipSeparationSpace(true, -1)) {
atNewLine = true;
if (state.lineIndent > parentIndent) {
indentStatus = 1;
} else if (state.lineIndent === parentIndent) {
indentStatus = 0;
} else if (state.lineIndent < parentIndent) {
indentStatus = -1;
}
}
}
if (indentStatus === 1) {
while (state.readTagProperty() || state.readAnchorProperty()) {
if (state.skipSeparationSpace(true, -1)) {
atNewLine = true;
allowBlockCollections = allowBlockStyles;
if (state.lineIndent > parentIndent) {
indentStatus = 1;
} else if (state.lineIndent === parentIndent) {
indentStatus = 0;
} else if (state.lineIndent < parentIndent) {
indentStatus = -1;
}
} else {
allowBlockCollections = false;
}
}
}
if (allowBlockCollections) {
allowBlockCollections = atNewLine || allowCompact;
}
if (indentStatus === 1 || CONTEXT_BLOCK_OUT === nodeContext) {
const cond = CONTEXT_FLOW_IN === nodeContext ||
CONTEXT_FLOW_OUT === nodeContext;
flowIndent = cond ? parentIndent : parentIndent + 1;
blockIndent = state.position - state.lineStart;
if (indentStatus === 1) {
if (
(allowBlockCollections &&
(state.readBlockSequence(blockIndent) ||
state.readBlockMapping(blockIndent, flowIndent))) ||
state.readFlowCollection(flowIndent)
) {
hasContent = true;
} else {
if (
(allowBlockScalars && state.readBlockScalar(flowIndent)) ||
state.readSingleQuotedScalar(flowIndent) ||
state.readDoubleQuotedScalar(flowIndent)
) {
hasContent = true;
} else if (state.readAlias()) {
hasContent = true;
if (state.tag !== null || state.anchor !== null) {
return state.throwError(
"Cannot compose node: alias node should not have any properties",
);
}
} else if (
state.readPlainScalar(flowIndent, CONTEXT_FLOW_IN === nodeContext)
) {
hasContent = true;
if (state.tag === null) {
state.tag = "?";
}
}
if (state.anchor !== null) {
state.anchorMap.set(state.anchor, state.result);
}
}
} else if (indentStatus === 0) {
// Special case: block sequences are allowed to have same indentation level as the parent.
// http://www.yaml.org/spec/1.2/spec.html#id2799784
hasContent = allowBlockCollections &&
state.readBlockSequence(blockIndent);
}
}
if (state.tag !== null && state.tag !== "!") {
if (state.tag === "?") {
for (
let typeIndex = 0;
typeIndex < state.implicitTypes.length;
typeIndex++
) {
type = state.implicitTypes[typeIndex]!;
// Implicit resolving is not allowed for non-scalar types, and '?'
// non-specific tag is only assigned to plain scalars. So, it isn't
// needed to check for 'kind' conformity.
if (type.resolve(state.result)) {
// `state.result` updated in resolver if matched
state.result = type.construct(state.result);
state.tag = type.tag;
if (state.anchor !== null) {
state.anchorMap.set(state.anchor, state.result);
}
break;
}
}
} else if (state.typeMap[state.kind ?? "fallback"].has(state.tag)) {
const map = state.typeMap[state.kind ?? "fallback"];
type = map.get(state.tag)!;
if (state.result !== null && type.kind !== state.kind) {
return state.throwError(
`Unacceptable node kind for !<${state.tag}> tag: it should be "${type.kind}", not "${state.kind}"`,
);
}
if (!type.resolve(state.result)) {
// `state.result` updated in resolver if matched
return state.throwError(
`Cannot resolve a node with !<${state.tag}> explicit tag`,
);
} else {
state.result = type.construct(state.result);
if (state.anchor !== null) {
state.anchorMap.set(state.anchor, state.result);
}
}
} else {
return state.throwError(`Cannot resolve unknown tag !<${state.tag}>`);
}
}
return state.tag !== null || state.anchor !== null || hasContent;
}