Skip to content

Commit

Permalink
feat: traverse ast nodes
Browse files Browse the repository at this point in the history
  • Loading branch information
JounQin committed Jul 29, 2019
1 parent 33ec2a2 commit 6a71e25
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 66 deletions.
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
"description": "ESLint Parser/Plugin for MDX",
"repository": "git@github.com:rx-ts/eslint-plugin-mdx.git",
"author": "JounQin <admin@1stg.me>",
"main": "./dist",
"main": "dist",
"license": "MIT",
"files": [
"dist"
"dist",
"types.d.ts"
],
"scripts": {
"prepublishOnly": "yarn build",
Expand All @@ -20,7 +21,6 @@
},
"dependencies": {
"@mdx-js/mdx": "^1.1.0",
"eslint-utils": "^1.4.0",
"eslint-visitor-keys": "^1.0.0",
"remark-mdx": "^1.1.0",
"remark-parse": "^7.0.0",
Expand Down
109 changes: 49 additions & 60 deletions src/parser.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
// eslint-disable-next-line @typescript-eslint/no-triple-slash-reference
/// <reference path="../shim.d.ts" />
/// <reference path="../types.d.ts" />

import { parse as esParse } from 'espree'
import remarkMdx from 'remark-mdx'
import remarkParse from 'remark-parse'
import remarkStringify from 'remark-stringify'
import unified from 'unified'

import { traverse } from './traverse'

import { Position, Parent } from 'unist'
import { AST, Linter } from 'eslint'
import { Statement, ModuleDeclaration } from 'estree'

const transNodePos = (position: Position) => {
const start = position.start.offset
Expand Down Expand Up @@ -39,73 +40,61 @@ export const parseForESLint = (

const tokens: AST.Token[] = []

return {
ast: {
...transNodePos(root.position),
comments: [],
body: root.children.reduce<Array<Statement | ModuleDeclaration>>(
(nodes, { position, type }) => {
if (!['export', 'import', 'jsx'].includes(type)) {
return nodes
}

const rawText = getRawText(code, position)
traverse(root, {
enter({ position, type }) {
if (!['export', 'import', 'jsx'].includes(type)) {
return
}

let node = {
...transNodePos(position),
value: rawText,
}
const rawText = getRawText(code, position)

const { tokens: esTokens, ...AST } = esParse(
rawText,
options,
) as AST.Program
const node = transNodePos(position)

const offset = node.start - AST.range[0]
const { tokens: esTokens, ...AST } = esParse(
rawText,
options,
) as AST.Program

node = {
...AST,
...node,
}
const offset = node.start - AST.range[0]

nodes.push(node as any)
tokens.push(
...esTokens.map(token => {
const {
loc: { start: tokenStart, end: tokenEnd },
} = token
const start = token.range[0] + offset
const end = token.range[1] + offset
const startLine = node.loc.start.line + tokenStart.line - 1
const startColumn = node.loc.start.column + tokenStart.column - 1
return {
...token,
start,
end,
range: [start, end],
loc: {
start: {
line: startLine,
column: startColumn,
},
end: {
line: startLine + tokenEnd.line - 1,
column: startLine + tokenEnd.column - 1,
},
},
} as AST.Token
}),
)
tokens.push(
...esTokens.map(token => {
const {
loc: { start: tokenStart, end: tokenEnd },
} = token
const start = token.range[0] + offset
const end = token.range[1] + offset
const startLine = node.loc.start.line + tokenStart.line - 1
const startColumn = node.loc.start.column + tokenStart.column - 1
return {
...token,
start,
end,
range: [start, end],
loc: {
start: {
line: startLine,
column: startColumn,
},
end: {
line: startLine + tokenEnd.line - 1,
column: startLine + tokenEnd.column - 1,
},
},
} as AST.Token
}),
)
},
})

return nodes
},
[],
),
return {
ast: {
...transNodePos(root.position),
comments: [],
body: [],
type: 'Program',
sourceType: 'module',
tokens,
},
scopeManager: null,
visitorKeys: null,
}
}
31 changes: 31 additions & 0 deletions src/traverse.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { Node, Parent } from 'unist'

export type Traverser = (node: Node, parent?: Parent) => void

export interface TraverseOptions {
enter: Traverser
}

export class Traverse {
private _enter: Traverser

constructor({ enter }: TraverseOptions) {
this._enter = enter
}

traverse(node: Node, parent?: Parent) {
if (!node) {
return
}

this._enter(node, parent)

if (node.children) {
parent = node as Parent
parent.children.forEach(child => this.traverse(child, parent))
}
}
}

export const traverse = (root: Parent, options: TraverseOptions) =>
new Traverse(options).traverse(root)
2 changes: 0 additions & 2 deletions shim.d.ts → types.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
declare module 'eslint-utils' {}

declare module 'espree' {
import * as estree from 'estree'

Expand Down
2 changes: 1 addition & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1405,7 +1405,7 @@ eslint-scope@^5.0.0:
esrecurse "^4.1.0"
estraverse "^4.1.1"

eslint-utils@^1.3.0, eslint-utils@^1.3.1, eslint-utils@^1.4.0:
eslint-utils@^1.3.0, eslint-utils@^1.3.1:
version "1.4.0"
resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.0.tgz#e2c3c8dba768425f897cf0f9e51fe2e241485d4c"
integrity sha512-7ehnzPaP5IIEh1r1tkjuIrxqhNkzUJa9z3R92tLJdZIVdWaczEhr3EbhGtsMrVxi1KeR8qA7Off6SWc5WNQqyQ==
Expand Down

0 comments on commit 6a71e25

Please sign in to comment.