From 3599b9e515cb99d1ca47d7c044368e27c5fb7009 Mon Sep 17 00:00:00 2001 From: Kai Cataldo Date: Wed, 6 Nov 2019 20:54:39 -0500 Subject: [PATCH] Handle args in reverse order and when args overlap --- lib/source-code/source-code.js | 22 ++- tests/lib/source-code/source-code.js | 207 ++++++++++++++++++++++----- 2 files changed, 187 insertions(+), 42 deletions(-) diff --git a/lib/source-code/source-code.js b/lib/source-code/source-code.js index 5d7ccdaf1e3..3ebff96d236 100644 --- a/lib/source-code/source-code.js +++ b/lib/source-code/source-code.js @@ -412,16 +412,28 @@ class SourceCode extends TokenStore { /** * Determines if two nodes or tokens have at least one whitespace character - * between them. - * @param {ASTNode|Token} first The node or token to check after. - * @param {ASTNode|Token} second The node or token to check before. + * between them. Order does not matter. Returns false if the given nodes or + * tokens overlap. + * @param {ASTNode|Token} first The first node or token to check between. + * @param {ASTNode|Token} second The second node or token to check between. * @returns {boolean} True if there is a whitespace character between * any of the tokens found between the two given nodes or tokens. * @public */ isSpaceBetweenTokens(first, second) { - const finalToken = this.getFirstToken(second) || second; - let currentToken = this.getLastToken(first) || first; + + // Arguments are overlapping. + if (first.range[0] <= second.range[0] && first.range[1] >= second.range[0] || + second.range[0] <= first.range[0] && second.range[1] >= first.range[0]) { + return false; + } + + const nodesAreReversed = second.range[1] <= first.range[0]; + const startingNodeOrToken = nodesAreReversed ? second : first; + const endingNodeOrToken = nodesAreReversed ? first : second; + const firstToken = this.getLastToken(startingNodeOrToken) || startingNodeOrToken; + const finalToken = this.getFirstToken(endingNodeOrToken) || endingNodeOrToken; + let currentToken = firstToken; while (currentToken !== finalToken) { const nextToken = this.getTokenAfter(currentToken, { includeComments: true }); diff --git a/tests/lib/source-code/source-code.js b/tests/lib/source-code/source-code.js index c7d67c70557..d4d1dd4dd27 100644 --- a/tests/lib/source-code/source-code.js +++ b/tests/lib/source-code/source-code.js @@ -1798,16 +1798,34 @@ describe("SourceCode", () => { ["let/**/foo", false], ["let/*\n*/foo", false] ], (code, expected) => { - it(code, () => { - const ast = espree.parse(code, DEFAULT_CONFIG), - sourceCode = new SourceCode(code, ast); + describe("when the first given is located before the second", () => { + it(code, () => { + const ast = espree.parse(code, DEFAULT_CONFIG), + sourceCode = new SourceCode(code, ast); + + assert.strictEqual( + sourceCode.isSpaceBetweenTokens( + sourceCode.ast.tokens[0], + sourceCode.ast.tokens[sourceCode.ast.tokens.length - 1] + ), + expected + ); + }); + }); - assert.strictEqual( - sourceCode.isSpaceBetweenTokens( - sourceCode.ast.tokens[0], sourceCode.ast.tokens[sourceCode.ast.tokens.length - 1] - ), - expected - ); + describe("when the first given is located after the second", () => { + it(code, () => { + const ast = espree.parse(code, DEFAULT_CONFIG), + sourceCode = new SourceCode(code, ast); + + assert.strictEqual( + sourceCode.isSpaceBetweenTokens( + sourceCode.ast.tokens[sourceCode.ast.tokens.length - 1], + sourceCode.ast.tokens[0] + ), + expected + ); + }); }); }); @@ -1844,16 +1862,34 @@ describe("SourceCode", () => { ["a/* */+` /*\n*/ ` /* */+c", true], ["a/* */+ ` /*\n*/ ` /* */+c", true] ], (code, expected) => { - it(code, () => { - const ast = espree.parse(code, DEFAULT_CONFIG), - sourceCode = new SourceCode(code, ast); + describe("when the first given is located before the second", () => { + it(code, () => { + const ast = espree.parse(code, DEFAULT_CONFIG), + sourceCode = new SourceCode(code, ast); + + assert.strictEqual( + sourceCode.isSpaceBetweenTokens( + sourceCode.ast.tokens[0], + sourceCode.ast.tokens[sourceCode.ast.tokens.length - 2] + ), + expected + ); + }); + }); - assert.strictEqual( - sourceCode.isSpaceBetweenTokens( - sourceCode.ast.tokens[0], sourceCode.ast.tokens[sourceCode.ast.tokens.length - 2] - ), - expected - ); + describe("when the first given is located after the second", () => { + it(code, () => { + const ast = espree.parse(code, DEFAULT_CONFIG), + sourceCode = new SourceCode(code, ast); + + assert.strictEqual( + sourceCode.isSpaceBetweenTokens( + sourceCode.ast.tokens[sourceCode.ast.tokens.length - 2], + sourceCode.ast.tokens[0] + ), + expected + ); + }); }); }); }); @@ -1888,16 +1924,34 @@ describe("SourceCode", () => { [";\n/**/\nlet foo = bar", true], [";\n/* */\nlet foo = bar", true] ], (code, expected) => { - it(code, () => { - const ast = espree.parse(code, DEFAULT_CONFIG), - sourceCode = new SourceCode(code, ast); + describe("when the first given is located before the second", () => { + it(code, () => { + const ast = espree.parse(code, DEFAULT_CONFIG), + sourceCode = new SourceCode(code, ast); + + assert.strictEqual( + sourceCode.isSpaceBetweenTokens( + sourceCode.ast.tokens[0], + sourceCode.ast.body[sourceCode.ast.body.length - 1] + ), + expected + ); + }); + }); - assert.strictEqual( - sourceCode.isSpaceBetweenTokens( - sourceCode.ast.tokens[0], sourceCode.ast.body[sourceCode.ast.body.length - 1] - ), - expected - ); + describe("when the first given is located after the second", () => { + it(code, () => { + const ast = espree.parse(code, DEFAULT_CONFIG), + sourceCode = new SourceCode(code, ast); + + assert.strictEqual( + sourceCode.isSpaceBetweenTokens( + sourceCode.ast.body[sourceCode.ast.body.length - 1], + sourceCode.ast.tokens[0] + ), + expected + ); + }); }); }); }); @@ -1932,16 +1986,34 @@ describe("SourceCode", () => { ["let foo = bar;\n/**/\n;", true], ["let foo = bar;\n/* */\n;", true] ], (code, expected) => { - it(code, () => { - const ast = espree.parse(code, DEFAULT_CONFIG), - sourceCode = new SourceCode(code, ast); + describe("when the first given is located before the second", () => { + it(code, () => { + const ast = espree.parse(code, DEFAULT_CONFIG), + sourceCode = new SourceCode(code, ast); + + assert.strictEqual( + sourceCode.isSpaceBetweenTokens( + sourceCode.ast.body[0], + sourceCode.ast.tokens[sourceCode.ast.tokens.length - 1] + ), + expected + ); + }); + }); - assert.strictEqual( - sourceCode.isSpaceBetweenTokens( - sourceCode.ast.body[0], sourceCode.ast.tokens[sourceCode.ast.tokens.length - 1] - ), - expected - ); + describe("when the first given is located after the second", () => { + it(code, () => { + const ast = espree.parse(code, DEFAULT_CONFIG), + sourceCode = new SourceCode(code, ast); + + assert.strictEqual( + sourceCode.isSpaceBetweenTokens( + sourceCode.ast.tokens[sourceCode.ast.tokens.length - 1], + sourceCode.ast.body[0] + ), + expected + ); + }); }); }); }); @@ -1973,6 +2045,42 @@ describe("SourceCode", () => { ["let foo = bar;\n/**/\nlet baz = qux;", true], ["let foo = bar;\n/* */\nlet baz = qux;", true], ["let foo = 1;let foo2 = 2; let foo3 = 3;", true] + ], (code, expected) => { + describe("when the first given is located before the second", () => { + it(code, () => { + const ast = espree.parse(code, DEFAULT_CONFIG), + sourceCode = new SourceCode(code, ast); + + assert.strictEqual( + sourceCode.isSpaceBetweenTokens( + sourceCode.ast.body[0], + sourceCode.ast.body[sourceCode.ast.body.length - 1] + ), + expected + ); + }); + }); + + describe("when the first given is located after the second", () => { + it(code, () => { + const ast = espree.parse(code, DEFAULT_CONFIG), + sourceCode = new SourceCode(code, ast); + + assert.strictEqual( + sourceCode.isSpaceBetweenTokens( + sourceCode.ast.body[sourceCode.ast.body.length - 1], + sourceCode.ast.body[0] + ), + expected + ); + }); + }); + }); + }); + + describe("should return false either of the arguments' location is inside the other one", () => { + leche.withData([ + ["let foo = bar;", false] ], (code, expected) => { it(code, () => { const ast = espree.parse(code, DEFAULT_CONFIG), @@ -1980,7 +2088,32 @@ describe("SourceCode", () => { assert.strictEqual( sourceCode.isSpaceBetweenTokens( - sourceCode.ast.body[0], sourceCode.ast.body[sourceCode.ast.body.length - 1] + sourceCode.ast.tokens[0], + sourceCode.ast.body[0] + ), + expected + ); + + assert.strictEqual( + sourceCode.isSpaceBetweenTokens( + sourceCode.ast.tokens[sourceCode.ast.tokens.length - 1], + sourceCode.ast.body[0] + ), + expected + ); + + assert.strictEqual( + sourceCode.isSpaceBetweenTokens( + sourceCode.ast.body[0], + sourceCode.ast.tokens[0] + ), + expected + ); + + assert.strictEqual( + sourceCode.isSpaceBetweenTokens( + sourceCode.ast.body[0], + sourceCode.ast.tokens[sourceCode.ast.tokens.length - 1] ), expected );