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

feat: add support for decorator metadata in scope analysis and in consistent-type-imports#2751

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

Merged
bradzacher merged 8 commits intotypescript-eslint:masterfromFrezc:fix/meta
Jan 18, 2021

Conversation

Frezc
Copy link
Contributor

Fixes#2559

Changes:

  • check import if referenced by decorator metadata if "emitDecoratorMetadata" if on.
  • fix type import to value import if it referenced by decorator metadata

Disquse and LucasPaganini reacted with thumbs up emoji
@typescript-eslint
Copy link
Contributor

Thanks for the PR,@Frezc!

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. As a thank you, your profile/company logo will be added to our main README which receives thousands of unique visitorsper day.

@codecov
Copy link

codecovbot commentedNov 10, 2020
edited
Loading

Codecov Report

Merging#2751 (b631e7a) intomaster (85c2720) willdecrease coverage by0.07%.
The diff coverage is92.01%.

@@            Coverage Diff             @@##           master    #2751      +/-   ##==========================================- Coverage   92.76%   92.68%   -0.08%==========================================  Files         310      312       +2       Lines       10393    10584     +191       Branches     2943     3004      +61     ==========================================+ Hits         9641     9810     +169- Misses        347      353       +6- Partials      405      421      +16
FlagCoverage Δ
unittest92.68% <92.01%> (-0.08%)⬇️

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

Impacted FilesCoverage Δ
packages/scope-manager/src/analyze.ts70.96% <50.00%> (-1.45%)⬇️
...kages/scope-manager/src/referencer/ClassVisitor.ts91.34% <91.34%> (ø)
...eslint-plugin/src/rules/consistent-type-imports.ts95.00% <93.06%> (-2.16%)⬇️
...ackages/scope-manager/src/referencer/Referencer.ts93.90% <100.00%> (-0.97%)⬇️
...ckages/scope-manager/src/referencer/TypeVisitor.ts89.24% <100.00%> (+0.11%)⬆️
.../src/rules/sort-type-union-intersection-members.ts92.30% <0.00%> (ø)
packages/eslint-plugin/src/rules/comma-spacing.ts97.87% <0.00%> (+0.09%)⬆️

Copy link
Member

@bradzacherbradzacher left a comment
edited
Loading

Choose a reason for hiding this comment

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

Thanks for looking into this!
Quick eyeball of the code - a few comments:

requiring type information in the rule is a breaking change.
We should not be making this change as it hugely limits the usability of the rule.

This is the wrong approach to fix this - this should be fixed in the scope analyser - not in the rule.
Fixing this in the scope analyser would benefitall consumers of scope information, and not just this specific rule.

@bradzacherbradzacher added the awaiting responseIssues waiting for a reply from the OP or another party labelNov 10, 2020
@bradzacherbradzacher changed the titlefix(eslint-plugin): [consistent-type-imports] fix passive value import in decorator metadatafeat(eslint-plugin): [consistent-type-imports] fix passive value import in decorator metadataNov 10, 2020
@bradzacherbradzacher added the enhancementNew feature or request labelNov 10, 2020
@Frezc
Copy link
ContributorAuthor

requiring type information in the rule is a breaking change.
We should not be making this change as it hugely limits the usability of the rule.

I setallowWithoutFullTypeInformation = true togetParserServices. This won't make tsconfig optional ?

This is the wrong approach to fix this - this should be fixed in the scope analyser - not in the rule.
Fixing this in the scope analyser would benefitall consumers of scope information, and not just this specific rule.

emm.. I have no idea what is scope analyser. Can you give me a brief explanation?

@bradzacher
Copy link
Member

Thescope analyser is the tooling which runs over the AST and figures out what's a variable and where it is used.

Right now it doesn't understand that the decorators can consume values whenemitDecoratorMetadata is turned on.

So when it analyses

constructor(privatereadonlyconfig:ConfigService,privatereadonlyusersService:UsersService,privatereadonlylogger:Logger,privatereadonlyauthService:AuthService,  @InjectRepository(UserSessionRepository)privatereadonlyuserSessionRepository:UserSessionRepository,)

It doesn't understand thatprivate readonly config: ConfigService creates animplicit value reference onConfigService because there is a decorator andemitDecoratorMetadata is turned on.

