Giter Club home page Giter Club logo

esquery's People

Contributors

azu avatar brettz9 avatar cherryblossom000 avatar goloroden avatar jrfeenst avatar jupenur avatar jviide avatar markkoester avatar michaelficarra avatar mysticatea avatar nikaspran avatar not-an-aardvark avatar nwronski avatar nzakas avatar ota-meshi avatar papandreou avatar qard avatar quramy avatar sebmck avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

esquery's Issues

How to match import with given specifier (ie. match on list of nodes)

I'm trying to use grasp with squery which I think uses esquery under the hood?
How do I match an import with a given specifier:

I can't do import-dec[specifiers=x] since specifiers is a list of nodes, such as import {x, y z} from 'v'

const find = 'import-dec[specifiers=x] ~ class-dec[id=#CoolGang]'
const replace = `class {{.id}} {{.body}}`

const replacer = grasp.replace('squery', find, replace)

travis build failing in 0.6 and 0.8 due to ^ versions in transitive dependencies

npm ERR! Error: No compatible version found: bn.js@'^0.15.0'
npm ERR! Valid install targets:
npm ERR! ["0.1.0","0.1.1","0.1.2","0.1.3","0.1.4","0.1.5","0.1.6","0.1.7","0.2.0","0.2.1","0.2.2","0.3.0","0.3.1","0.4.0","0.4.1","0.4.2","0.4.3","0.4.4","0.5.0","0.5.1","0.5.2","0.5.3","0.5.4","0.6.0","0.7.0","0.7.1","0.8.0","0.8.1","0.9.0","0.10.0","0.10.1","0.11.0","0.11.1","0.11.2","0.11.3","0.11.4","0.11.5","0.11.6","0.11.7","0.12.0","0.13.0","0.13.1","0.13.2","0.13.3","0.14.0","0.14.1","0.14.2","0.15.0","0.15.1","0.15.2","0.16.0"]
npm ERR!     at installTargetsError (/home/travis/.nvm/v0.8.28/lib/node_modules/npm/lib/cache.js:719:10)
npm ERR!     at /home/travis/.nvm/v0.8.28/lib/node_modules/npm/lib/cache.js:641:10

