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

Remove duplication from transformers #29871

Conversation

danielbodart
Copy link

@danielbodart danielbodart commented Feb 12, 2019

Fixes #28310, #24459, cevek/ttypescript#29

This pull requests removes duplication (chainBundle) from all the transformer functions and moves it to a single place (getTransformers).

This will then fix custom transformers so they work with single outFile compiler option (Bundle being passed) and gets rid of the need for chainBundle to be exposed.

This pull request is a refactoring to remove duplication and increase consistence by having a single way all transformers are used.

@msftclas
Copy link

msftclas commented Feb 12, 2019

CLA assistant check
All CLA requirements met.

@danielbodart
Copy link
Author

danielbodart commented Feb 12, 2019

Also replaced createBundle in chainBundle with version from transformTypeScript so it correctly handles InputFiles. Then removed from transformTypeScript so no duplication

rbuckton
rbuckton previously approved these changes Feb 13, 2019
@weswigham
Copy link
Member

It's worth noting that declaration after-transformers still won't be auto-chained (they don't use getTransformers, ofc) - this also precludes the ability for any custom transformer to specifically handle bundles (potentially by unbundling or by adding prepends).

@weswigham
Copy link
Member

(I think the other option proposed in the linked issue:

  1. leave everything as it is and write in the documentation that the transformer developer should support Bundle nodes.

Is probably better - we should update the docs to say that a custom transformer should handle bundle nodes and then expose chainBundle for use)

@danielbodart
Copy link
Author

danielbodart commented Feb 13, 2019

@weswigham I'm not sure I agree. You are making the normal use case suffer for the exception. Every single custom transformer that I have come across in the wild (mainly from the https://github.com/cevek/ttypescript home page) would need to be updated rather than they just work as expected.

I would argue it would be better to have a separate interface/contract for bundle transformers (if anyone actually wanted to do that). I'd probably make the method take a Bundle and return a Bundle, rather than passing the complexity down with union types.

@danielbodart
Copy link
Author

On the subject of declaration after-transformers, they already have a different type signature so it's probably too late to fix them but if it was my code I would simplify them and separate Bundle transformation as I mentioned previously.

@weswigham
Copy link
Member

Except the declaration transformer meaningfully transforms bundles, so it actually cares about them (quite a lot). I'm simply stating that it's not unlikely that a set of other transforms may exist which also care about weather or not files are being bundled and would like to manipulate that bundle.

@rbuckton
Copy link
Member

this also precludes the ability for any custom transformer to specifically handle bundles

This is a very good point. This could potentially be a breaking change for custom transforms.

@rbuckton rbuckton dismissed their stale review February 13, 2019 23:38

Potential breaking change.

@danielbodart
Copy link
Author

danielbodart commented Feb 14, 2019

Hmmm I don't think that's correct, right now customer transformers (excluding decorators as they have a different contact) can't transform bundles at all. They are broken when bundles are used. If you changed the signature for them you would break every single one out there. Changing an argument type to a union type is not backwards compatible.

This change is backward compatible, fixes them so they all work with bundles correctly with zero change and gets rid of a bunch of duplication. This change does not effect declaration transformers.

I would argue creating bundle transformers should be a separate method on custom transformers but it's out of scope for this change.

@danielbodart
Copy link
Author

@rbuckton Any more thoughts on this?

@weswigham
Copy link
Member

weswigham commented Feb 28, 2019

Like, if we're currently passing bundles to transformers, the type declaration is what's wrong, IMO - it should reflect that we're passing bundles (since anyone who's noticed the mismatch is being forced to handle them right now anyway).

@rbuckton
Copy link
Member

rbuckton commented May 7, 2019

Ideally a custom transformer should be able to take a bundle, but I agree that adding Bundle to a union is problematic. Instead of the changes mentioned in this PR, we should consider wrapping the custom transformers to handle bundles, since our API today only allows custom before and after transformers for SourceFile:

    export interface CustomTransformers {
        /** Custom transformers to evaluate before built-in .js transformations. */
        before?: TransformerFactory<SourceFile>[];
        /** Custom transformers to evaluate after built-in .js transformations. */
        after?: TransformerFactory<SourceFile>[];
        /** Custom transformers to evaluate after built-in .d.ts transformations. */
        afterDeclarations?: TransformerFactory<Bundle | SourceFile>[];
    }

We would need to consider a different mechanism to indicate whether a custom transformer supports Bundle, perhaps by modifying the definition as follows:

export type CustomTransformerFactory = (context: TransformationContext) => CustomTransformer;

export interface CustomTransformer {
    transformSourceFile(node: SourceFile): SourceFile;
    transformBundle(node: Bundle): Bundle;
}

export interface CustomTransformers {
    /** Custom transformers to evaluate before built-in .js transformations. */
    before?: (TransformerFactory<SourceFile> | CustomTransformerFactory)[];
    /** Custom transformers to evaluate after built-in .js transformations. */
    after?: (TransformerFactory<SourceFile> | CustomTransformerFactory)[];
    /** Custom transformers to evaluate after built-in .d.ts transformations. */
    afterDeclarations?: (TransformerFactory<Bundle | SourceFile> | CustomTransformerFactory)[];
}

@rbuckton
Copy link
Member

rbuckton commented May 7, 2019

I've submitted #31301 as an alternative to this approach.

@rbuckton
Copy link
Member

rbuckton commented May 8, 2019

Closing this PR as #31301 has been merged

@rbuckton rbuckton closed this May 8, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

API: Make public internal chainBundle
4 participants