Because it doesn't understand this - it just creates a type-only reference toConfigService.
This data then flows through to the lint rules (i.e.consistent-type-imports) which then look atimport ConfigService from './ConfigService', and sees only type-only imports - and flags it.

Fix the source of the data (the scope analyser) and the rule will "just work".

@bradzacherbradzacher removed the awaiting responseIssues waiting for a reply from the OP or another party labelDec 12, 2020
Copy link
Member

@bradzacherbradzacher left a comment
edited
Loading

Choose a reason for hiding this comment

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

Definitely heading in the right direction!
This is looking great so far!


Instead of intermingling all of this logic withReferencer, I think we should separate it out into its ownClassVisitor - similar to how we currently haveTypeVisitor andPatternVisitor.

Classes are a pretty strict set of things, so we can more easily isolate the logic and setup the appropriate state there.

I mention this as there is one case that you haven't yet handled with your implementation code:

importThingfrom'thing';@decoratorclassFoo{constructor(arg:Thing,){}}

In this example, the decorator on the class with a constructor creates a similar reference to that of a decorated method.

playground repl

Handling this case will involve another piece of local state and things could get messy at that point, because you can nest class declarations within methods:

@decoratorclassBar{constructor(arg:React.Component,){    @decoratorclassFoo{constructor(arg:React.Component,){}}}}

repl

So being able to doClassVisitor.visit(clazz) will be much nicer as we can construct one ClassVisitor per class and thus isolate the state entirely.


It's also worth noting that decorators are only ever valid for class declarations - so we could do some cleaner separation of logic to ignore bad cases:

@decoratorclassFoo{constructor(arg:React.Component,){}}@decorator// this is invalid (TS semantic error)constclassExpr=class{  @decorator// this is invalid (TS semantic error)method(    @decorator// this is invalid (TS semantic error)arg:React.Component,){}}constobj={  @decorator// this is invalid (syntax error)method(    @decorator// this is invalid (TS semantic error)arg:React.Component,){}}

One other case I don't see tested, is this:

classFoo{method(    @decoratorarg1:Thing1,arg2:Thing2,){}}

repl

In this instance - TS will emit metadata aboutbothThing1 andThing2, even though onlyarg1 is decorated.

All of the cases that I found TS to emit metadata are listed in my comment here:#2559 (comment)

Frezc reacted with thumbs up emoji
@bradzacherbradzacher added the awaiting responseIssues waiting for a reply from the OP or another party labelDec 13, 2020
@Frezc
Copy link
ContributorAuthor

I mention this as there is one case that you haven't yet handled with your implementation code:

importThingfrom'thing';@decoratorclassFoo{constructor(arg:Thing,){}}

In this example, the decorator on the class with a constructor creates a similar reference to that of a decorated method.

This case at:https://github.com/typescript-eslint/typescript-eslint/pull/2751/files#diff-0cfd7f7e671424ab7fca326415a261843e64acdd13ecb12fc5133bd98b642948R184-R198

One other case I don't see tested, is this:

classFoo{method(    @decoratorarg1:Thing1,arg2:Thing2,){}}

repl

In this instance - TS will emit metadata aboutbothThing1 andThing2, even though onlyarg1 is decorated.

I missed this, thanks for hint.

@bradzacher
Copy link
Member

bradzacher commentedDec 15, 2020
edited
Loading

One thing I didn't mention - please add some snapshot tests!

Your tests so far are great as they are explicit assertions of how it works, but as you've probably found out they're super cumbersome to write.

A snapshot test is less strict/safe as you have to manually eyeball the output, but they're nice because they're so easy to write. It means you can create isolated cases for each case and have a granular regression test.

They're also nice because they create a visual representation of the scope, which I found invaluable in figuring out how it all works.

https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/scope-manager/tests/fixtures/decorators

You can add the new scope manager optionhere

And then add this to the top of your fixture to turn on the option (example).

////@emitDecoratorMetadata = trueclassFixture{...}

@FrezcFrezc requested a review frombradzacherJanuary 3, 2021 15:05
Copy link
Member

@bradzacherbradzacher left a comment

Choose a reason for hiding this comment

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

Almost there! The code's looking good I think.

could you also add some snapshots for the nested class cases:

