Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

fix(eslint-plugin): [no-misused-promises] theinheritedMethods andproperties options to check all statically analyzable declarations#10310

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
ronami wants to merge22 commits intotypescript-eslint:main
base:main
Choose a base branch
Loading
fromronami:no-misused-promises-inherited-methods-static-access-value

Conversation

ronami
Copy link
Member

@ronamironami commentedNov 8, 2024
edited
Loading

PR Checklist

Overview

This PRresolves#10211 and uses the existinggetStaticMemberAccessValue() utility instead oftsutils.getPropertyOfType() to handle most statically analyzable declarations/properties:

conststaticSymbol=Symbol.for('static symbol');interfaceInterface{identifier:()=>void;1:()=>void;2:()=>void;stringLiteral:()=>void;computedStringLiteral:()=>void;// well known symbol[Symbol.iterator]:()=>void;// less sure if this one is possible to lint for[staticSymbol]:()=>void;}classClazzimplementsInterface{asyncidentifier(){}async1(){}async[2](){}async'stringLiteral'(){}async['computedStringLiteral'](){}async[Symbol.iterator](){};async[staticSymbol](){};}

I added some PR review comments on parts of the PR I'm not sure are correct, please let me know what you think.

@typescript-eslint
Copy link
Contributor

Thanks for the PR,@ronami!

typescript-eslint is a 100% community driven project, and we are incredibly grateful that you are contributing to that community.

The core maintainers work on this in their personal time, so please understand that it may not be possible for them to review your work immediately.

Thanks again!


🙏Please, if you or your company is finding typescript-eslint valuable, help us sustain the project by sponsoring it transparently onhttps://opencollective.com/typescript-eslint.

@netlifyNetlify
Copy link

netlifybot commentedNov 8, 2024
edited
Loading

Deploy Preview fortypescript-eslint ready!

NameLink
🔨 Latest commit6c48db9
🔍 Latest deploy loghttps://app.netlify.com/sites/typescript-eslint/deploys/6772ea964c1c98000821d3c8
😎 Deploy Previewhttps://deploy-preview-10310--typescript-eslint.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 99 (🟢 up 8 from production)
Accessibility: 100 (no change from production)
Best Practices: 92 (no change from production)
SEO: 98 (no change from production)
PWA: 80 (no change from production)
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to yourNetlify site configuration.

@nx-cloudNx Cloud
Copy link

nx-cloudbot commentedNov 8, 2024
edited
Loading

View yourCI Pipeline Execution ↗ for commit6c48db9.

CommandStatusDurationResult
nx test eslint-plugin --coverage=false✅ Succeeded7m 15sView ↗
nx test eslint-plugin✅ Succeeded5m 52sView ↗
nx test type-utils✅ Succeeded<1sView ↗
nx test utils✅ Succeeded<1sView ↗
nx run types:build✅ Succeeded<1sView ↗
nx test visitor-keys✅ Succeeded<1sView ↗
nx run-many --target=build --exclude website --...✅ Succeeded27sView ↗
nx test typescript-eslint✅ Succeeded4sView ↗
Additional runs (24)✅ Succeeded...View ↗

☁️Nx Cloud last updated this comment at2024-12-30 19:01:53 UTC

@ronamironami changed the titlefix(eslint-plugin): [no-misused-promises]inheritedMethods andproperties to check all statically analyzable declarationsfix(eslint-plugin): [no-misused-promises] theinheritedMethods andproperties options to check all statically analyzable declarationsNov 8, 2024
Comment on lines 969 to 978
function getWellKnownStringOfSymbol(symbol: symbol): string | null {
switch (symbol) {
case Symbol.iterator:
return 'iterator';
case Symbol.asyncIterator:
return 'asyncIterator';
}

return null;
}
Copy link
MemberAuthor

@ronamironamiNov 8, 2024
edited
Loading

Choose a reason for hiding this comment

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

I'm not sure if there's a better way to map a symbol to its string counterparttsutils.getWellKnownSymbolPropertyOfType is expecting.

The list forwell-known symbols isn't long, but this will still require maintaining this mapping.

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

If this approach makes sense, this list can be expanded to support other well-known symbols.

Choose a reason for hiding this comment

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

Is there a reason we need to stick to well-known symbols? I'd think we should go with any detected symbol, no?

kirkwaiblinger reacted with thumbs up emoji
Copy link
MemberAuthor

@ronamironamiNov 14, 2024
edited
Loading

Choose a reason for hiding this comment

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

Hmm, I might be missing something, but I'm not entirely sure how to check if a JavaScriptsymbol exists on anotherts.Type 🤔

Here's how existing code checks if an inherited type has astring symbol:

constescapedMemberName=ts.escapeLeadingUnderscores(staticAccessValue);constsymbolMemberMatch=type.getSymbol()?.members?.get(escapedMemberName);return(symbolMemberMatch??tsutils.getPropertyOfType(type,escapedMemberName));

I've looked into theSymbolObject but couldn't find a way to check against an arbitrarysymbol (not to be confused withts.Symbol).

Because of this, I've created a function to map between known symbols and their string representation, which are passed totsutils.getWellKnownSymbolPropertyOfType to check if they exist on the inherited type.

Edit: I don't think it's feasible to iterate the inherited parent's nodes, as a function may be higher up the inheritance chain:

conststaticSymbol=Symbol.for('static symbol');interfaceBar{[staticSymbol]:()=>void;}interfaceFooextendsBar{}classClazzimplementsFoo{// should be reportedasync[staticSymbol](){}}

Choose a reason for hiding this comment

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

Hmm gotcha thanks. cc@kirkwaiblinger - I'm fine with this as a patchwork helper, with as little hardcoding as possible.

functiongetWellKnownStringOfSymbol(symbol:symbol):string|null{for(const[key,value]ofObject.entries(Symbol)){if(symbol===value){returnkey;}}returnnull;}

And, sorry for dropping the ball on this again 🤦 there's something about symbols that makes me instinctively forget the conversation...

ronami reacted with thumbs up emoji
Copy link
MemberAuthor

Choose a reason for hiding this comment

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

I've updated the PR to not hard-code well-known symbols, thanks!

The only alternative I had in mind for not hard-coding was to extract the value fromSymbol.prototype.toString() with a regex (which I really didn't want to do), but I didn't think of iterating the globalSymbol's keys.

This means that arbitrary symbols (e.g.Symbol.for('foo')) won't be reported by the rule though.

Choose a reason for hiding this comment

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

Yeah I don't see a way to work for arbitrary symbols 😞

ronami reacted with thumbs up emoji

Choose a reason for hiding this comment

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

ronami reacted with eyes emoji
@codecovCodecov
Copy link

codecovbot commentedNov 8, 2024
edited
Loading

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 86.92%. Comparing base(3ae4148) to head(6c48db9).
Report is 71 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@##             main   #10310      +/-   ##==========================================+ Coverage   86.86%   86.92%   +0.06%==========================================  Files         445      446       +1       Lines       15455    15514      +59       Branches     4507     4520      +13     ==========================================+ Hits        13425    13486      +61+ Misses       1675     1673       -2  Partials      355      355
FlagCoverage Δ
unittest86.92% <100.00%> (+0.06%)⬆️

Flags with carried forward coverage won't be shown.Click here to find out more.

Files with missing linesCoverage Δ
...ges/eslint-plugin/src/rules/no-misused-promises.ts98.56% <100.00%> (+0.83%)⬆️
packages/eslint-plugin/src/util/misc.ts98.85% <ø> (ø)

... and9 files with indirect coverage changes

@ronamironami marked this pull request as ready for reviewNovember 9, 2024 13:59
Comment on lines 575 to 579
node.type !== AST_NODE_TYPES.MethodDefinition &&
node.type !== AST_NODE_TYPES.TSAbstractMethodDefinition &&
node.type !== AST_NODE_TYPES.TSMethodSignature &&
node.type !== AST_NODE_TYPES.TSPropertySignature &&
node.type !== AST_NODE_TYPES.PropertyDefinition
Copy link
MemberAuthor

Choose a reason for hiding this comment

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

This is enough to pass the test suit but there are additional types available to satisfygetStaticMemberAccessValue.

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

This is necessary mainly for type-checking, and I don't know if this can realistically have a runtime scenario. Please let me know if this should be handled differently (currently, there is no coverage for this).

Choose a reason for hiding this comment

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

I don't believe this can realistically be a runtime scenario. I think the real issue here is that althoughnodeMember is typets.TypeElement | ts.ClassElement,node is typeTSESTree.Node.

The two strategies I'd think could be good would be:

  • Simpler: use anas to correct TypeScript's understanding ofnode's type to beNodeWithKey (which will need to be exported frommisc.ts)
  • More aligned with how most of our typed lint rules go: instead of iterating over thetsNode.members, iterate over the members ofnode

The latter is probably a lot more work and changes the existing code. So I think theas strategy would be reasonable.

ronami reacted with thumbs up emoji
Copy link
MemberAuthor

Choose a reason for hiding this comment

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

Yes, I've started with a type-assertion on my initial implementation but I wasn't sure if there's a realistic case where this would explode.

I updated the code to use a type assertion, as the second option seems to be a lot more work.

JoshuaKGoldberg reacted with thumbs up emoji
Copy link
Member

@JoshuaKGoldbergJoshuaKGoldberg left a comment

Choose a reason for hiding this comment

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

I like where this is going!

ronami reacted with heart emoji

Choose a reason for hiding this comment

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

ronami reacted with thumbs up emoji
Comment on lines 575 to 579
node.type !== AST_NODE_TYPES.MethodDefinition &&
node.type !== AST_NODE_TYPES.TSAbstractMethodDefinition &&
node.type !== AST_NODE_TYPES.TSMethodSignature &&
node.type !== AST_NODE_TYPES.TSPropertySignature &&
node.type !== AST_NODE_TYPES.PropertyDefinition

Choose a reason for hiding this comment

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

I don't believe this can realistically be a runtime scenario. I think the real issue here is that althoughnodeMember is typets.TypeElement | ts.ClassElement,node is typeTSESTree.Node.

The two strategies I'd think could be good would be:

  • Simpler: use anas to correct TypeScript's understanding ofnode's type to beNodeWithKey (which will need to be exported frommisc.ts)
  • More aligned with how most of our typed lint rules go: instead of iterating over thetsNode.members, iterate over the members ofnode

The latter is probably a lot more work and changes the existing code. So I think theas strategy would be reasonable.

ronami reacted with thumbs up emoji
Comment on lines 969 to 978
function getWellKnownStringOfSymbol(symbol: symbol): string | null {
switch (symbol) {
case Symbol.iterator:
return 'iterator';
case Symbol.asyncIterator:
return 'asyncIterator';
}

return null;
}

Choose a reason for hiding this comment

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

Is there a reason we need to stick to well-known symbols? I'd think we should go with any detected symbol, no?

kirkwaiblinger reacted with thumbs up emoji
@JoshuaKGoldbergJoshuaKGoldberg added the awaiting responseIssues waiting for a reply from the OP or another party labelNov 10, 2024
@JoshuaKGoldberg
Copy link
Member

👋 Hey@ronami, did you want to re-request review on this?

No pressure, just asking because it's been a bit and I've seen other things from you in the meantime. 🙂

ronami reacted with heart emoji

@ronami
Copy link
MemberAuthor

ronami commentedDec 2, 2024
edited
Loading

👋 Hey@ronami, did you want to re-request review on this?

No pressure, just asking because it's been a bit and I've seen other things from you in the meantime. 🙂

Hey@JoshuaKGoldberg, thanks for checking up on this ❤️

I'vecommented here on something I'm not sure how to implement (I might be missing something 🙈).

I didn't want to ask for a re-review since it's still an open discussion. This is the only remaining open issue before the PR can be re-reviewed.

JoshuaKGoldberg reacted with thumbs up emoji

@github-actionsgithub-actionsbot removed the awaiting responseIssues waiting for a reply from the OP or another party labelDec 26, 2024
context,
);

if (!staticAccessValue) {

Choose a reason for hiding this comment

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

(same as other comment)

Suggested change
if(!staticAccessValue){
if(staticAccessValue==null){

@@ -492,9 +492,14 @@ export default createRule<Options, MessageId>({
if (objType == null) {
return;
}
const propertySymbol = checker.getPropertyOfType(
const staticAccessValue = getStaticMemberAccessValue(node, context);
if (!staticAccessValue) {

Choose a reason for hiding this comment

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

(bug)

Suggested change
if(!staticAccessValue){
if(staticAccessValue==null){

because

classMyClass{''():void{}}classMySubclassextendsMyClass{async''():Promise<void>{}}

ronami reacted with thumbs up emoji
Copy link
MemberAuthor

Choose a reason for hiding this comment

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

Oh, nice catch! Is there any reason we don't havestrict-boolean-expressions enabled?

Choose a reason for hiding this comment

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

Because IIRC both Joshs don't like it hehe. Brad and I both do like it. 🤷‍♂️

Comment on lines 969 to 978
function getWellKnownStringOfSymbol(symbol: symbol): string | null {
switch (symbol) {
case Symbol.iterator:
return 'iterator';
case Symbol.asyncIterator:
return 'asyncIterator';
}

return null;
}

Choose a reason for hiding this comment

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

ronami reacted with eyes emoji
@kirkwaiblinger
Copy link
Member

Hey@ronami, do you plan to make further changes regarding#10310 (comment) or is this intended to be reviewed as is?

ronami reacted with eyes emoji

@ronami
Copy link
MemberAuthor

ronami commentedJan 19, 2025
edited
Loading

Hey@ronami, do you plan to make further changes regarding#10310 (comment) or is this intended to be reviewed as is?

Oh, I'm sorry; I've looked into it but completely forgot to get back to it.


I didn't consider the issue with the current approach, which could result in different values on different machines and NodeJS versions (though looking intoMDN, it seems pretty much all well-known symbols are supported on rather old Node versions already).

I haven't noticedheritageType.getProperties().map(sym => sym.links.nameType), which, while not part of the API, does seem to work in various edge cases, and types do seem=== to each other, interesting 🙃.

Having a way to get the key type of a propertySymbol would be useful. I'll be happy to check if this can be added to the public API or if there's a reasonable hack we can currently use. Should this be filed as a GitHub issue or discussed on the TypeScript Discord channel?

Thanks for your help with this ❤️

@kirkwaiblinger
Copy link
Member

I didn't consider the issue with the current approach, which could result in different values on different machines and NodeJS versions (though looking intoMDN, it seems pretty much all well-known symbols are supported on rather old Node versions already).

Ok, that definitely alleviates some of the concern 👍 Though I guess there's maybe still a forwards-compatibility question.

I haven't noticedheritageType.getProperties().map(sym => sym.links.nameType), which, while not part of the API, does seem to work in various edge cases, and types do seem=== to each other, interesting 🙃.

Having a way to get the key type of a propertySymbol would be useful. I'll be happy to check if this can be added to the public API or if there's a reasonable hack we can currently use. Should this be filed as a GitHub issue or discussed on the TypeScript Discord channel?

What I usually do is just ask questions on the TS discord and copy down the link on the issue/PR I'm working on - partly for visibility and partly just so I can find it again myself! 😅

Thanks for your help with this ❤️

❤️

ronami reacted with thumbs up emoji

@kirkwaiblingerkirkwaiblinger added the awaiting responseIssues waiting for a reply from the OP or another party labelJan 24, 2025
@JoshuaKGoldberg
Copy link
Member

👋@ronami just checking in, how is this going?

Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@JoshuaKGoldbergJoshuaKGoldbergJoshuaKGoldberg requested changes

@kirkwaiblingerkirkwaiblingerkirkwaiblinger left review comments

Requested changes must be addressed to merge this pull request.

Assignees
No one assigned
Labels
awaiting responseIssues waiting for a reply from the OP or another party
Projects
None yet
Milestone
No milestone
Development

Successfully merging this pull request may close these issues.

Bug: [no-misused-promises]inheritedMethods check should flag all statically analyzable declarations, not just identifiers and numbers.
3 participants
@ronami@JoshuaKGoldberg@kirkwaiblinger

[8]ページ先頭

©2009-2025 Movatter.jp