-
Notifications
You must be signed in to change notification settings - Fork 17
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
✨ Move param dec to class #24
✨ Move param dec to class #24
Conversation
Codecov Report
@@ Coverage Diff @@
## master #24 +/- ##
==========================================
- Coverage 91.89% 91.52% -0.37%
==========================================
Files 4 4
Lines 111 118 +7
Branches 41 45 +4
==========================================
+ Hits 102 108 +6
- Misses 9 10 +1
Continue to review full report at Codecov.
|
Another compilation divergence came accross: // example class
class Decoratee {
someMethod(@Inject() param: String) {}
} Compiled by TS class Decoratee {
someMethod(param) { }
}
tslib_1.__decorate([
tslib_1.__param(0, Inject()),
tslib_1.__metadata("design:type", Function),
tslib_1.__metadata("design:paramtypes", [String]),
tslib_1.__metadata("design:returntype", void 0)
], Decoratee.prototype, "someMethod", null);
exports.Decoratee = Decoratee; Compiled by babel var Decoratee =
/*#__PURE__*/
function () {
function Decoratee() {
_classCallCheck(this, Decoratee);
}
_createClass(Decoratee, [{
key: "someMethod",
value: function someMethod(param) {}
}]);
return Decoratee;
}();
exports.Decoratee = Decoratee;
(0, Inject)()(Decoratee.prototype, "someMethod", 0); TS adds more metadata. Should we handle this in this PR as well?
import { types as t } from '@babel/core'; so that the CI passes? |
So I implemented the decorator installation anyway (by decorator installation I mean placing the decorator in the class/field decorator array instead of adding it after the class). I extended it quite a bit by now, so please have a good look and tell me if I should split it in several PRs or if you want something changed. I am quite excited that babel comes this close to TypeScript with just some wrapping. Metadata on Methods (other than the constructor)I added the The |
Hey @leonardfactory, can you have a look at this PR? Is there anything I should change? |
Hi @wtho! sorry for the delay but I've been busy these days. Your job seems outstanding. I'm reviewing it but I'll need some time to do some tests and check it 👍 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You got a real good catch here! Thank you for this contribution, and for your precious work. It seems to me this should work just as usual and should not break existing projects, however just adapt the code style in order to keep it clean. Waiting for your changes in order to merge this cool piece of work.
src/metadata/metadataVisitor.ts
Outdated
) | ||
) | ||
); | ||
// decorators!.push( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please, add a comment here warning that following code is just an hint for future works about returnType
: elseway this seems just like a forgotten copy paste 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a shorter comment with a useful reference to the TSC compiler. If someone wants to tackle this at some time, this will be a good starting point.
339b142
to
d4395ed
Compare
The parameter decorator is now not applied on the class after the class declaration, but instead added as class decorator itself. This is imitated from TypeScript compilation. It leads to more consistency between compilers and increases compatibility of libraries that depend on this behavior. Furthermore the `design:type` decorator is also added to each decorated class (with value `Function`, as TSC does as well).
d4395ed
to
1371f6b
Compare
I think it won't behave differently in most projects, although some might depend on the way or order the decorators are applied. I personally would prefer to release a major version, but it's up to you. If you want me to add additional notes to the README or changelog, I'll be happy to do so! |
@leonardfactory we are still waiting on this feature. Would be awesome if you could have another look at it. I already fixed the changes requested, and thinking again about it being breaking, I think it does not have to be. It adds some additional decorators, but does not remove any that were applied before. If you are hesitant to merge and deploy, I would be happy if you could already publish a beta version. Cheers! |
Codecov Report
@@ Coverage Diff @@
## master #24 +/- ##
==========================================
- Coverage 91.89% 91.52% -0.37%
==========================================
Files 4 4
Lines 111 118 +7
Branches 41 45 +4
==========================================
+ Hits 102 108 +6
- Misses 9 10 +1
Continue to review full report at Codecov.
|
@wtho I'm willing to merge and release this asap, however got some issues with type declarations from master. Just let me check them. |
The parameter decorator is now not applied on the class after the
class declaration, but instead added as class decorator itself.
This is imitated from TypeScript compilation.
It leads to more consistency between compilers and increases
compatibility of libraries that depend on this behavior.
Example
Compilation using TSC
To understand the change in this PR, we should also have a look at
tslib.__param
:So looking at
tslib_1.__param(idx, Inject())
and knowing thatInject()
will return a decorator function with the two argumentstarget
andfunction
, the__param
call basically is the decoratorCompilation using babel and this plugin, before this change
Compilation using babel with this PR change
As Decorators are applied in reverse order (in the example above
dec3
, thendec2
, and thendec
), some libraries may rely on the class decorator (heredec
) being applied after the parameter decorator (dec2
). Angular's Dependency Injection in fact does rely on this. This PR solves this.How it works
The new function in
parameterVisitor
transforms the previously postponed decorator call into a classical decorator, that gets called with the others. It wraps the expression the same waytslib.__param
does inside another function call, as it has to be passed previously.Side Effects
If the class has only a parameter decorator, no class decorator, previously
Reflect.metadat('design:paramtypes', ...
was never called on the class. Now that we transform the parameter decorator to a kind of class decorator, it will be called anyway. This leads to the novel possibility of metadata about constructor parameter being available through reflection at runtime, although no true class decorator is applied. This coincidentally solves #22.To Clarify
TODO
Solves #23, #22