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

feat(eslint-plugin): Add unified-signature rule #178

Merged

Conversation

armanio123
Copy link
Contributor

Adding tslint's rule unified-signature.

packages/eslint-plugin/ROADMAP.md Outdated Show resolved Hide resolved
packages/eslint-plugin/lib/rules/unified-signatures.js Outdated Show resolved Hide resolved
@armano2 armano2 added the enhancement: new plugin rule New rule request for eslint-plugin label Feb 3, 2019
bradzacher
bradzacher previously approved these changes Feb 7, 2019
Copy link
Member

@armano2 armano2 left a comment

Choose a reason for hiding this comment

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

i'm unsure if this implementation is best what we can do in here

its weird that we have to iterate over nodes few times

this is just idea and i didn't tested it but it should work:

    const scopes = [];
    let currentScope = {
      overloads: new Map(),
      parent: undefined,
      typeParameters: undefined
    };

    function createScope(parent, typeParameters = undefined) {
      scopes.push(currentScope);
      currentScope = {
        overloads: new Map(),
        parent,
        typeParameters
      };
    }

    function checkScope() {
      const failures = checkOverloads(
        Array.from(currentScope.overloads.values()),
        currentScope.typeParameters
      );
      addFailures(failures);
      currentScope = scopes.pop();
    }

    function addOverload(signature, key = null) {
      key = key || getOverloadKey(signature);
      if (signature.parent === currentScope.parent && key) {
        const overloads = currentScope.overloads.get(key);
        if (overloads !== undefined) {
          overloads.push(signature);
        } else {
          currentScope.overloads.set(key, [signature]);
        }
      }
    }

    return {
      Program(node) {
        createScope(node);
      },
      TSModuleBlock(node) {
        createScope(node);
      },
      TSInterfaceDeclaration(node) {
        createScope(node.body, node.typeParameters);
      },
      ClassDeclaration(node) {
        createScope(node.body, node.typeParameters);
      },
      TSTypeLiteral(node) {
        createScope(node);
      },
      // collect overloads
      TSDeclareFunction(node) {
        if (node.id && !node.body) {
          addOverload(node, node.id.name);
        }
      },
      TSCallSignatureDeclaration: addOverload,
      TSConstructSignatureDeclaration: addOverload,
      TSMethodSignature: addOverload,
      TSAbstractMethodDefinition(node) {
        if (!node.value.body) {
          addOverload(node);
        }
      },
      MethodDefinition(node) {
        if (!node.value.body) {
          addOverload(node);
        }
      },
      // validate scopes
      'Program:exit': checkScope,
      'TSModuleBlock:exit': checkScope,
      'TSInterfaceDeclaration:exit': checkScope,
      'ClassDeclaration:exit': checkScope,
      'TSTypeLiteral:exit': checkScope
    };

i still don't like this code, but at-least we don't have to iterate over nodes with custom implementation

with that you are going to be able to remove: checkStatements, checkMembers, collectOverloads.

@JamesHenry
Copy link
Member

Apologies for the conflicts, we decided to remove the counts from the ROADMAP here: #225

They are too awkward to maintain manually, so this is the last time you will have to deal with syncing that up!

@bradzacher bradzacher added BLOCKED: awaiting ts migration enhancement: new plugin rule New rule request for eslint-plugin and removed enhancement: new plugin rule New rule request for eslint-plugin labels Feb 11, 2019
@JamesHenry
Copy link
Member

@armanio123 Thanks again for your contribution, when do you think you'll be able to pick this up again?

@@ -0,0 +1,616 @@
/**
* @fileoverview Warns for any two overloads that could be unified into one by using a union or an optional/rest parameter.
* @author Armando Aguirre
Copy link
Member

Choose a reason for hiding this comment

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

Sorry we've changed to using all-contributors now and removed all other occurrences of these file-level author comments, please could you remove this

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed.

@armanio123
Copy link
Contributor Author

Added the changes requested, migrated to TS and addressed the comments as well. Let me know if there's anything else.

@codecov
Copy link

codecov bot commented Mar 11, 2019

Codecov Report

Merging #178 into master will decrease coverage by <.01%.
The diff coverage is 97.16%.

@@            Coverage Diff            @@
##           master    #178      +/-   ##
=========================================
- Coverage    97.2%   97.2%   -0.01%     
=========================================
  Files          67      68       +1     
  Lines        2360    2501     +141     
  Branches      337     385      +48     
=========================================
+ Hits         2294    2431     +137     
  Misses         44      44              
- Partials       22      26       +4
Impacted Files Coverage Δ
packages/eslint-plugin/src/util/misc.ts 84.21% <100%> (+4.21%) ⬆️
...ages/eslint-plugin/src/rules/unified-signatures.ts 97.08% <97.08%> (ø)

@bradzacher bradzacher requested a review from armano2 March 12, 2019 00:59
@@ -34,7 +34,7 @@
| [`promise-function-async`] | ✅ | [`@typescript-eslint/promise-function-async`] |
| [`typedef`] | 🛑 | N/A |
| [`typedef-whitespace`] | ✅ | [`@typescript-eslint/type-annotation-spacing`] |
| [`unified-signatures`] | 🛑 | N/A |
| [`unified-signatures`] | | [`@typescript-eslint/unified-signatures`] |
Copy link
Member

Choose a reason for hiding this comment

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

need to add the link at the bottom of the file or else this won't work

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

Copy link
Member

@bradzacher bradzacher left a comment

Choose a reason for hiding this comment

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

need to tighten up the types if this is going to be merged.
Most of the functions have params of type any. Ideally there should be zero anys.

You can import { TSESTree } from '@typescript-eslint/typescript-estree'; and use the types within that namespace to type nodes and the like.

@JamesHenry
Copy link
Member

Thanks for working through all the feedback, @armanio123!

@JamesHenry JamesHenry merged commit 6ffaa0b into typescript-eslint:master Mar 20, 2019
@JamesHenry
Copy link
Member

@uniqueiniquity is going to apply this to the TS repo this week :)

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 21, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement: new plugin rule New rule request for eslint-plugin
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants