- the `fileNames` Set that was previously introduced in c86e07bc caused a regression during watch mode
- this is because `setSnapshot` was updated to call `this.fileNames.add`, but `getScriptSnapshot` was not
- instead of updating both to be the same, we can just call `setSnapshot` from `getScriptSnapshot` as this code is supposed to be identical
- also rename `data` -> `source` for consistency and clarity (`source` is a more specific name)
- no need to duplicate types this way, which can and have changed over
time -- it's always the same typings this way
- also reorganize `host.ts` to have similar categories of functions near
each other, instead of a mix of functions wherever
- similar to how I organized the tests for `host` as well
- shrink the code a bit this way too
- add a comment about `getDefaultLibFileName`'s confusing naming
pointing to the TS issues about how this is an old mistake but
changing it now would be breaking
- this is also how the TS Wiki recommends setting up hosts: https://github.com/microsoft/TypeScript/wiki/Using-the-Compiler-API#incremental-build-support-using-the-language-services
- NOTE: because of how `tsproxy` works to support alternate TS
implementations, this does require that `tsModule` _exists_ at the
time of instantiation, i.e. that `setTypescriptModule` has already
been called
- for `host.ts`, `LanguageServiceHost` is only instantiated after
`setTypescriptModule`, but for `diagnostics-format-host.ts`, it is
immediately instantiated (at the bottom of the file), hence why
`getCurrentDirectory` can't just be assigned to `tsModule.sys`
- there is a way to fix this, but the refactoring is more complex
as it would require creating in `index.ts` and then passing it
as an argument -- would want to refactor more at that point too,
so leaving that out for now in this otherwise small, isolated
refactor
- for a different, but related reason, the `host.trace` tests have to
mock `console` instead of just `console.log`, since `trace` would
just be set to the old, unmocked `console.log` otherwise
- as it's assigned directly to `console.log` now
- basically, general format is:
```ts
import x from "external-dep"
import y from "./internal-dep"
```
- so external deps, new line, then internal/local deps
- with some further sorting within there, like trying to keep Node
built-ins (e.g. `path`) at the top half of externals, then core deps
like `typescript`, then any other external deps
- and similar for internal deps -- core internals at the top half of
internals, then any other internal deps
- just to keep things consistent between files -- makes the top
easier to read through when it's similar between files
- also makes it easier for contributors to understand where to put
imports, as there's a sorting already there
- this is how I generally sort my imports and how I wrote most of the
unit test suite's imports as well
- there is automation for this that we should probably add once TSLint
is replaced here; some previous art:
- https://github.com/trivago/prettier-plugin-sort-imports
- https://github.com/lydell/eslint-plugin-simple-import-sort/
- Older:
- https://github.com/renke/import-sort/tree/master/packages/import-sort-style-module
- https://github.com/mcdougal/js-isort
- inspired by Python's `isort` ofc
* fix: add `realpath` to host to properly resolve monorepos
- tested this in a pnpm repo with symlinked deps and it worked there,
so I believe this fixes all pnpm issues
- it may also fix some Lerna issues if they were due to symlinks, but
I didn't check those
- not sure about others, e.g. Rush, Yarn workspaces, Yarn PnP
- I figured out this was needed by staring at the TS source code and
then I found this line:
67673f324d/src/compiler/moduleNameResolver.ts (L1412)
- it expects `host.realpath` to be implemented for TS's `realPath` to
work correctly, otherwise it just returns the path with no
transformation (i.e. the path to the symlink instead of the
realpath)
- this is not documented _anywhere_ and we were hitting this when
calling `getEmitOutput`, before even using `moduleNameResolver`
- so I just tried implementing it... and it worked!
- notably, the other Rollup TS plugins don't implement this either???
- not sure how they don't error on this??
- note that I added a `!` as `realpath` doesn't have to be implemented
on `ts.sys`... but it is in the default implementation (see comment)
- I originally had a ternary with `fs.realpathSync` if it didn't exist
but that is literally what the default implementation uses
- can add this back in the future if it becomes an issue
* fix realpath test on windows
- _.endsWith -> String.endsWith
- _.concat -> Array.concat
- _.each -> Array.forEach
- _.filter -> Array.filter
- _.map -> Array.map
- _.some -> Array.some
- _.has -> `key in Object`
- _.defaults -> Object.assign
- _.get -> `?.` and `??` (optional chaining and nullish coalescing)
- refactor: replace fairly complicated `expandIncludeWithDirs` func to
just use a few simple `forEach`s
- not as FP anymore, more imperative, but much simpler to read IMO
- refactor: add a `getDiagnostics` helper to DRY up some code
- also aids readability IMO
- a few places are still using lodash, but this paves the way toward
removing it or replacing it with much smaller individual deps
- _.compact still used because Array.filter heavily complicates the
type-checking currently
- _.isFunction still used because while it's a one-liner natively,
need to import a function in several places
- also the package `lodash.isFunction` is lodash v3 and quite
different from the v4 implementation, so couldn't replace with it
unfortunately
- _.merge is a deep merge, so there's no native version of this
- but we may remove deep merges entirely in the future (as tsconfig
doesn't quite perform a deep merge), or could replace this with a
smaller `lodash.merge` package or similar
- see also https://github.com/you-dont-need/You-Dont-Need-Lodash-Underscore
- this was introduced in v4.1.0 of @rollup/pluginutils:
https://github.com/rollup/plugins/blob/master/packages/pluginutils/CHANGELOG.md#v410
- this is the same as the code in `normalize.ts` but it uses constants
from Node and is used by multiple Rollup plugins, so just helps with
standardization
- also less code and types to ship in the bundle!
- removed the dist files for `normalize` as well, but didn't do a build
in this commit as those are usually done in separate commits
If we have plugins that are ordered before typescript, e.g. `replace`,
the input to typescript should be the output of the previous plugin.
However, this doesn't happen, instead typescript transforms the original
file.
From my (possibly incorrect) analysis, this happens because of a cache
invalidation issue. If a module is processed by typescript before it is
transformed by the plugin, it seems the file is read directly from the
disk and inserted into the LanguageService `HostCache`. Later, when the
file is transformed by the plugin, there is a call to `setSnapshot` with
the "good" code (transformed by previous plugins), and then a call to
`getEmitOutput` which is expected to use the snapshot we had just set.
But this does *not* happen, instead we get the "bad" code from the
`HostCache`.
To fix this, make each call to `setSnapshot` increment the "script
version"; this tells typescript that it needs to reprocess the file.