diff --git a/src/types/__tests__/state.spec-d.ts b/src/types/__tests__/state.spec-d.ts index 9caf3e9..76ae3dd 100644 --- a/src/types/__tests__/state.spec-d.ts +++ b/src/types/__tests__/state.spec-d.ts @@ -3,6 +3,7 @@ * @module esast-util-attach-comments/types/tests/unit-d/State */ +import type { Optional } from '@flex-development/tutils' import type { Comment } from 'estree' import type TestSubject from '../state' @@ -16,4 +17,10 @@ describe('unit-d:types/State', () => { it('should match [index: number]', () => { expectTypeOf().toHaveProperty('index').toEqualTypeOf() }) + + it('should match [leave?: boolean]', () => { + expectTypeOf() + .toHaveProperty('leave') + .toEqualTypeOf>() + }) }) diff --git a/src/types/state.ts b/src/types/state.ts index 7bfced8..bbce909 100644 --- a/src/types/state.ts +++ b/src/types/state.ts @@ -22,6 +22,11 @@ type State = { * Index of current comment. */ index: number + + /** + * Visiting nodes on exit? + */ + leave?: boolean } export type { State as default } diff --git a/src/utils/__tests__/compare.spec.ts b/src/utils/__tests__/compare.spec.ts index 1a6264d..d69d812 100644 --- a/src/utils/__tests__/compare.spec.ts +++ b/src/utils/__tests__/compare.spec.ts @@ -8,7 +8,15 @@ import testSubject from '../compare' describe('unit:utils/compare', () => { it('should return Number.NaN if comparison cannot be made', () => { - expect(testSubject({}, {}, true)).to.be.NaN + // Arrange + const cases: Parameters[] = [ + [], + [{}, null], + [null, {}, true] + ] + + // Act + Expect + cases.forEach(params => expect(testSubject(...params)).to.be.NaN) }) describe('position', () => { diff --git a/src/utils/__tests__/slice.spec.ts b/src/utils/__tests__/slice.spec.ts new file mode 100644 index 0000000..e3f9ba5 --- /dev/null +++ b/src/utils/__tests__/slice.spec.ts @@ -0,0 +1,61 @@ +/** + * @file Unit Tests - slice + * @module esast-util-attach-comments/utils/tests/unit/slice + */ + +import type { State } from '#src/types' +import type { NewExpression } from 'estree' +import testSubject from '../slice' + +describe('unit:utils/slice', () => { + let node: NewExpression + let state: State + + beforeAll(() => { + state = { + comments: [ + { + position: { + end: { column: 33, line: 11, offset: 411 }, + start: { column: 18, line: 11, offset: 396 } + }, + type: 'Block', + value: ' @__PURE__ ' + }, + { + position: { + end: { column: 27, line: 14, offset: 535 }, + start: { column: 12, line: 14, offset: 520 } + }, + type: 'Block', + value: ' @__PURE__ ' + } + ], + index: 0 + } + + node = { + arguments: [], + callee: { + name: 'Set', + position: { + end: { column: 41, line: 11, offset: 419 }, + start: { column: 38, line: 11, offset: 416 } + }, + type: 'Identifier' + }, + position: { + end: { column: 43, line: 11, offset: 421 }, + start: { column: 34, line: 11, offset: 412 } + }, + type: 'NewExpression' + } + }) + + it('should return slice from state.comments', () => { + expect(testSubject(state, node)) + .to.be.an('array') + .of.length(1) + .with.deep.ordered.members([state.comments[0]]) + }) +}) diff --git a/src/utils/compare.ts b/src/utils/compare.ts index c15bb6e..3e5ee1f 100644 --- a/src/utils/compare.ts +++ b/src/utils/compare.ts @@ -3,6 +3,7 @@ * @module esast-util-attach-comments/utils/compare */ +import type { Nilable } from '@flex-development/tutils' import type { Comment, Node } from 'estree' declare module 'estree' { @@ -28,15 +29,15 @@ type Field = 'end' | 'start' * * @this {void} * - * @param {Pick} comment - Comment node - * @param {Pick} node - Node to check + * @param {Nilable>?} [comment] - Comment node + * @param {Nilable>?} [node] - Node to check * @param {boolean?} [end] - Use `end` position of `node` in comparsion? * @return {number} Comparison result */ function compare( this: void, - comment: Pick, - node: Pick, + comment?: Nilable>, + node?: Nilable>, end?: boolean ): number { /** @@ -47,7 +48,7 @@ function compare( const field: Field = end ? 'end' : 'start' // compare positions - if (comment.position?.start && node.position?.[field]) { + if (comment?.position?.start && node?.position?.[field]) { return ( comment.position.start.line - node.position[field].line || comment.position.start.column - node.position[field].column diff --git a/src/utils/index.ts b/src/utils/index.ts index 57b7f2b..de1bc27 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -5,3 +5,4 @@ export { default as compare } from './compare' export { default as keycheck } from './keycheck' +export { default as slice } from './slice' diff --git a/src/utils/slice.ts b/src/utils/slice.ts new file mode 100644 index 0000000..973d8a9 --- /dev/null +++ b/src/utils/slice.ts @@ -0,0 +1,42 @@ +/** + * @file Utilities - slice + * @module esast-util-attach-comments/utils/slice + */ + +import type { State } from '#src/types' +import type { Comment, Node } from 'estree' +import compare from './compare' + +/** + * Get a comments slice. + * + * @see {@linkcode Comment} + * @see {@linkcode Node} + * @see {@linkcode State} + * + * @internal + * + * @this {void} + * + * @param {State} state - Visitor state + * @param {Node} node - Node being visited + * @return {Comment[]} Slice from `state.comments` + */ +function slice(this: void, state: State, node: Node): Comment[] { + /** + * Slice result. + * + * @const {Comment[]} result + */ + const result: Comment[] = [] + + // get slice + while ( + state.comments[state.index] && + compare(state.comments[state.index], node, state.leave) < 1 + ) result.push(state.comments[state.index++]!) + + return result +} + +export default slice