diff --git a/src/compose/composer.ts b/src/compose/composer.ts index 598ba78b..3fe9248a 100644 --- a/src/compose/composer.ts +++ b/src/compose/composer.ts @@ -133,7 +133,12 @@ export class Composer< * * Mostly useful at the end of input for an empty stream. */ - streamInfo() { + streamInfo(): { + comment: string + directives: Directives + errors: YAMLParseError[] + warnings: YAMLWarning[] + } { return { comment: parsePrelude(this.prelude).comment, directives: this.directives, @@ -148,13 +153,19 @@ export class Composer< * @param forceDoc - If the stream contains no document, still emit a final document including any comments and directives that would be applied to a subsequent document. * @param endOffset - Should be set if `forceDoc` is also set, to set the document range end and to indicate errors correctly. */ - *compose(tokens: Iterable, forceDoc = false, endOffset = -1) { + *compose( + tokens: Iterable, + forceDoc = false, + endOffset = -1 + ): Generator, void, unknown> { for (const token of tokens) yield* this.next(token) yield* this.end(forceDoc, endOffset) } /** Advance the composer by one CST token. */ - *next(token: Token) { + *next( + token: Token + ): Generator, void, unknown> { if (process.env.LOG_STREAM) console.dir(token, { depth: null }) switch (token.type) { case 'directive': @@ -245,7 +256,10 @@ export class Composer< * @param forceDoc - If the stream contains no document, still emit a final document including any comments and directives that would be applied to a subsequent document. * @param endOffset - Should be set if `forceDoc` is also set, to set the document range end and to indicate errors correctly. */ - *end(forceDoc = false, endOffset = -1) { + *end( + forceDoc = false, + endOffset = -1 + ): Generator, void, unknown> { if (this.doc) { this.decorate(this.doc, true) yield this.doc diff --git a/src/doc/Document.ts b/src/doc/Document.ts index 14456486..782f87d5 100644 --- a/src/doc/Document.ts +++ b/src/doc/Document.ts @@ -265,7 +265,7 @@ export class Document< key: unknown, value: unknown, options: CreateNodeOptions = {} - ) { + ): Pair { const k = this.createNode(key, null, options) as K const v = this.createNode(value, null, options) as V return new Pair(k, v) diff --git a/src/doc/directives.ts b/src/doc/directives.ts index 37f1ce0b..55227a86 100644 --- a/src/doc/directives.ts +++ b/src/doc/directives.ts @@ -53,7 +53,7 @@ export class Directives { * During parsing, get a Directives instance for the current document and * update the stream state according to the current version's spec. */ - atDocument() { + atDocument(): Directives { const res = new Directives(this.yaml, this.tags) switch (this.yaml.version) { case '1.1': @@ -78,7 +78,7 @@ export class Directives { add( line: string, onError: (offset: number, message: string, warning?: boolean) => void - ) { + ): boolean { if (this.atNextDocument) { this.yaml = { explicit: Directives.defaultYaml.explicit, version: '1.1' } this.tags = Object.assign({}, Directives.defaultTags) @@ -124,7 +124,7 @@ export class Directives { * @returns Resolved tag, which may also be the non-specific tag `'!'` or a * `'!local'` tag, or `null` if unresolvable. */ - tagName(source: string, onError: (message: string) => void) { + tagName(source: string, onError: (message: string) => void): string | null { if (source === '!') return '!' // non-specific tag if (source[0] !== '!') { @@ -164,7 +164,7 @@ export class Directives { * Given a fully resolved tag, returns its printable string form, * taking into account current tag prefixes and defaults. */ - tagString(tag: string) { + tagString(tag: string): string { for (const [handle, prefix] of Object.entries(this.tags)) { if (tag.startsWith(prefix)) return handle + escapeTagName(tag.substring(prefix.length)) @@ -172,7 +172,7 @@ export class Directives { return tag[0] === '!' ? tag : `!<${tag}>` } - toString(doc?: Document) { + toString(doc?: Document): string { const lines = this.yaml.explicit ? [`%YAML ${this.yaml.version || '1.2'}`] : [] diff --git a/src/nodes/Alias.ts b/src/nodes/Alias.ts index 8461c3df..bcc1d57e 100644 --- a/src/nodes/Alias.ts +++ b/src/nodes/Alias.ts @@ -49,7 +49,7 @@ export class Alias extends NodeBase { return found } - toJSON(_arg?: unknown, ctx?: ToJSContext) { + toJSON(_arg?: unknown, ctx?: ToJSContext): unknown { if (!ctx) return { source: this.source } const { anchors, doc, maxAliasCount } = ctx const source = this.resolve(doc) @@ -85,7 +85,7 @@ export class Alias extends NodeBase { ctx?: StringifyContext, _onComment?: () => void, _onChompKeep?: () => void - ) { + ): string { const src = `*${this.source}` if (ctx) { anchorIsValid(this.source) diff --git a/src/nodes/Collection.ts b/src/nodes/Collection.ts index 9e336b91..171ff2cf 100644 --- a/src/nodes/Collection.ts +++ b/src/nodes/Collection.ts @@ -163,7 +163,7 @@ export abstract class Collection extends NodeBase { else return isCollection(node) ? node.getIn(rest, keepScalar) : undefined } - hasAllNullValues(allowScalar?: boolean) { + hasAllNullValues(allowScalar?: boolean): boolean { return this.items.every(node => { if (!isPair(node)) return false const n = node.value diff --git a/src/nodes/Pair.ts b/src/nodes/Pair.ts index e3f369f2..f41a8791 100644 --- a/src/nodes/Pair.ts +++ b/src/nodes/Pair.ts @@ -6,13 +6,14 @@ import type { StringifyContext } from '../stringify/stringify.ts' import { stringifyPair } from '../stringify/stringifyPair.ts' import { addPairToJSMap } from './addPairToJSMap.ts' import { isNode, NODE_TYPE, PAIR } from './identity.ts' +import type { Node } from './Node.ts' import type { ToJSContext } from './toJS.ts' export function createPair( key: unknown, value: unknown, ctx: CreateNodeContext -) { +): Pair { const k = createNode(key, undefined, ctx) const v = createNode(value, undefined, ctx) return new Pair(k, v) diff --git a/src/nodes/Scalar.ts b/src/nodes/Scalar.ts index b9d92cd6..982a65cd 100644 --- a/src/nodes/Scalar.ts +++ b/src/nodes/Scalar.ts @@ -61,7 +61,7 @@ export class Scalar extends NodeBase { return ctx?.keep ? this.value : toJS(this.value, arg, ctx) } - toString() { + toString(): string { return String(this.value) } } diff --git a/src/nodes/YAMLMap.ts b/src/nodes/YAMLMap.ts index 23df326f..6169e14f 100644 --- a/src/nodes/YAMLMap.ts +++ b/src/nodes/YAMLMap.ts @@ -20,7 +20,7 @@ export type MapLike = export function findPair( items: Iterable>, key: unknown -) { +): Pair | undefined { const k = isScalar(key) ? key.value : key for (const it of items) { if (isPair(it)) { @@ -57,7 +57,7 @@ export class YAMLMap extends Collection { * A generic collection parsing method that can be extended * to other node classes that inherit from YAMLMap */ - static from(schema: Schema, obj: unknown, ctx: CreateNodeContext) { + static from(schema: Schema, obj: unknown, ctx: CreateNodeContext): YAMLMap { const { keepUndefined, replacer } = ctx const map = new this(schema) const add = (key: unknown, value: unknown) => { diff --git a/src/nodes/YAMLSeq.ts b/src/nodes/YAMLSeq.ts index 39e78dfb..c3f96e99 100644 --- a/src/nodes/YAMLSeq.ts +++ b/src/nodes/YAMLSeq.ts @@ -98,7 +98,7 @@ export class YAMLSeq extends Collection { else this.items[idx] = value } - toJSON(_?: unknown, ctx?: ToJSContext) { + toJSON(_?: unknown, ctx?: ToJSContext): unknown[] { const seq: unknown[] = [] if (ctx?.onCreate) ctx.onCreate(seq) let i = 0 @@ -121,7 +121,7 @@ export class YAMLSeq extends Collection { }) } - static from(schema: Schema, obj: unknown, ctx: CreateNodeContext) { + static from(schema: Schema, obj: unknown, ctx: CreateNodeContext): YAMLSeq { const { replacer } = ctx const seq = new this(schema) if (obj && Symbol.iterator in Object(obj)) { diff --git a/src/nodes/addPairToJSMap.ts b/src/nodes/addPairToJSMap.ts index 08bb0608..54806eba 100644 --- a/src/nodes/addPairToJSMap.ts +++ b/src/nodes/addPairToJSMap.ts @@ -11,7 +11,7 @@ export function addPairToJSMap( ctx: ToJSContext | undefined, map: MapLike, { key, value }: Pair -) { +): MapLike { if (isNode(key) && key.addToJSMap) key.addToJSMap(ctx, map, value) // TODO: Should drop this special case for bare << handling else if (isMergeKey(ctx, key)) addMergeToJSMap(ctx, map, value) diff --git a/src/parse/cst-stringify.ts b/src/parse/cst-stringify.ts index e428c2c7..7ccb5510 100644 --- a/src/parse/cst-stringify.ts +++ b/src/parse/cst-stringify.ts @@ -6,10 +6,10 @@ import type { CollectionItem, Token } from './cst.ts' * Fair warning: This applies no validation whatsoever, and * simply concatenates the sources in their logical order. */ -export const stringify = (cst: Token | CollectionItem) => +export const stringify = (cst: Token | CollectionItem): string => 'type' in cst ? stringifyToken(cst) : stringifyItem(cst) -function stringifyToken(token: Token) { +function stringifyToken(token: Token): string { switch (token.type) { case 'block-scalar': { let res = '' @@ -42,7 +42,7 @@ function stringifyToken(token: Token) { } } -function stringifyItem({ start, key, sep, value }: CollectionItem) { +function stringifyItem({ start, key, sep, value }: CollectionItem): string { let res = '' for (const st of start) res += st.source if (key) res += stringifyToken(key) diff --git a/src/parse/cst-visit.ts b/src/parse/cst-visit.ts index 01b9aa9d..3961906c 100644 --- a/src/parse/cst-visit.ts +++ b/src/parse/cst-visit.ts @@ -1,4 +1,10 @@ -import type { CollectionItem, Document } from './cst.ts' +import type { + BlockMap, + BlockSequence, + CollectionItem, + Document, + FlowCollection +} from './cst.ts' const BREAK = Symbol('break visit') const SKIP = Symbol('skip children') @@ -39,7 +45,7 @@ export type Visitor = ( * visitor is called on item entry, next visitors are called after handling * a non-empty `key` and when exiting the item. */ -export function visit(cst: Document | CollectionItem, visitor: Visitor) { +export function visit(cst: Document | CollectionItem, visitor: Visitor): void { if ('type' in cst && cst.type === 'document') cst = { start: cst.start, value: cst.value } _visit(Object.freeze([]), cst, visitor) @@ -59,7 +65,10 @@ visit.SKIP = SKIP as symbol visit.REMOVE = REMOVE as symbol /** Find the item at `path` from `cst` as the root */ -visit.itemAtPath = (cst: Document | CollectionItem, path: VisitPath) => { +visit.itemAtPath = ( + cst: Document | CollectionItem, + path: VisitPath +): CollectionItem | undefined => { let item: CollectionItem = cst for (const [field, index] of path) { const tok = item?.[field] @@ -75,7 +84,10 @@ visit.itemAtPath = (cst: Document | CollectionItem, path: VisitPath) => { * * Throws an error if the collection is not found, which should never happen if the item itself exists. */ -visit.parentCollection = (cst: Document | CollectionItem, path: VisitPath) => { +visit.parentCollection = ( + cst: Document | CollectionItem, + path: VisitPath +): BlockMap | BlockSequence | FlowCollection => { const parent = visit.itemAtPath(cst, path.slice(0, -1)) const field = path[path.length - 1][0] const coll = parent?.[field] diff --git a/src/parse/cst.ts b/src/parse/cst.ts index c73cdcc3..a945ea03 100644 --- a/src/parse/cst.ts +++ b/src/parse/cst.ts @@ -174,7 +174,7 @@ export const isScalar = ( /* istanbul ignore next */ /** Get a printable representation of a lexer token */ -export function prettyToken(token: string) { +export function prettyToken(token: string): string { switch (token) { case BOM: return '' diff --git a/src/parse/lexer.ts b/src/parse/lexer.ts index ebe7f137..c8ab6437 100644 --- a/src/parse/lexer.ts +++ b/src/parse/lexer.ts @@ -171,7 +171,7 @@ export class Lexer { * * @returns A generator of lexical tokens */ - *lex(source: string, incomplete = false) { + *lex(source: string, incomplete = false): Generator { if (source) { if (typeof source !== 'string') throw TypeError('source is not a string') this.buffer = this.buffer ? this.buffer + source : source diff --git a/src/parse/line-counter.ts b/src/parse/line-counter.ts index f5ba111e..633eaa11 100644 --- a/src/parse/line-counter.ts +++ b/src/parse/line-counter.ts @@ -10,14 +10,14 @@ export class LineCounter { * Should be called in ascending order. Otherwise, call * `lineCounter.lineStarts.sort()` before calling `linePos()`. */ - addNewLine = (offset: number) => this.lineStarts.push(offset) + addNewLine = (offset: number): number => this.lineStarts.push(offset) /** * Performs a binary search and returns the 1-indexed { line, col } * position of `offset`. If `line === 0`, `addNewLine` has never been * called or `offset` is before the first known newline. */ - linePos = (offset: number) => { + linePos = (offset: number): { line: number; col: number } => { let low = 0 let high = this.lineStarts.length while (low < high) { diff --git a/src/parse/parser.ts b/src/parse/parser.ts index 2828e564..2d19e824 100644 --- a/src/parse/parser.ts +++ b/src/parse/parser.ts @@ -176,7 +176,7 @@ export class Parser { * * @returns A generator of tokens representing each directive, document, and other structure. */ - *parse(source: string, incomplete = false) { + *parse(source: string, incomplete = false): Generator { if (this.onNewLine && this.offset === 0) this.onNewLine(0) for (const lexeme of this.lexer.lex(source, incomplete)) yield* this.next(lexeme) @@ -186,7 +186,7 @@ export class Parser { /** * Advance the parser by the `source` of one lexical token. */ - *next(source: string) { + *next(source: string): Generator { this.source = source if (env.LOG_TOKENS) console.log('|', prettyToken(source)) @@ -237,7 +237,7 @@ export class Parser { private lexer = new Lexer(); /** Call at end of input to push out any remaining constructions */ - *end() { + *end(): Generator { while (this.stack.length > 0) yield* this.pop() } diff --git a/src/schema/yaml-1.1/omap.ts b/src/schema/yaml-1.1/omap.ts index f3baa1a8..cd14c3e4 100644 --- a/src/schema/yaml-1.1/omap.ts +++ b/src/schema/yaml-1.1/omap.ts @@ -16,17 +16,17 @@ export class YAMLOMap extends YAMLSeq { this.tag = YAMLOMap.tag } - add = YAMLMap.prototype.add.bind(this) - delete = YAMLMap.prototype.delete.bind(this) - get = YAMLMap.prototype.get.bind(this) - has = YAMLMap.prototype.has.bind(this) - set = YAMLMap.prototype.set.bind(this) + add: typeof YAMLMap.prototype.add = YAMLMap.prototype.add.bind(this) + delete: typeof YAMLMap.prototype.delete = YAMLMap.prototype.delete.bind(this) + get: typeof YAMLMap.prototype.get = YAMLMap.prototype.get.bind(this) + has: typeof YAMLMap.prototype.has = YAMLMap.prototype.has.bind(this) + set: typeof YAMLMap.prototype.set = YAMLMap.prototype.set.bind(this) /** * If `ctx` is given, the return type is actually `Map`, * but TypeScript won't allow widening the signature of a child method. */ - toJSON(_?: unknown, ctx?: ToJSContext) { + toJSON(_?: unknown, ctx?: ToJSContext): unknown[] { if (!ctx) return super.toJSON(_) const map = new Map() if (ctx?.onCreate) ctx.onCreate(map) @@ -45,7 +45,11 @@ export class YAMLOMap extends YAMLSeq { return map as unknown as unknown[] } - static from(schema: Schema, iterable: unknown, ctx: CreateNodeContext) { + static from( + schema: Schema, + iterable: unknown, + ctx: CreateNodeContext + ): YAMLOMap { const pairs = createPairs(schema, iterable, ctx) const omap = new this() omap.items = pairs.items diff --git a/src/schema/yaml-1.1/set.ts b/src/schema/yaml-1.1/set.ts index b1396fde..bafc3bc6 100644 --- a/src/schema/yaml-1.1/set.ts +++ b/src/schema/yaml-1.1/set.ts @@ -76,7 +76,7 @@ export class YAMLSet extends YAMLMap | null> { ctx?: StringifyContext, onComment?: () => void, onChompKeep?: () => void - ) { + ): string { if (!ctx) return JSON.stringify(this) if (this.hasAllNullValues(true)) return super.toString( @@ -87,7 +87,11 @@ export class YAMLSet extends YAMLMap | null> { else throw new Error('Set items must all have null values') } - static from(schema: Schema, iterable: unknown, ctx: CreateNodeContext) { + static from( + schema: Schema, + iterable: unknown, + ctx: CreateNodeContext + ): YAMLSet { const { replacer } = ctx const set = new this(schema) if (iterable && Symbol.iterator in Object(iterable)) diff --git a/src/stringify/foldFlowLines.ts b/src/stringify/foldFlowLines.ts index ea15a47c..b1734645 100644 --- a/src/stringify/foldFlowLines.ts +++ b/src/stringify/foldFlowLines.ts @@ -49,7 +49,7 @@ export function foldFlowLines( onFold, onOverflow }: FoldOptions = {} -) { +): string { if (!lineWidth || lineWidth < 0) return text if (lineWidth < minContentWidth) minContentWidth = 0 const endStep = Math.max(1 + minContentWidth, 1 + lineWidth - indent.length) diff --git a/src/stringify/stringifyNumber.ts b/src/stringify/stringifyNumber.ts index 455bc750..b2489953 100644 --- a/src/stringify/stringifyNumber.ts +++ b/src/stringify/stringifyNumber.ts @@ -5,7 +5,7 @@ export function stringifyNumber({ minFractionDigits, tag, value -}: Scalar) { +}: Scalar): string { if (typeof value === 'bigint') return String(value) const num = typeof value === 'number' ? value : Number(value) if (!isFinite(num)) return isNaN(num) ? '.nan' : num < 0 ? '-.inf' : '.inf' diff --git a/src/stringify/stringifyString.ts b/src/stringify/stringifyString.ts index 2de6aa37..b52ad9ce 100644 --- a/src/stringify/stringifyString.ts +++ b/src/stringify/stringifyString.ts @@ -346,7 +346,7 @@ export function stringifyString( ctx: StringifyContext, onComment?: () => void, onChompKeep?: () => void -) { +): string { const { implicitKey, inFlow } = ctx const ss: StringifyScalar = typeof item.value === 'string'