RFC: Extensibility model by weswigham · Pull Request #9038 · microsoft/TypeScript

We use our internal module resolution logic to resolve the location of the entrypoint of a plugin from the compilation, then pass that path off to the host to have it load the code. For our node host, this is just a require call. We then look at the exported values of this module and check for members annotated with the private member ["extension-kind"] which is intended to be one of the string literal values defined as valid ExtensionKinds. Later on, the loaded extensions can be retrieved and constructed when required, then have their methods called.

Please note: The extension API is not included anywhere in the compiler - however, an example of how to implement a package for using the extension API is given in the tests. It's my recommendation that the extension API be a separate package from TS proper, since the 'global' tsc needs to use the 'local' extension, and if that local extension has its own bundled typescript, then version mismatching can happen unexpectedly.

Additionally, to serve as a testbed for extension loading (and to implement a frequently asked for feature), single-pass semantic and syntactic lint extensions are also in this PR.

Thoughts:

  • We could implement the loadExtension method on other hosts similarly to how I've implemented it in the tests (if that is desirable). This is pretty much amounts to building a commonjs module loader into the compiler.

Future work: