-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Suggestion: CompilerHost should be able to "plug into" a LanguageServiceHost #9017
Comments
Thanks for this awesome writeup and summarizing the points of the conversation! 💯 |
No problem I'm glad I could clarify!!! |
CC @chuckjaz as we had a chat with about this issue. So why do you use |
CC @s-panferov @jbrantly, please chime up if I'm not explaining this right. @mhegazy @chuckjaz so I said above that webpack is responsible for serving individual files one at a time to a loader. In that case, you can't use CompilerHost on one TS file at a time (because you lose program context between transpilation). LSH provides the ability to build up your Program of files, and then additionally update them only compiling that one file in the context of the Program. Is there something I am missing? |
This may be relevant to plugin-typescript as well. |
The LanguageService API (LS), and the matching host, LanguageServiceHost (LSH), are built for IDE/Editor scenarios. The LS is mainly designed to be able to answer questions like get completions at position, quick info, formatting edits, etc.. one thing that the LS has to do well is update the state after an edit. The Compiler API, (i.e. createProgram), and the matching host implementation, CompilerHost, are designed for generating outputs and errors given a set of sources. Obviously there is an overlap. the LS is a higher level abstraction than the Compiler API. but, assuming i understand your needs correctly, you do not really need it. If i understand correctly, what you need is given some source file, generate js/map/declarations, and compute errors. generating outputs and errors are done through Caching state, and reusing it is done through two things:
For reusing the SourceFiles, the CompilerHost API has The second is achieved by passing the old program to the The LS can do this for you as well, as part of other things, but as noted before, you do not need the LS to do this. I think the request here is for an API, that given a Program instance, and a set of edits, generate a new program with reusing as much as possible. if this is accurate, then we can definitely do that. |
First, I want to thank you and @DanielRosenwasser for the support while you guys are in the midst of a crazy busy and awesome TS2.0 timeline. I apoligize if this response is messy but its hard for me to track everything in both loaders to ensure that the right things are done here.
Not quite, what's needed is: (again @s-panferov and @jbrantly please correct me on this)
https://github.com/TypeStrong/ts-loader/blob/master/index.ts#L587-L633 |
|
To simplify requirements:
@TheLarkInn wants some kind of plugins, that are able to modify source code using semantic information (if I'm correct). So maybe we need a fast way to update Program's semantic information from the new file independently of diagnostics output (to get the new semantic state available for the plugin during a |
@s-panferov Thank you so much for the much more accurate translation! Your support in this has been invaluable. |
The dependency graph is not something that is provide today by the LS or the Compiler API. so we can use this issue to track adding it. |
one thing to note, as There are two operations, 1. transpilation, and 2. typechecking transpilation can be done most of the time on a single file. you can use typechecking is a project wide operation. can not be done on a single file. but it does generate errors. obviously, transpiling a single file is significantly faster than typechecking the whole project. but the two are not the same. so if you do not care about errors, e.g. you report them from a different channel e.g. IDE, full build step, then use |
@mhegazy: your explanation of LanguageService vs CompilerHost, caching etc should be in the Compiler Api docs :) |
@DanielRosenwasser wanted to bump this issue for relevance. This is still a definite need for not only webpack loaders, but also angular and potentially broccoli-typescript plugin. |
@TheLarkInn, chiming in here - this is relevant to karma-typescript too since the The upside of this approach is that I can use the The downside is that it's such a clunky workaround imo: it adds an unwanted delay to the compilation, there's always the risk of race conditions introducing subtle bugs etc. So this would be a more than welcome addition to the Typescript API. |
With #20234, i think the underlying issues in this thread should all be addressed. #20234 introduces two new concepts, a Builder and a Watcher. |
Background
The traditional method of transpiling a typescript application is through
ts.CompilerHost
. This is awesome, and there are slowly becoming more and more CompilerHost based "flavors" oftsc
that developers are wanting to use. I spoke about this with @alexeagle and @mhegazy briefly on this as well:Webpack Loaders
A webpack loader in its most simple form does the following:
As you can see all a loader does is take a raw source, and return it. On top of this webpack handles file resolution through some crafty regex:
Webpack Typescript Loaders Cannot & Should Not Use
ts.CompilerHost
So knowing what we know about how a file is tranformed and resolved through webpack,
ts.CompilerHost
is not an option for a ts-webpack loader. Why? Loaders are a powerful tool in webpack because they can be chained together with other loaders. For example: This Angular2 TS Loader I wrote. CompilerHost (as you know probably) runs a build/transpiliation against a whole project, and not one file per time. Therefore if you tried to plop a CompilerHost in a webpack loader, it would lose the context between each file.Webpack TS Loaders &
ts.LanguageServiceHost
.Because of this, the current typescript webpack loaders that are being used (ts-loader, awesome-typescript-loader) are both using
ts.LanguageServiceHost
. Why? Because LSG's support transpilation at a long-term lifetime one-file-at-a-time transpilation, persisting the transpile context back to thets.Program
. (This is tranditionally useful for IDE'S yes, but its a match made in heaven for a webpack loader). I would call this an 'edge-case' request, however, with 5+ million downloads a month, webpack is increasingly more popular than any bundler at the moment.The Problem:
Trying to use
ts.CompilerHost
implementations in ats.LanguageServiceHost
is a huge pain, and doesn't port well into an existing LSH. Its true that they share some functions, however there lacks a way to use a CompilerHost in a LanguageService incrementally.The Solution.
Create some way to attach the functionality of a custom CompilerHost implementation, and then perform it on a per-file basis, updating the
LanguageServiceHost
to help persist the transpilation/program contex. This will allow not only @s-panferov and @TypeStrong able to create plugin's systems that allow for super powerful TS builds in webpack. Or instead a plugin system where you add/override certain functionalities to an existing LSH.Please refer to this conversation thread of me explaining the issue to @DanielRosenwasser with lots of examples:
Start: https://gitter.im/Microsoft/TypeScript?at=5757ab04662b042b7e596b70
End: https://gitter.im/Microsoft/TypeScript?at=5757b77445cf128e5f1d7429
References
#6508 (comment)
angular/angular#8759
TypeStrong/ts-loader#223
https://github.com/TypeStrong/ts-loader/issues/
s-panferov/awesome-typescript-loader#153
TypeStrong/ts-loader#224
The text was updated successfully, but these errors were encountered: