Skip to content
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

Update: Add includeComments to getTokenByRangeStart (fixes #8068) #8069

Merged
merged 2 commits into from
Feb 18, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
17 changes: 10 additions & 7 deletions docs/developer-guide/working-with-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -280,18 +280,21 @@ Once you have an instance of `SourceCode`, you can use the methods on it to work
* `getLastTokensBetween(nodeOrToken1, nodeOrToken2, countOptions)` - returns the last `count` tokens between two nodes or tokens.
* `getTokens(node)` - returns all tokens for the given node.
* `getTokensBetween(nodeOrToken1, nodeOrToken2)` - returns all tokens between two nodes.
* `getTokenByRangeStart(index)` - returns the token whose range starts at the given index in the source.
* `getTokenByRangeStart(index, rangeOptions)` - returns the token whose range starts at the given index in the source.
* `getNodeByRangeIndex(index)` - returns the deepest node in the AST containing the given source index.

> `skipOptions` is an object which has 3 properties; `skip`, `includeComments`, and `filter`. Default is `{skip: 0, includeComments: false, filter: null}`.
> - The `skip` is a positive integer, the number of skipping tokens. If `filter` option is given at the same time, it doesn't count filtered tokens as skipped.
> - The `includeComments` is a boolean value, the flag to include comment tokens into the result.
> - The `filter` is a function which gets a token as the first argument, if the function returns `false` then the result excludes the token.
> - `skip` is a positive integer, the number of skipping tokens. If `filter` option is given at the same time, it doesn't count filtered tokens as skipped.
> - `includeComments` is a boolean value, the flag to include comment tokens into the result.
> - `filter` is a function which gets a token as the first argument, if the function returns `false` then the result excludes the token.
>
> `countOptions` is an object which has 3 properties; `count`, `includeComments`, and `filter`. Default is `{count: 0, includeComments: false, filter: null}`.
> - The `count` is a positive integer, the maximum number of returning tokens.
> - The `includeComments` is a boolean value, the flag to include comment tokens into the result.
> - The `filter` is a function which gets a token as the first argument, if the function returns `false` then the result excludes the token.
> - `count` is a positive integer, the maximum number of returning tokens.
> - `includeComments` is a boolean value, the flag to include comment tokens into the result.
> - `filter` is a function which gets a token as the first argument, if the function returns `false` then the result excludes the token.
>
> `rangeOptions` is an object which has 1 property: `includeComments`.
> - `includeComments` is a boolean value, the flag to include comment tokens into the result.

There are also some properties you can access:

Expand Down
23 changes: 20 additions & 3 deletions lib/token-store/cursors.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,25 @@ class CursorFactory {
}

/**
* Creates the cursor iterates tokens with normalized options.
* Creates a base cursor instance that can be decorated by createCursor.
*
* @param {Token[]} tokens - The array of tokens.
* @param {Comment[]} comments - The array of comments.
* @param {Object} indexMap - The map from locations to indices in `tokens`.
* @param {number} startLoc - The start location of the iteration range.
* @param {number} endLoc - The end location of the iteration range.
* @param {boolean} includeComments - The flag to iterate comments as well.
* @returns {Cursor} The created base cursor.
* @private
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was curious if this is actually private since we call these methods in token-store/index?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, it's my mistake of copy/paste!

*/
createBaseCursor(tokens, comments, indexMap, startLoc, endLoc, includeComments) {
const Cursor = includeComments ? this.TokenCommentCursor : this.TokenCursor;

return new Cursor(tokens, comments, indexMap, startLoc, endLoc);
}

/**
* Creates a cursor that iterates tokens with normalized options.
*
* @param {Token[]} tokens - The array of tokens.
* @param {Comment[]} comments - The array of comments.
Expand All @@ -52,8 +70,7 @@ class CursorFactory {
* @private
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above.

*/
createCursor(tokens, comments, indexMap, startLoc, endLoc, includeComments, filter, skip, count) {
const Cursor = includeComments ? this.TokenCommentCursor : this.TokenCursor;
let cursor = new Cursor(tokens, comments, indexMap, startLoc, endLoc);
let cursor = this.createBaseCursor(tokens, comments, indexMap, startLoc, endLoc, includeComments);

if (filter) {
cursor = new FilterCursor(cursor, filter);
Expand Down
14 changes: 12 additions & 2 deletions lib/token-store/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -236,10 +236,20 @@ module.exports = class TokenStore {
/**
* Gets the token starting at the specified index.
* @param {number} offset - Index of the start of the token's range.
* @param {Object} [options=0] - The option object.
* @param {boolean} [options.includeComments=false] - The flag to iterate comments as well.
* @returns {Token|null} The token starting at index, or null if no such token.
*/
getTokenByRangeStart(offset) {
const token = this.tokens[this.indexMap[offset]] || null;
getTokenByRangeStart(offset, options) {
const includeComments = options && options.includeComments;
const token = cursors.forward.createBaseCursor(
this.tokens,
this.comments,
this.indexMap,
offset,
-1,
includeComments
).getOneToken();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

createCursorWithSkip is the function to normalize options for overload of number (skip), function (filter), or object. I think we can use cursors.forward.createCursor directly since this does not use skip.

const token = cursors.forward.createCursor(
    this.tokens,
    this.comments,
    this.indexMap,
    offset, // startLoc
    -1,     // endLoc
    includeComments,
    null,   // filter
    0,      // skip
    -1      // count
).getOneToken()

Or, it's nice if we define cursors.forward.createBaseCursor function with this part.

const token = cursors.forward.createBaseCursor(
    this.tokens,
    this.comments,
    this.indexMap,
    offset, // startLoc
    -1,     // endLoc
    includeComments
).getOneToken()


if (token && token.range[0] === offset) {
return token;
Expand Down
19 changes: 19 additions & 0 deletions tests/lib/token-store.js
Original file line number Diff line number Diff line change
Expand Up @@ -1020,6 +1020,25 @@ describe("TokenStore", () => {
assert.isNull(result);
});

it("should return a comment token when includeComments is true", () => {
const result = store.getTokenByRangeStart(15, { includeComments: true });

assert.equal(result.type, "Block");
assert.equal(result.value, "B");
});

it("should not return a comment token at the supplied index when includeComments is false", () => {
const result = store.getTokenByRangeStart(15, { includeComments: false });

assert.isNull(result);
});

it("should not return comment tokens by default", () => {
const result = store.getTokenByRangeStart(15);

assert.isNull(result);
});

});

describe("when calling getTokenOrCommentBefore", () => {
Expand Down