Skip to content

Upgrade esquery and use new option #100

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .eslintrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ overrides:
"@typescript-eslint/no-duplicate-imports": error
- files: "typings/**"
rules:
node/no-missing-import:
'@mysticatea/node/no-missing-import':
- error
- allowModules:
- estree
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"eslint-scope": "^5.0.0",
"eslint-visitor-keys": "^1.1.0",
"espree": "^6.2.1",
"esquery": "^1.0.1",
"esquery": "^1.4.0",
"lodash": "^4.17.15"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion src/ast/traverse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import type { Node } from "./nodes"
// Helpers
//------------------------------------------------------------------------------

const KEYS = Evk.unionWith({
export const KEYS = Evk.unionWith({
VAttribute: ["key", "value"],
VDirectiveKey: ["name", "argument", "modifiers"],
VDocumentFragment: ["children"],
Expand Down
8 changes: 5 additions & 3 deletions src/external/node-event-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* This file is copied from `eslint/lib/util/node-event-generator.js`
*/
import EventEmitter from "events"
import esquery, {Selector} from "esquery"
import esquery, {ESQueryOptions, Selector} from "esquery"
import union from "lodash/union"
import intersection from "lodash/intersection"
import memoize from "lodash/memoize"
Expand Down Expand Up @@ -187,6 +187,7 @@ const parseSelector = memoize<(rawSelector: string) => NodeSelector>(rawSelector
*/
export default class NodeEventGenerator {
emitter: EventEmitter
esqueryOptions: ESQueryOptions

private currentAncestry: Node[]
private enterSelectorsByNodeType: Map<string, NodeSelector[]>
Expand All @@ -198,8 +199,9 @@ export default class NodeEventGenerator {
* @param emitter - An event emitter which is the destination of events. This emitter must already
* have registered listeners for all of the events that it needs to listen for.
*/
constructor(emitter: EventEmitter) {
constructor(emitter: EventEmitter, esqueryOptions: ESQueryOptions) {
this.emitter = emitter
this.esqueryOptions = esqueryOptions
this.currentAncestry = []
this.enterSelectorsByNodeType = new Map()
this.exitSelectorsByNodeType = new Map()
Expand Down Expand Up @@ -260,7 +262,7 @@ export default class NodeEventGenerator {
* @param selector An AST selector descriptor
*/
private applySelector(node: Node, selector: NodeSelector): void {
if (esquery.matches(node, selector.parsedSelector, this.currentAncestry)) {
if (esquery.matches(node, selector.parsedSelector, this.currentAncestry, this.esqueryOptions)) {
this.emitter.emit(selector.rawSelector, node)
}
}
Expand Down
11 changes: 9 additions & 2 deletions src/parser-services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import type {
VDocumentFragment,
VAttribute,
} from "./ast"
import { traverseNodes } from "./ast"
import { getFallbackKeys, KEYS, traverseNodes } from "./ast/traverse"
import type { LocationCalculator } from "./common/location-calculator"
import type {
CustomBlockContext,
Expand Down Expand Up @@ -149,6 +149,10 @@ export function define(
// Traverse template body.
const generator = new NodeEventGenerator(
emitter as EventEmitter,
{
visitorKeys: KEYS,
fallback: getFallbackKeys,
},
)
traverseNodes(
rootAST.templateBody as VElement,
Expand Down Expand Up @@ -273,7 +277,10 @@ export function define(
}

// Traverse custom block.
const generator = new NodeEventGenerator(emitter)
const generator = new NodeEventGenerator(emitter, {
visitorKeys: parsedResult.visitorKeys,
fallback: getFallbackKeys,
})
traverseNodes(parsedResult.ast, {
visitorKeys: parsedResult.visitorKeys,
enterNode(n) {
Expand Down
42 changes: 42 additions & 0 deletions test/define-custom-blocks-visitor.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,18 @@ const noProgramExitRule = {
}
},
}
const siblingSelectorRule = {
create(context) {
return {
"* ~ *"(node) {
context.report({
node,
message: "* ~ *",
})
},
}
},
}

function createLinter(target = "json") {
const linter = new Linter()
Expand Down Expand Up @@ -417,6 +429,36 @@ describe("parserServices.defineCustomBlocksVisitor tests", () => {
)
})

it("should work even if used sibling selector.", () => {
const code = `
<i18n lang="json">
[42, 42]
</i18n>
`
const linter = createLinter()
linter.defineRule("test-for-sibling-selector", (context) =>
context.parserServices.defineCustomBlocksVisitor(
context,
jsonParser,
{
target: "json",
create: siblingSelectorRule.create,
}
)
)
const messages = linter.verify(code, {
...LINTER_CONFIG,
rules: {
"test-for-sibling-selector": "error",
},
})

assert.strictEqual(messages.length, 1)
assert.strictEqual(messages[0].message, "* ~ *")
assert.strictEqual(messages[0].line, 3)
assert.strictEqual(messages[0].column, 6)
})

describe("API tests", () => {
it("should work getAncestors().", () => {
const code = `
Expand Down
28 changes: 28 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -614,5 +614,33 @@ describe("Basic tests", () => {
assert.strictEqual(messages2.length, 1)
assert.strictEqual(messages2[0].message, "OK")
})

it("should work even if used sibling selector.", () => {
const code = "<template><div/><div/></template>"
const config = {
parser: PARSER_PATH,
rules: {
"test-rule": "error",
},
}
const linter = new Linter()

linter.defineParser(PARSER_PATH, require(PARSER_PATH))
linter.defineRule("test-rule", (context) =>
context.parserServices.defineTemplateBodyVisitor({
"* ~ *"(node) {
context.report({ node, message: "OK" })
},
})
)

const messages1 = linter.verify(code, config)
const messages2 = linter.verify(linter.getSourceCode(), config)

assert.strictEqual(messages1.length, 1)
assert.strictEqual(messages1[0].message, "OK")
assert.strictEqual(messages2.length, 1)
assert.strictEqual(messages2[0].message, "OK")
})
})
})
40 changes: 35 additions & 5 deletions typings/esquery/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,32 @@
* See LICENSE file in root directory for full license.
*/

export type Selector = AdjacentSelector | AttributeSelector | ChildSelector | ClassSelector | CompoundSelector | DescendantSelector | FieldSelector | HasSelector | IdentifierSelector | MatchesSelector | NotSelector | NthChildSelector | NthLastChildSelector | SiblingSelector | WildcardSelector
import type { Node } from "../../src/ast"
// eslint-disable-next-line @mysticatea/node/no-missing-import
import type { VisitorKeys } from "../eslint-visitor-keys"

export type Selector =
| AdjacentSelector
| AttributeSelector
| ChildSelector
| ClassSelector
| CompoundSelector
| DescendantSelector
| FieldSelector
| HasSelector
| IdentifierSelector
| MatchesSelector
| NotSelector
| NthChildSelector
| NthLastChildSelector
| SiblingSelector
| WildcardSelector

export type TraverseOptionFallback = (node: Node) => readonly string[]
export interface ESQueryOptions {
visitorKeys?: VisitorKeys
fallback?: TraverseOptionFallback
}

export interface AdjacentSelector {
type: "adjacent"
Expand All @@ -16,7 +41,7 @@ export interface AttributeSelector {
type: "attribute"
name: string
operator: string | null | undefined
value: { type: string, value: any }
value: { type: string; value: any }
}

export interface ChildSelector {
Expand Down Expand Up @@ -68,13 +93,13 @@ export interface NotSelector {
export interface NthChildSelector {
type: "nth-child"
right: Selector
index: { type: string, value: any }
index: { type: string; value: any }
}

export interface NthLastChildSelector {
type: "nth-last-child"
right: Selector
index: { type: string, value: any }
index: { type: string; value: any }
}

export interface SiblingSelector {
Expand All @@ -89,6 +114,11 @@ export interface WildcardSelector {

declare const esquery: {
parse(query: string): Selector
matches(node: object, selector: Selector, ancestry: object[]): boolean
matches(
node: object,
selector: Selector,
ancestry: object[],
options?: ESQueryOptions,
): boolean
}
export default esquery