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

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

Merged
merged 1 commit into from
Jul 17, 2019

Conversation

golopot
Copy link
Contributor

@golopot golopot commented Jul 12, 2019

Fixes #1357.

Fixes false positives like this:

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

@coveralls
Copy link

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

Coverage Status

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

@@ -34,6 +47,7 @@ module.exports = {

create: function (context) {
const namespace = new Map([[rootProgram, new Map()]])
const isTypescriptFile = /\.ts|\.tsx$/.test(context.getFilename())
Copy link
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
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
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
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.

src/rules/export.js Outdated Show resolved Hide resolved
@@ -137,7 +141,7 @@ module.exports = {
for (let [name, nodes] of named) {
if (nodes.size <= 1) continue

if (isTypescriptFile && isTypescriptFunctionOverloads(nodes)) continue
if (isTypescriptFunctionOverloads([...nodes])) continue
Copy link
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
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
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

*/
function isTypescriptFunctionOverloads(nodes) {
return Array.from(nodes).some(node => node.parent.type === 'TSDeclareFunction') &&
Array.from(nodes).every(node => (
Copy link
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
Contributor Author

@golopot golopot 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
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
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
@golopot golopot 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