functiondeco(...param:any){}@decoclassA{constructor(foo:b.Foo){classB{constructor(bar:c.Foo){}}}}
functiondeco(...param:any){}classA{constructor(foo:b.Foo){    @decoclassB{constructor(bar:c.Foo){}}}}
functiondeco(...param:any){}@decoclassA{constructor(foo:b.Foo){    @decoclassB{constructor(bar:c.Foo){}}}}

They should all work fine - but a few extra snapshots to prevent regressions would be ace.

Thanks for sticking with this! We're almost there!

@bradzacherbradzacher removed the awaiting responseIssues waiting for a reply from the OP or another party labelJan 4, 2021
Copy link
Member

@bradzacherbradzacher left a comment

Choose a reason for hiding this comment

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

LGTM - thanks heaps for all of your work here and following this through to the end.
You've done a great job!

Comment on lines +104 to +111
Reference$9 {
identifier: Identifier<"T">,
isRead: true,
isTypeReference: true,
isValueReference: false,
isWrite: false,
resolved: Variable$5,
},
Copy link
Member

Choose a reason for hiding this comment

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

From the looks of it - this one is wrong.

This reference is for the pair:

set[keyName](a:T){}  @decoget[keyName](){}

TS will emitthe following code:

__decorate([deco,__metadata("design:type",T),__metadata("design:paramtypes",[])],A.prototype,_a,null);

So whilst it hasn't referenced the param type - it did reference the return type.
I don't think it's worth spending any time fixing this - it's a super rare usecase. Also it'll be a pretty hard case to reliably fix I think.

I'm 100% okay with just marking this as a KP and only looking at fixing it if someone runs into the issue.

@bradzacherbradzacher changed the titlefeat(eslint-plugin): [consistent-type-imports] fix passive value import in decorator metadatafeat: add support for decorator metadata in scope analysis and in consistent-type-importsJan 18, 2021
@bradzacherbradzacher merged commit445e416 intotypescript-eslint:masterJan 18, 2021
bradzacher added a commit that referenced this pull requestJan 19, 2021
…ass method default paramsFixes#2941Fixes#2942This was a regression introduced by#2751
bradzacher added a commit that referenced this pull requestJan 19, 2021
…ass method default params (#2943)Fixes#2941Fixes#2942This was a regression introduced by#2751
@miluoshi
Copy link
Contributor

miluoshi commentedJan 19, 2021
edited
Loading

I think this change broke@typescript-eslint/no-unused-vars rule for me.

After updating@typescript-eslint packages fromv4.13.0 tov4.14.0 the@typescript-eslint/no-unused-vars rule started showing false positive in my codebase. After explicitly disablingemitDecoratorMetadata in tsconfig.json the warning disappears.

See attached screenshot:
image

1:10  warning  'ChangeDetectorRef' is defined but never used                      @typescript-eslint/no-unused-vars

edit: There were related issues created#2946#2947

kmaraz, marecektn, mvnrhd, robertohuertasm, and pmstss reacted with thumbs up emoji

@bradzacher
Copy link
Member

And as linked above, this was fixed in#2943

miluoshi reacted with heart emoji

@pmstss
Copy link

Seems something is still wrong with this change. After updating from 4.13.0 to 4.14.1 (or 4.14.0)@typescript-eslint/no-unused-vars reports false positives.

image

Single usage of importedMultiFactorState is marked with an arrow.

@bradzacher
Copy link
Member

bradzacher commentedJan 28, 2021
edited
Loading

Don't comment on old, closed PRs. The comments are not easily discoverable by other users, and PRs do not show up in the "issues" tab - further hiding them from other users.

There is a pinned issue to follow, which is easily discoverable by using theissue search forno-unused-vars

@typescript-eslinttypescript-eslint locked asresolvedand limited conversation to collaboratorsJan 28, 2021
Sign up for freeto subscribe to this conversation on GitHub. Already have an account?Sign in.
Reviewers

@bradzacherbradzacherbradzacher approved these changes

Assignees
No one assigned
Labels
enhancementNew feature or request
Projects
None yet
Milestone
No milestone
Development

Successfully merging this pull request may close these issues.

[consistent-type-imports] add support for passive value usage by decorators whenemitDecoratorMetadata is enabled
4 participants
@Frezc@bradzacher@miluoshi@pmstss

[8]ページ先頭

©2009-2025 Movatter.jp