Skip to content

[fix] export: false positive for typescript overloads#1412

Merged
ljharb merged 1 commit into
import-js:masterfrom
chiawendt:issue-1327
Jul 17, 2019
Merged

[fix] export: false positive for typescript overloads#1412
ljharb merged 1 commit into
import-js:masterfrom
chiawendt:issue-1327

Conversation

@chiawendt
Copy link
Copy Markdown
Contributor

Fixes #1357.

Fixes false positives like this:

export function foo(a: number) {}
export function foo(a: string) {}

@coveralls
Copy link
Copy Markdown

coveralls commented Jul 12, 2019

Coverage Status

Coverage increased (+0.003%) to 97.963% when pulling 22d5440 on golopot:issue-1327 into 5abd5ed on benmosher:master.

@coveralls
Copy link
Copy Markdown

Coverage Status

Coverage increased (+0.003%) to 97.757% when pulling 5703fb0 on golopot:issue-1327 into 6512110 on benmosher:master.

Comment thread src/rules/export.js Outdated

create: function (context) {
const namespace = new Map([[rootProgram, new Map()]])
const isTypescriptFile = /\.ts|\.tsx$/.test(context.getFilename())
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

this seems like something that would need to be determined based on parser settings, not hardcoded extensions - also, what about flow?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

  1. Will it suffice to do something like \/@typescript-eslint\/parser\/.test(context.parserPath)?(context.parserPath is like /home/some-user/some-project/node_modules/@typescript-eslint/parser/dist/parser.js) 2. It seems that flow does not accept function overload like the case here.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

that would force people to install the typescript parser even if they weren’t using typescript, i think - ideally we’d find a more reliable mechanism than “its typescript” to handle this case.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Just find out find that these function nodes without body has node type TSDeclareFunction. Therefore I change the bail out logic to some nodes is TSDeclareFunction && every nodes is TSDeclareFunction or FunctionDeclaration.

Comment thread src/rules/export.js Outdated
Comment thread src/rules/export.js Outdated
if (nodes.size <= 1) continue

if (isTypescriptFile && isTypescriptFunctionOverloads(nodes)) continue
if (isTypescriptFunctionOverloads([...nodes])) continue
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

why the spread into an array? is nodes not an Array, just an iterable? Set maybe? if so I might Array.from(nodes) to make it a little clearer. but definitely nitpicking, this is a great improvement

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

why not pass the Set in directly, and convert it inside the function?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Ready for review

Comment thread src/rules/export.js Outdated
*/
function isTypescriptFunctionOverloads(nodes) {
return Array.from(nodes).some(node => node.parent.type === 'TSDeclareFunction') &&
Array.from(nodes).every(node => (
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

let's definitely not do Array.from twice. maybe something like this for the body of the function?

const types = new Set(Array.from(nodes, node => node.parent.type));
if (!types.has('TSDeclareFunction') || types.size > 2) {
  return false;
}
return types.size === 1 || types.has('FunctionDeclaration');

Copy link
Copy Markdown
Contributor Author

@chiawendt chiawendt Jul 17, 2019

Choose a reason for hiding this comment

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

I end up with this:

const types = new Set(Array.from(nodes, node => node.parent.type))
return types.size === 2 && types.has('TSDeclareFunction') && types.has('FunctionDeclaration')

The case when types is the same as new Set(["TSDeclareFunction"]) is when the function lacks implementation, which is a tsc error.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

That isn't the same logic though - your current logic allows it to be only "TSDeclareFunction". Functions don't need an implementation in tsc if they're just defining a type overload.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

That case is a tsc error https://www.typescriptlang.org/play/#code/KYDwDg9gTgLgBAMwK4DsDGMCWEWIBQCUQA . And for the purpose of this rule, that case does not matter.

@ljharb ljharb self-assigned this Jul 17, 2019
@ljharb ljharb merged commit 22d5440 into import-js:master Jul 17, 2019
@chiawendt chiawendt deleted the issue-1327 branch September 7, 2019 18:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

import/export: false positives for typescript overloads

4 participants