Skip to content

Commit

Permalink
feat: add leading and trailing fields
Browse files Browse the repository at this point in the history
Signed-off-by: Lexus Drumgold <[email protected]>
  • Loading branch information
unicornware committed Mar 5, 2024
1 parent a80b220 commit 4b9cfb3
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 30 deletions.
17 changes: 17 additions & 0 deletions __tests__/setup/chai.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* @file Test Setup - chai
* @module tests/setup/chai
* @see https://chaijs.com
*/

import { JestExtend as extend } from '@vitest/expect'
import chaiEach from 'chai-each'
import { chai } from 'vitest'

/**
* initialize chai plugins.
*
* @see https://github.com/jamesthomasonjr/chai-each
*/
extend(chai, chai.util)
chai.use(chaiEach)
2 changes: 1 addition & 1 deletion __tests__/setup/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
* @module tests/setup
*/

export {}
import './chai'
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@
"@vates/toggle-scripts": "1.0.0",
"@vitest/coverage-v8": "1.3.1",
"chai": "5.1.0",
"chai-each": "0.0.1",
"cross-env": "7.0.3",
"cspell": "8.5.0",
"devlop": "1.1.0",
Expand Down
56 changes: 46 additions & 10 deletions src/__snapshots__/util.integration.snap
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,26 @@ Program
│ property: Identifier<colon>
│ computed: false
│ optional: false
leadingComments:
comments:
│ ├─0 Block "*\\n * Construct a union of \`T\` and \`undefined\`.\\n *\\n * @template T\\n * @typedef {import('@flex-development/tutils').Optional<T>} Optional\\n "
│ │ leading: true
│ │ trailing: false
│ ├─1 Block "*\\n * @typedef {import('micromark-util-types').Code} Code\\n * @typedef {import('micromark-util-types').Construct} Construct\\n * @typedef {import('micromark-util-types').Effects} Effects\\n * @typedef {import('micromark-util-types').State} State\\n * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext\\n "
│ │ leading: true
│ │ trailing: false
│ └─2 Block "*\\n * Guard whether \`code\` can come before a gemoji.\\n *\\n * @see {@linkcode Code}\\n *\\n * @this {TokenizeContext}\\n *\\n * @param {Code} code - Previous character code\\n * @return {boolean} \`true\` if \`code\` allowed before construct\\n "
│ comments:
│ leading: true
│ trailing: false
│ leadingComments:
│ ├─0 Block "*\\n * Construct a union of \`T\` and \`undefined\`.\\n *\\n * @template T\\n * @typedef {import('@flex-development/tutils').Optional<T>} Optional\\n "
│ │ leading: true
│ │ trailing: false
│ ├─1 Block "*\\n * @typedef {import('micromark-util-types').Code} Code\\n * @typedef {import('micromark-util-types').Construct} Construct\\n * @typedef {import('micromark-util-types').Effects} Effects\\n * @typedef {import('micromark-util-types').State} State\\n * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext\\n "
│ │ leading: true
│ │ trailing: false
│ └─2 Block "*\\n * Guard whether \`code\` can come before a gemoji.\\n *\\n * @see {@linkcode Code}\\n *\\n * @this {TokenizeContext}\\n *\\n * @param {Code} code - Previous character code\\n * @return {boolean} \`true\` if \`code\` allowed before construct\\n "
│ leading: true
│ trailing: false
└─4 ExportDefaultDeclaration
declaration: ObjectExpression
properties:
Expand All @@ -66,40 +78,64 @@ Program
│ computed: false
│ key: Identifier<name>
│ kind: "init"
│ leadingComments:
│ └─0 Block "*\\n * Construct name.\\n "
│ comments:
│ └─0 Block "*\\n * Construct name.\\n "
│ leading: true
│ trailing: false
│ leadingComments:
│ └─0 Block "*\\n * Construct name.\\n "
│ leading: true
│ trailing: false
├─1 Property
│ method: false
│ shorthand: true
│ computed: false
│ key: Identifier<previous>
│ kind: "init"
│ leadingComments:
│ └─0 Block "*\\n * Guard whether \`code\` can come before this construct.\\n *\\n * @see {@linkcode Code}\\n *\\n * @this {TokenizeContext}\\n *\\n * @param {Code} code - Previous character code\\n * @return {boolean} \`true\` if \`code\` allowed before construct\\n "
│ comments:
│ └─0 Block "*\\n * Guard whether \`code\` can come before this construct.\\n *\\n * @see {@linkcode Code}\\n *\\n * @this {TokenizeContext}\\n *\\n * @param {Code} code - Previous character code\\n * @return {boolean} \`true\` if \`code\` allowed before construct\\n "
│ leading: true
│ trailing: false
│ leadingComments:
│ └─0 Block "*\\n * Guard whether \`code\` can come before this construct.\\n *\\n * @see {@linkcode Code}\\n *\\n * @this {TokenizeContext}\\n *\\n * @param {Code} code - Previous character code\\n * @return {boolean} \`true\` if \`code\` allowed before construct\\n "
│ leading: true
│ trailing: false
└─2 Property
method: true
shorthand: false
computed: false
key: Identifier<tokenize>
kind: "init"
leadingComments:
└─0 Block "*\\n * Set up a state machine to process character codes.\\n *\\n * @see {@linkcode Code}\\n * @see {@linkcode Effects}\\n * @see {@linkcode State}\\n *\\n * @this {TokenizeContext}\\n *\\n * @param {Effects} effects - Context object to transition state machine\\n * @param {State} ok - Success state function\\n * @param {State} nok - Error state function\\n * @return {State} Initial state\\n "
comments:
└─0 Block "*\\n * Set up a state machine to process character codes.\\n *\\n * @see {@linkcode Code}\\n * @see {@linkcode Effects}\\n * @see {@linkcode State}\\n *\\n * @this {TokenizeContext}\\n *\\n * @param {Effects} effects - Context object to transition state machine\\n * @param {State} ok - Success state function\\n * @param {State} nok - Error state function\\n * @return {State} Initial state\\n "
leadingComments:
└─0 Block "*\\n * Gemoji (\`:+1:\`) construct.\\n *\\n * @type {Construct}\\n "
leading: true
trailing: false
leadingComments:
└─0 Block "*\\n * Set up a state machine to process character codes.\\n *\\n * @see {@linkcode Code}\\n * @see {@linkcode Effects}\\n * @see {@linkcode State}\\n *\\n * @this {TokenizeContext}\\n *\\n * @param {Effects} effects - Context object to transition state machine\\n * @param {State} ok - Success state function\\n * @param {State} nok - Error state function\\n * @return {State} Initial state\\n "
leading: true
trailing: false
comments:
└─0 Block "*\\n * Gemoji (\`:+1:\`) construct.\\n *\\n * @type {Construct}\\n "
leading: true
trailing: false
leadingComments:
└─0 Block "*\\n * Gemoji (\`:+1:\`) construct.\\n *\\n * @type {Construct}\\n "
leading: true
trailing: false
sourceType: "module"
comments:
├─0 Block "*\\n * @file Fixtures - gemojiShortcode\\n * @module fixtures/gemojiShortcode\\n "
│ leading: true
│ trailing: false
└─1 Line " # sourceMappingURL=gemoji-shortcode.mjs.map"
leading: false
trailing: true
leadingComments:
└─0 Block "*\\n * @file Fixtures - gemojiShortcode\\n * @module fixtures/gemojiShortcode\\n "
leading: true
trailing: false
trailingComments:
└─0 Line " # sourceMappingURL=gemoji-shortcode.mjs.map"
leading: false
trailing: true
`;
37 changes: 26 additions & 11 deletions src/__tests__/visitor.functional.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import PURE_COMMENTS from '#fixtures/pure-comments'
import type { State } from '#src/types'
import * as utils from '#src/utils'
import type { Spy } from '#tests/interfaces'
import type { NewExpression, Program } from 'estree'
import type { Comment, NewExpression, Program } from 'estree'
import testSubject from '../visitor'

describe('functional:visitor', () => {
Expand Down Expand Up @@ -69,14 +69,15 @@ describe('functional:visitor', () => {
testSubject(state)(node, 'value')
})

it('should attach leading comments', () => {
it('should collect leading comments', () => {
// Arrange
const property: string = 'leadingComments'
const check = (node: Comment): boolean => !!node.leading

// Expect
expect(slice).toHaveBeenCalledOnce()
expect(slice).toHaveBeenCalledWith(state, node)
expect(node).to.have.deep.property(property, [state.comments[1]])
expect(node).to.have.deep.property('comments', [state.comments[1]])
expect(node).to.have.property('comments').each.satisfy(check)
})
})
})
Expand Down Expand Up @@ -107,11 +108,20 @@ describe('functional:visitor', () => {
comments: [
{
position: {
end: { column: 38, line: 2, offset: 38 },
start: { column: 1, line: 2, offset: 1 }
end: { column: 4, line: 4, offset: 79 },
start: { column: 1, line: 1, offset: 0 }
},
type: 'Block',
value:
'*\n * @file Fixtures - gemojiShortcode\n * @module fixtures/gemojiShortcode\n '
},
{
position: {
end: { column: 47, line: 134, offset: 3323 },
start: { column: 1, line: 134, offset: 3277 }
},
type: 'Line',
value: '# sourceMappingURL=polyfill.mjs.map'
value: '# sourceMappingURL=gemoji-shortcode.mjs.map'
}
],
index: 0
Expand All @@ -120,7 +130,7 @@ describe('functional:visitor', () => {
node = {
body: [],
position: {
end: { column: 1, line: 3, offset: 39 },
end: { column: 1, line: 135, offset: 3324 },
start: { column: 1, line: 1, offset: 0 }
},
sourceType: 'module',
Expand All @@ -133,10 +143,15 @@ describe('functional:visitor', () => {
testSubject(state, leave)(node, undefined)
})

it('should attach comments', () => {
it('should attach all comments', () => {
// Arrange
const { comments } = state

// Expect
expect(slice).toHaveBeenCalledWith(state, node)
expect(node).to.have.deep.property('comments', state.comments)
expect(node).to.have.deep.property('trailingComments', state.comments)
expect(node).to.have.deep.property('comments', comments)
expect(node).to.have.deep.property('leadingComments', [comments[0]])
expect(node).to.have.deep.property('trailingComments', [comments[1]])
})
})
})
Expand Down
23 changes: 22 additions & 1 deletion src/utils/slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ import type { State } from '#src/types'
import type { Comment, Node } from 'estree'
import compare from './compare'

declare module 'estree' {
interface Comment {
leading?: boolean | undefined
trailing?: boolean | undefined
}
}

/**
* Get a comments slice.
*
Expand Down Expand Up @@ -34,7 +41,21 @@ function slice(this: void, state: State, node: Node): Comment[] {
while (
state.comments[state.index] &&
compare(state.comments[state.index], node, state.leave) < 1
) result.push(state.comments[state.index++]!)
) {
/**
* Comment node.
*
* @const {Comment} comment
*/
const comment: Comment = state.comments[state.index++]!

// set fields
comment.leading = state.leave !== true
comment.trailing = state.leave === true

// add comment to slice
result.push(comment)
}

return result
}
Expand Down
12 changes: 5 additions & 7 deletions src/visitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,9 @@ function visitor(state: State, leave?: boolean): Visitor {

if (keycheck(key)) {
if ((state.leave = !!leave)) {
node.comments = []
node.trailingComments = []
node.trailingComments.push(...slice(state, node))
node.comments.push(...node.leadingComments!)
node.comments.push(...node.trailingComments)
node.comments!.push(...slice(state, node))
node.leadingComments = node.comments!.filter(n => n.leading)
node.trailingComments = node.comments!.filter(n => n.trailing)

for (const [key, value] of Object.entries(node)) {
switch (key) {
Expand All @@ -57,8 +55,8 @@ function visitor(state: State, leave?: boolean): Visitor {
}
}
} else {
node.leadingComments = []
node.leadingComments.push(...slice(state, node))
node.comments = []
node.comments.push(...slice(state, node))
}
}

Expand Down
8 changes: 8 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1462,6 +1462,7 @@ __metadata:
"@vates/toggle-scripts": "npm:1.0.0"
"@vitest/coverage-v8": "npm:1.3.1"
chai: "npm:5.1.0"
chai-each: "npm:0.0.1"
cross-env: "npm:7.0.3"
cspell: "npm:8.5.0"
devlop: "npm:1.1.0"
Expand Down Expand Up @@ -3238,6 +3239,13 @@ __metadata:
languageName: node
linkType: hard

"chai-each@npm:0.0.1":
version: 0.0.1
resolution: "chai-each@npm:0.0.1"
checksum: 10/bc4dc57fd60687a2dbe212e4a9cfc6e4598931749f66a48d3aa800dd821ec3f7e31bd53937fb16ff6f5936be94e11e50f3baee4b243a838ceeb46e6b7bfa72e3
languageName: node
linkType: hard

"chai@npm:5.1.0":
version: 5.1.0
resolution: "chai@npm:5.1.0"
Expand Down

0 comments on commit 4b9cfb3

Please sign in to comment.