I say we drop them from the CI process. Nobody is seriously using them anyway (or at least shouldn't be due to security concerns).

Do not bundle estraverse dependency?

I'd like to suggest creating another rollup artifact without the bundled estraverse.

This would have a few advantages:

  1. Smaller footprint if estraverse is already included in dependencies of the project that brings this in.
  2. Allow modifying estraverse.VisitorKeys, which would allow using esquery with things like TypeScript and JSX (and be a sensible workaround for #57)
  3. Work more canonically with Node.js projects (i.e. ability to use require cache, dependency resolutions and so on)

If this works, I can prepare a small PR over the next few days. To keep backwards compatibility, I can set it up as a new output artifact that wouldn't impact anything - would that work?

Add getting started / usage to readme

I’ve found that each time I use esquery I have a question how to use it? Is it conventional, like other estools: var query = require('esquery').query or is it plain function var query = require('esquery')? API is also not clear at first.
Examples could be found in tests, of course, but is there a sense to add short description to the readme, to give new users answer to such questions?

RegExp slash escapes not parsed correctly

Using the following snippet in the ESQuery demo:

var f = "foo/bar";

None of these queries is parsed correctly and all fail with an error:

[value=/foo\/bar/]

Invalid regular expression: /foo/: \ at end of pattern

[value=/foo\\/bar/]

Expected " " or "]" but "b" found.

[value=/foo\\\\/bar/]

Expected " " or "]" but "b" found.

I'm using tsquery to write an import-location-specific TSLint rule for RxJS and the RegExp issue appears to be an upstream problem with this package.

esquery.matches does not respect subject indicator.

var esprima = require('esprima');
var esquery = require('esquery');
var ast = esprima.parse('a + !b');
var query = esquery.parse('BinaryExpression! > UnaryExpression.right');

// should be true (does not work)
console.log(esquery.matches(ast.body[0].expression, query, [ast.body[0], ast]));
// should be false (does not work)
console.log(esquery.matches(ast.body[0].expression.right, query, [ast.body[0].expression, ast.body[0], ast]));

// should include only the BinaryExpression (works)
console.log(JSON.stringify(esquery.match(ast, query, []), null, 4));

Error thrown on nth-child with ExperimentalSpreadSyntax

Minimal reproduceable example:

https://astexplorer.net/#/gist/e0fb7d08090a532c3cdce571593671b2/622c0d4fed220a6b8d6655f0f746916aeb8bfb60

The :nth-child selector throws an error if object spread syntax (type of ExperimentalSpreadSyntax) is encountered.

Stack trace:

> eslint .

Cannot read property 'length' of undefined
TypeError: Cannot read property 'length' of undefined
    at nthChild (/Users/andrew/Documents/Code/vvv/www/editor/htdocs/wp-content/plugins/gutenberg/node_modules/esquery/esquery.js:256:34)
    at matches (/Users/andrew/Documents/Code/vvv/www/editor/htdocs/wp-content/plugins/gutenberg/node_modules/esquery/esquery.js:158:25)
    at Function.matches (/Users/andrew/Documents/Code/vvv/www/editor/htdocs/wp-content/plugins/gutenberg/node_modules/esquery/esquery.js:103:25)
    at NodeEventGenerator.applySelector (/Users/andrew/Documents/Code/vvv/www/editor/htdocs/wp-content/plugins/gutenberg/node_modules/eslint/lib/util/node-event-generator.js:250:21)
    at NodeEventGenerator.applySelectors (/Users/andrew/Documents/Code/vvv/www/editor/htdocs/wp-content/plugins/gutenberg/node_modules/eslint/lib/util/node-event-generator.js:278:22)
    at NodeEventGenerator.enterNode (/Users/andrew/Documents/Code/vvv/www/editor/htdocs/wp-content/plugins/gutenberg/node_modules/eslint/lib/util/node-event-generator.js:294:14)
    at CodePathAnalyzer.enterNode (/Users/andrew/Documents/Code/vvv/www/editor/htdocs/wp-content/plugins/gutenberg/node_modules/eslint/lib/code-path-analysis/code-path-analyzer.js:608:23)
    at Traverser.enter [as _enter] (/Users/andrew/Documents/Code/vvv/www/editor/htdocs/wp-content/plugins/gutenberg/node_modules/eslint/lib/linter.js:1006:32)
    at Traverser._traverse (/Users/andrew/Documents/Code/vvv/www/editor/htdocs/wp-content/plugins/gutenberg/node_modules/eslint/lib/util/traverser.js:132:14)
    at Traverser._traverse (/Users/andrew/Documents/Code/vvv/www/editor/htdocs/wp-content/plugins/gutenberg/node_modules/eslint/lib/util/traverser.js:147:30)

Throwing line:

for (i = 0, l = keys.length; i < l; ++i) {

Real-world use-case:

I am trying to create a no-restricted-syntax ESLint rule for forbidding all but ArrayExpression as the second argument of Lodash methods which accept path argument:

CallExpression[callee.name=/^(invokeMap|get|has|hasIn|invoke|result|set|setWith|unset|update|updateWith)$/] > :not(ArrayExpression):nth-child(2)

This works in isolated usage:

https://astexplorer.net/#/gist/e0fb7d08090a532c3cdce571593671b2/b70d4572529d872e27f8c3df62c4ce0be43dba88

...but with above error, fails with the object spread syntax.

Add a release log or annotate the tags in github releases

It'd be great if there was release notes for this project.
As a user, it's hard to parse all of the commit messages in the history to determine what's actually changed from version to version.

A markdown file in the repo root is one way people do this.
Another way is via the github releases UI.

"Child in specific slot" selector?

Hi, I'm thinking about using esquery for matching some pretty deeply nested constructs. I need to differentiate between eg. the object and property of a MemberExpression, so I cannot use the child selector, as it will match a child in either position:

const q = esquery.parse('MemberExpression > Identifier[name=foo]');
const ast = require('acorn').parse("foo.foo()")
console.log(esquery.match(ast, q));
[ Node { type: 'Identifier', start: 0, end: 3, name: 'foo' },
  Node { type: 'Identifier', start: 4, end: 7, name: 'foo' } ]

I know that I drop into "attribute mode" and achieve what I need using a query like:

MemberExpression[property.name=foo]

... but since the asts I need to match are much deeper than that, it would be really awkward to have to spell out the rest of the subtree like that with lots of repeated [property.foo.bar=123][property.foo.quux=abc]. It would be much nicer if I could use something like the > selector to cover the nesting aspects.

Am I overlooking a nice way to achieve that?

sibling (~) selector should only collect following siblings, not all siblings

The following-sibling combinator is made of the "tilde" (U+007E, ~) character that separates two compound selectors. The elements represented by the two compound selectors share the same parent in the document tree and the element represented by the first compound selector precedes (not necessarily immediately) the element represented by the second one.

See http://dev.w3.org/csswg/selectors4/#general-sibling-combinators.

Subject indicator false positives

Queries with subject indicators match more nodes than they should, and also match the same node multiple times. E.g.:

esquery(esprima.parse('foo = bar = baz'),
  '!AssignmentExpression > AssignmentExpression > Identifier');

...returns the following:

[ AssignmentExpression {
    type: 'AssignmentExpression',
    operator: '=',
    left: Identifier { type: 'Identifier', name: 'bar' },
    right: Identifier { type: 'Identifier', name: 'baz' } },
  AssignmentExpression {
    type: 'AssignmentExpression',
    operator: '=',
    left: Identifier { type: 'Identifier', name: 'foo' },
    right: 
     AssignmentExpression {
       type: 'AssignmentExpression',
       operator: '=',
       left: [Object],
       right: [Object] } },
  AssignmentExpression {
    type: 'AssignmentExpression',
    operator: '=',
    left: Identifier { type: 'Identifier', name: 'bar' },
    right: Identifier { type: 'Identifier', name: 'baz' } },
  AssignmentExpression {
    type: 'AssignmentExpression',
    operator: '=',
    left: Identifier { type: 'Identifier', name: 'foo' },
    right: 
     AssignmentExpression {
       type: 'AssignmentExpression',
       operator: '=',
       left: [Object],
       right: [Object] } } ]

As far as I can tell, it should return only this:

[ AssignmentExpression {
    type: 'AssignmentExpression',
    operator: '=',
    left: Identifier { type: 'Identifier', name: 'foo' },
    right: 
     AssignmentExpression {
       type: 'AssignmentExpression',
       operator: '=',
       left: [Object],
       right: [Object] } } ]

SelectorNode class failing to compile

Fails on 0.3.0, but works on gh-pages

esquery.parse(':function')

Error is

"Expected "#", "*", ".", ":first-child", ":last-child", ":matches(", ":not(", ":nth-child(", ":nth-last-child(", "[" or [^ [\],():#!=><~+.] but ":" found."

Result on gh-pages is

{
  "type": "class",
  "name": "function"
}

Demo page uses old version

esquery.min.js in the gh-pages branch is an old version and needs to be updated. Specifically, the demo page still expects a postfix subject indicator. PR to follow shortly.

Update gh-pages

Could you update gh-pages so that https://estools.github.io/esquery/ is against the current version, or, better yet, use Github's ability under Settings to have the github.io URL point to master so it is always up to date?

Thanks!

quoted attribute values consume too much

a[b="c"][d="e"]

parses as

{
  "type": "compound",
  "selectors": [
    {
      "type": "identifier",
      "value": "a"
    },
    {
      "type": "attribute",
      "name": "b",
      "operator": "=",
      "value": {
        "type": "literal",
        "value": "c\"][d=\"e"
      }
    }
  ]
}

I expected

{
  "type": "compound",
  "selectors": [
    {
      "type": "identifier",
      "value": "a"
    },
    {
      "type": "attribute",
      "name": "b",
      "operator": "=",
      "value": {
        "type": "literal",
        "value": "c"
      }
    },
    {
      "type": "attribute",
      "name": "d",
      "operator": "=",
      "value": {
        "type": "literal",
        "value": "e"
      }
    }
  ]
}

... which is how the above selector parses when then the value is unquoted.

TSQuery!

Hey team!

I've been using ESQuery for several years and I love the API, so thank you for your efforts. I've been writing a lot of TypeScript lately, and I've had a go at a project using the ESQuery API for querying TypeScript ASTs. I'm planning on open-sourcing it, but I checked out your licence and saw the following point:

Neither the name of the ESQuery nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

I'm hoping it will be okay to mention that the API is taken from ESQuery (and that it uses your selector parser internally)? Assuming that falls within the realm of that particular licence term, I'd like to request permission to use the name ESQuery.

Thanks!

Please tag latest release v1.0.1

It seems an npm release was made without tagging it here in git.

Please tag it - that eases tracking for other distributors - e.g. Debian where I have recently included this module. :-)

Add support for comment matching

Comments in the AST are stored separately (if at all). They will have to be associated with the nodes somehow, perhaps range would work. The use case is for things like overriding rules in esquery or searching for the doc of a particular statement.

Add support for AST token matching

Adding token matching is useful for a few cases where things like whitespace are important but not represented in the AST.

Possible pseudo selectors:

  • :token(type, value) - token inside the node
  • :nth-token(n, type, value) - token inside or around the associated node (n tokens)
  • :nth-token-before(n, type, value) - token before the associated node (n tokens)
  • :nth-token-after(n, type, value) - token after the associated node (n tokens)

Demo page broken in Safari 6, other browsers without 'performance' object

Safari (at least as of 6.1) doesn't expose a global called performance so the demo just stops where you call performance.now().

Safari doesn't appear to implement the performance object behind a prefix, either, the way Chrome used to have webkitPerformance. So you're stuck with millisecond resolution in Safari, but I note that the initial demo takes 7ms in Chrome on my machine.

I'm not sure if you want to go all the way and use a performance.now() polyfill or not, and if so, which one, so I'll refrain from issuing a PR.

How do I get the ancestor list?

The closest I could find is discusssed here but the pull request is not merged.
#45

In dom, once I get a node via css selector, I always have a parentNode property to trace up to the root of the tree.

descendant selector includes ancestor in search

Using Identifier [name=x] produces identical results to Identifier[name=x] in the demo, even though it should produce no results. The "descendant" selector should require that the RHS be one or more steps below the LHS in the tree, not zero or more.

Feature Request: get target node type from selector

I'm looking at using esquery in ESLint, and it looks very close to what I need for the implementation I have in mind. The one thing that is missing is a way to figure out the target node type of a given selector. Basically, something that can take the selector AST and returns:

"*" => "*"
"FunctionDeclaration > VariableDeclarator" => "VariableDeclarator"
":not(FunctionDeclaration)" => "*"

Basically, my implementation will look like:

var queryAST = esquery.parse(key);
var targetType = esquery.getTargetType(queryAST);

eslint.on(targetType, function(node) {
    If (esquery.matches(node, queryAST, parents)) {
        // apply rule
    }
}

attribute selector cannot match Boolean-valued properties

I tried searching for UpdateExpression[prefix=true] today, but true is being interpreted as a string. Should it also match a prefix property with the Boolean value true? Should it only match that value since it was specified without quotes?

Running the tests

Hi,

I'm trying to run the tests with the command:

npm test

results in error for me:

Error: Tried loading "fixtures/conditional" at ./fixtures/conditional.js then tried...

But when I run with the command below, the tests run ok:

node node_modules/jstestr/bin/jstestr.js module=tests/queryAttribute
node node_modules/jstestr/bin/jstestr.js module=tests/queryField
etc...

Is there some other command I have to use?

I´m running with:

  • Windows 10
  • Node v6.9.1
  • npm 3.10.8

Thank you.

Add support for classes of types

Various types can be classified and group together. Things like statements and expressions. Possible pseudo selectors:

  • :statement - all statement nodes
  • :expression - all expression nodes
  • :declaration - all declaration nodes
  • :function - all function node types
  • :pattern - all pattern node types

Attribute regex test converts undefined attributes to strings

When matching an attribute regex for an attribute that does not exist, esquery appears to test the regex on the string 'null'. This can result in confusing false positives.

For example, I would expect the following selector to match any unicode regex literal:

Literal[regex.flags=/u/]

But it also matches all non-regex literals. This is because non-regex literals don't have a regex.flags property, so the regex /u/ gets matched against null, resulting in a successful match.

const esquery = require('esquery');
const espree = require('espree');
const selector = esquery.parse('Literal[regex.flags=/u/]');

const expressionStatement = espree.parse('1').body[0].expression;

esquery.matches(expressionStatement, selector) // => true

(Originally reported in eslint/eslint#8733)

Breaking change in version 1.2.0 isn't represented with a major version increment

With the most recent release of this package, I'm no longer able to run eslint for my project without it failing. This is tough, because my team runs it on build as part of our CI tooling (currently using node version 5.12.0). Doesn't seem like NPM tries to resolve packages based on engine versions, either.

It looks like this was intentional– but I'm curious why there wasn't a major version increment for it?

As an aside: this particular package is one that we should be updating to used fix versions but haven't yet.

Thanks for maintaining this project! Would be glad to help out with any potential solutions you all would be interested in.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.