226 Commits

Author SHA1 Message Date
Anton Gilgur
e8f59ef485
fix: don't error out while catching a buildStart error (#422)
- per in-line comment, if an error occurs during `buildStart` initialization, then the `cache` may not exist yet during `buildDone`
  - since we now use `context.error` instead of `throw` during initialization (from the `options` -> `buildStart` change), `buildEnd` will run during initialization
    - and the `cache` var is initialized in `buildStart` as well, so if an error occurs before then, the `cache` won't exist
      - we should gracefully handle this in all cases, since it's possible that even creating the `cache` could throw an error

- this error was hiding the underlying error, which was problematic for DX as well as bug reports (see my issue follow-up)

- add an integration test for `tsconfig` to make sure this code works
  - while this is similar to the previous `tsconfig` integration tests (that were moved to unit tests), this covers all cases of `buildStart` errors, and is not specific to the different `tsconfig` errors (unlike the unit tests)
  - this test will fail without the source code changes in this commit
2022-09-20 09:47:04 -06:00
Anton Gilgur
ba262937f8
refactor: consolidate diagnostics funcs into single file (#416)
* refactor: consolidate `diagnostics` funcs into single file

- move `IDiagnostic` and `convertDiagnostic` from `tscache` to `print-diagnostics`, then rename it to `diagnostics.ts`
  - the diagnostic funcs being in `tscache` always felt like a strange place for them
    - especially when `parse-tsconfig` or `print-diagnostics` would import them from `tscache`, which sounded like an unrelated file

- may want to move `diagnostics-format-host` into this file as well, as it is _only_ used in this file
  - leaving as is for now, limiting this change to a smaller one

* test: add unit test for `convertDiagnostic`

- this was previously only covered in integration tests
  - since unit tests don't currently touch `index` or `tscache`, and `convertDiagnostic` was previously in `tscache`
    - another reason why consolidating these functions into one file made sense

* fix(diagnostics): use `formatHost.getNewLine()` instead of `\n`

- since new lines are host OS specific

- this fixes the `convertDiagnostic` test on Windows too, where it was failing
2022-09-12 10:12:50 -06:00
Anton Gilgur
560ed8dac7
fix: handle all type-only imports by piping TS imports (#406)
* fix: handle all type-only imports by piping TS imports

- `result.references` is populated by `ts.preProcessFile`; i.e. this is TS discovering all imports, instead of Rollup
  - TS's imports include type-only files as TS understands those (whereas they aren't emitted in the JS for Rollup to see, since, well, they produce no JS)
  - so we can pipe all these through Rollup's `this.resolve` and `this.load` to make them go through Rollup's `resolveId` -> `load` -> `transform` hooks
    - this makes sure that other plugins on the chain get to resolve/transform them as well
    - and it makes sure that we run the same code that we run on all other files on type-only ones too
      - for instance: adding declarations, type-checking, setting them as deps in the cache graph, etc
      - yay recursion!
        - also add check for circular references b/c of this recursion (which Rollup docs confirm is necessary, per in-line comment)
    - and Rollup ensures that there is no perf penalty if a regular file is processed this way either, as it won't save the hook results when it appears in JS (i.e. Rollup's module graph)
      - we are checking more files though, so that in and of itself means potential slowdown for better correctness

- add a test for this that uses a `tsconfig` `files` array, ensuring that the `include` workaround won't cover these type-only files
  - this test fails without the new code added to `index` in this commit
  - also add another file, `type-only-import-import`, to the `no-errors` fixture to ensure that we're not just checking imports one level deep, and actually going through type-only imports of type-only imports as well
    - the declaration check for this will fail if type-only imports are not handled recursively
      - an initial version of this fix that I had that didn't call `this.load` failed this check

- refactor(test): make the integration tests more resilient to output ordering changes
  - due to the eager calls to `this.load`, the ordering of declaration and declaration map outputs in the bundle changed
    - and bc TS's default ordering of imports seems to differ from Rollup's
  - note that this only changed the order of the "bundle output" object -- which Rollup doesn't guarantee ordering of anyway
    - all files are still in the bundle output and are still written to disk
    - for example, the `watch` tests did not rely on this ordering and as such did not need to change due to the ordering change
  - create a `findName` helper that will search the `output` array instead, ensuring that most ordering does not matter
    - we do still rely on `output[0]` being the bundled JS (ESM) file, however

- refactor(test): go through a `files` array for tests that check for multiple files instead of listing out each individual check
  - this makes the tests more resilient to fixture changes as well (i.e. addition / deletion of files)
  - create `no-errors.ts` that exports a list of files for this fixture
    - didn't need to do the same for `errors.ts` as of yet; may do so in the future though

* move type-only recursion to after declarations are added to the `declarations` dict

- preserve some ordering and simplify future debugging

- also fix lint issue, `let modules` -> `const modules`
  - I previously changed it (while WIP), but now it's static/never reassigned, so can use `const`

* rewrite the core logic with a `for...of` loop instead

- simpler to follow than `map` + `filter` + `Promise.all`
  - might(?) be faster without `Promise.all` as well as more can happen async without waiting
    - (I'm not totally sure of the low-level implementation of async to know for sure though)

* add comment about normalization
2022-08-30 13:07:13 -06:00
Anton Gilgur
c6be0eb3a8
refactor(cache): simplify creating / using the cache var (#415)
- as everything is created in the `buildStart` hook now (which has `RollupContext`), we can create the `cache` there too
  - no need for slightly hacky, lazy creation during `transform` anymore
  - simplifies it and also standardizes it so it's created the same way as all the other instance vars

- fix: reset `cache` after each watch cycle
  - previously the cache was never reset, meaning that if anything became dirty in a watch cycle, it would never get reset back
    - in some cases, this would mean that the cache was effectively always dirty during an entire watch mode run, and therefore never used
      - this would be quite inefficient as the FS usage for the cache would just go to waste
  - see that test coverage has now increased as a result!
2022-08-30 09:12:22 -06:00
Anton Gilgur
1e71d5064d
clean: remove ConsoleContext entirely by using buildStart (#414)
- the only reason that `ConsoleContext` was still used was because the `options` hook doesn't support certain context functions like `this.error` / `this.warn` etc
  - but `buildStart` does! so we can just move pretty much everything into `buildStart` instead
    - didn't move setting `rollupOptions` because that value gets hashed and the value in `buildStart` is different, as it is after all plugins' `options` hooks have ran
    - this way we don't need `ConsoleContext` what-so-ever and so can remove it entirely!
      - as well as `IContext`, its tests, etc

- use `this.error` instead of `throw`ing errors in `parse-tsconfig` as it exists now
  - couldn't in the `options` hook, can in `buildStart`
  - this also ensure we don't have all the `rpt2: ` prefixes ever missing again
    - c.f. ff8895103c8466694e7d8eeb734f51d2850670d8, 0628482ea26ddf56e6ef5521e4dcb85ef5b4beb6
  - refactor `parse-tsconfig.spec` to account for this change

- c.f. Rollup hooks docs: https://rollupjs.org/guide/en/#options, https://rollupjs.org/guide/en/#buildstart
2022-08-29 08:47:30 -06:00
Anton Gilgur
79053fe82f
refactor: combine check-tsconfig with parse-tsconfig (#413)
- `checkTsConfig` is literally only used by `parseTsConfig`
  - I first just moved the function over, but it's a two-liner, so thought it made more sense to just in-line it

- merge the unit tests as well
  - we already check the non-error case in `parse-tsconfig.spec`, so only add the error case

- `check-tsconfig` was longer in the past and more files were being created then for separation, so this may have made more sense then, but now it is unnecessary
  - c.f. 733207791800ffe15672554d2a6337c73c65cf74
2022-08-24 23:22:20 -06:00
Anton Gilgur
88863838a0
fix(dx): remove extra quote in emitDeclarationOnly log statement (#412)
- must've been a copy+paste mistake or something
2022-08-24 22:53:55 -06:00
Anton Gilgur
3fc8caf3d9
test(cache): ignore coverage for corrupted cache check (#401)
- similar to the other safety checks in `clean`, this won't be hit during normal usage
2022-08-19 15:02:15 -06:00
Anton Gilgur
697e839708
clean: remove redundant generateRound === 0 check (#400)
- when `options` is called, `generateRound` should have already been reset to `0`, so this is redundant / unnecessary
  - `options` is only called once per watch cycle
  - `options` is also an `input` hook, not an `output` hook, i.e. it's only called once for _all_ outputs, _not_ per each output
    - `generateRound` only tracks the output round

- this might be leftover historical remnants prior to Rollup officially separating `output` hooks, but even before then, it should only have been called once for _all_ outputs
  - since, per the Rollup API, it's only called during `rollup.rollup` and not during `bundle.generate` etc
  - c.f. old docs https://github.com/rollup/rollup/blob/v1.18.0/docs/05-plugin-development.md#options
  - it's possible this is _even older_, but I couldn't find plugin docs for Rollup pre-1.0 to try to confirm against
2022-08-19 15:01:58 -06:00
Anton Gilgur
d286015ad2
test: add parse-tsconfig spec (#397)
* test: add `parse-tsconfig` spec

- test passing tsconfig, buggy tsconfig, non-existent tsconfig, and not a tsconfig
- clean: "failed to read" error will never happen as we already checked for existence of the file earlier
  - so remove the `undefined` check and instead use a non-null assertion (plus a comment explaining it)

- refactor: move the integration test for tsconfig error into this unit test instead
  - faster / more efficient / more precise

- refactor: split out a `makeOptions` func that creates default plugin options to use in tests
  - similar to `makeStubbedContext`

* fix windows test by normalizing

Co-authored-by: Eugene Zolenko <zolenkoe@gmail.com>
2022-08-19 14:59:39 -06:00
Anton Gilgur
c1f3a35dea
refactor: combine two context files into one (#396)
* refactor: combine two context files into one

- they're virtually identical, so combine them instead of keeping them separate
  - changes to one should probably be made to both
  - still a < 100 LoC file

- refactor out `_.isFunction` with a simple `getText` function instead
  - checks the opposite
  - one more lodash removal!

- add docstrings about when to use the two contexts

* disable tslint rule for this file
2022-08-19 14:58:02 -06:00
Anton Gilgur
bc01134c2b
revert: back to using vue.d.ts instead of .d.ts for Vue declarations (#410)
This reverts commit e145d0baebbbef1eec691b99d1ce0dce1e49f38c.

- Per discussion on the original issue and reverted PR, it seems that the request to use `.d.ts` instead of `.vue.d.ts` was made in error
  - `.d.ts` seems to only be necessary if Vue users were importing `.vue` SFCs without extensions ("extensionless")
    - i.e. `import MyComponent from "./MyComponent"` instead of `import MyComponent from "./MyComponent.vue"`
  - and "extensionless" imports are no longer supported by the Vue team (but used to be)
  - requiring extensionless imports also breaks imports when extensions _are_ used
  - so these are not necessarily compatible with each other, but the Vue team support strongly suggests that `.vue.d.ts` would be the proper way forward
2022-08-18 17:05:15 -06:00
Anton Gilgur
c37dbf6ee9
refactor(diagnostics): simplify some conditionals (#402)
- reduce the complexity of the code by decreasing the amount of nesting

- note that `print` returns `void` anyway, so calling it within the `return` statement doesn't change anything
  - and this is within a `void` `forEach` at that too
2022-08-08 13:22:02 -06:00
Anton Gilgur
bbed47e16a
refactor(cache): further condense walkTree (#393)
- `forEach` returns `void`, so we can just `return` it and condense the `if` a bit
2022-08-08 13:20:05 -06:00
Anton Gilgur
ad29112a5f
refactor: split out an addDeclaration func (#392)
- DRY it up and follow the same pattern as `typecheckFile`
- this also standardizes some things like normalization etc so that they're harder to miss
2022-08-08 13:18:14 -06:00
Anton Gilgur
ed0fbd9b85
refactor: move snapshot check into typecheckFile (#391)
- just slightly simplify / DRY up repeated code
  - this matches the style of some of the other functions in the codebase, such as `emitDeclaration`, `getAllReferences`, etc

- also fix indentation in `typecheckFile`
  - apparently I double-intended this accidentally, so make it single indent
2022-08-08 13:16:35 -06:00
Anton Gilgur
3dda648f0f
refactor: move generateRound = 0 to buildEnd (#390)
- since the `buildEnd` hook exists nowadays, we can just reset it there, right before `generateBundle` is called for each output and increments it per output
- also modify the comment to account for this change and the fact that `buildEnd` exists and is used nowadays
2022-08-08 13:15:24 -06:00
Anton Gilgur
70c6e253e8
optim(cache): don't check imports for syntactic diagnostics (#389)
- Per the TS LS Wiki (https://github.com/microsoft/TypeScript/wiki/Using-the-Language-Service-API#design-goals), syntactic diagnostics only need to parse the specific file in question
  - since syntax is independent of imports; imports only affect semantics
2022-08-08 13:14:46 -06:00
Anton Gilgur
e75d97a758
optim(watch): don't reset DocumentRegistry b/t watch cycles (#388)
- we can re-use the same one during watch instead of resetting it in the `options` hook
  - should make the LS a bit faster / more efficient in watch mode as most source files are shared between watch cycles
2022-08-08 13:14:04 -06:00
Anton Gilgur
4d20f5c638
dx: be more explicit with emitSkipped error (#395)
- a few issues have reported that "failed to transpile" is a vague / confusing error
  - and `emitSkipped` actually _doesn't_ mean that it failed to transpile, as, in current versions of TS, it's not due to syntactic or semantic errors
- so explicitly say "Emit skipped" instead, which is slightly less vague, in that it can actually be used as a search term
  - and provide a link to my TS issue that lists some reasons why `emitSkipped` occurs, since this is unfortunately otherwise undocumented by TS
    - in the future, hopefully that issue will be resolved and we'll be able to give better or more specific error messages, but for now this is probably the best we can do due to its undocumented nature, unfortunately
2022-08-08 13:11:48 -06:00
Anton Gilgur
d17864d875 dx(cache): improve clean edge-case errors with quotes (#394)
- follows the style of most of the other errors in the codebase
  - when referencing a variable, file path, etc, put quotes around it in the output
    - so it's easier to distinguish in the log
2022-08-08 13:11:18 -06:00
Anton Gilgur
c2b3db2300
fix: don't duplicate type-only check on Windows (#385)
- gotta remember to normalize file names 🙃
  - this fixes a failing test on Windows by fixing the underlying bug

- refactor: improve normalization in errors.spec
  - normalize _all_ calls to `local`, instead of just one
  - this doesn't affect the tests, only the source code change does, but I added this first and it's better practice / test future-proofing
2022-07-21 12:15:15 -06:00
Anton Gilgur
eab48a3951
fix: type-check included files missed by transform (type-only files) (#345)
* fix: type-check `include`d files missed by transform (type-only files)

- type-only files never get processed by Rollup as their imports are
  elided/removed by TS in the resulting compiled JS file
  - so, as a workaround, make sure that all files in the `tsconfig`
    `include` (i.e. in `parsedConfig.fileNames`) are also type-checked
    - note that this will not catch _all_ type-only imports, in
      particular if one is using `tsconfig` `files` (or in general _not_
      using glob patterns in `include`) -- this is just a workaround,
      that requires a separate fix
  - we do the same process for generating declarations for "missed"
    files right now in `_onwrite`, so basically do the same thing but
    for type-checking in `_ongenerate`

(_technically_ speaking, there could be full TS files
(i.e. _not_ type-only) that are in the `include` and weren't
transformed
- these would basically be independent TS files not part of the bundle
  that the user wanted type-checking and declarations for (as we
  _already_ generate declarations for those files))

* move misssed type-checking to `buildEnd` hook, remove declarations check

- `buildEnd` is a more correct place for it, since this does not generate any output files
  - (unlike the missed declarations)
  - and this means it's only called once per build, vs. once per output

- remove the check against the `declarations` dict as one can type-check without outputting declarations
  - i.e. if `declaration: false`; not the most common use-case for rpt2, but it is one

* add new checkedFiles Set to not duplicate type-checking

- since `parsedConfig.fileNames` could include files that were already checked during the `transform` hook
- and because `declarations` dict is empty when `declaration: false`, so can't check against that

* move checkedFiles.add to the beginning of typecheckFile

- because printing diagnostics can bail if the category was error
  - that can result in a file being type-checked but not added to checkedFiles

* wip: fuse _ongenerate functionality into buildEnd, _onwrite into generateBundle

- per ezolenko, the whole generateRound etc stuff was a workaround because the buildEnd hook actually _didn't exist_ before
  - so now that it does, we can use it to simplify some logic
  - no longer need `_ongenerate` as that should be in `buildEnd`, and no longer need `_onwrite` as it is the only thing called in `generateBundle`, so just combine them
  - importantly, `buildEnd` also occurs before output generation, so this ensures that type-checking still occurs even if `bundle.generate()` is not called

- also move the `walkTree` call to above the "missed" type-checking as it needs to come first
  - it does unconditional type-checking once per watch cycle, whereas "missed" only type-checks those that were, well, "missed"
  - so in order to not have duplication, make "missed" come after, when the `checkedFiles` Set has been filled by `walkTree` already

- and for simplification, just return early on error to match the current behavior
  - in the future, may want to print the error and continue type-checking other files
    - so that all type-check errors are reported, not just the first one

NOTE: this is WIP because the `cache.done()` call and the `!noErrors` message are incorrectly blocked behind the `pluginOptions.check` conditional right now
- `cache.done()` needs to be called regardless of check or error or not, i.e. in all scenarios
  - but ideally it should be called after all the type-checking here
- `!noErrors` should be logged regardless of check or not
  - and similarly, after the type-checking

* call `cache().done()` and `!noErrors` in check and non-check conditions

- instead of making a big `if` statement, decided to split out a `buildDone` function
  - to always call at the end of the input phase

- we can also move the `cache().done()` in `emitSkipped` into `buildEnd`, as `buildEnd` gets called when an error occurs as well
  - and this way we properly print for errors as well

- `buildDone` will have more usage in other PRs as well, so I figure it makes sense to split it out now as well

* use `RollupContext` for type-only files

- i.e. bail out when `abortOnError: true`, which `ConsoleContext` can't do
  - `ConsoleContext` is basically meant for everywhere `RollupContext` can't be used
    - which is effectively only in the `options` hook, per the Rollup docs: https://rollupjs.org/guide/en/#options

* add test for type-only file with type errors

- now that the integration tests exist, we can actually test this scenario

- refactor: give each test their own `onwarn` mock when necessary
  - while `restoreMocks` is set in the `jest.config.js`, Jest apparently has poor isolation of mocks: https://github.com/facebook/jest/issues/7136
    - if two tests ran in parallel, `onwarn` was getting results from both, screwing up the `toBeCalledTimes` number
  - couldn't get the syntax error to work with `toBeCalledTimes` either
    - if no mock is given, it _does_ print warnings, but if a mock is given, it doesn't print, yet isn't called?
      - I think the mock is getting screwed up by the error being thrown here; maybe improperly saved or something
2022-07-12 10:01:01 -06:00
Anton Gilgur
af271af204
feat: capture watch mode when called via the Rollup API (#384)
- `process.env.ROLLUP_WATCH` is only set when using the CLI
  - when using watch mode through the Rollup API (https://rollupjs.org/guide/en/#rollupwatch), this is not set
  - but since Rollup 2.14.0 (https://github.com/rollup/rollup/blob/master/CHANGELOG.md#2140), `this.meta.watchMode` is available
    - still check the env variable for backward-compat on older Rollup versions

- notably, this is needed to test watch mode, since the tests are done via the Rollup API
2022-07-12 09:56:35 -06:00
Anton Gilgur
0628482ea2
feat: add rpt2 prefix to remaining errors (#382)
- most were added in ff8895103c8466694e7d8eeb734f51d2850670d8, but these two were missed

- this should now cover all **thrown** errors
  - they only get thrown in the `options` hook, which does not implement Rollup's `this.error`
  - all other errors are already auto-prefixed by RollupContext etc
2022-07-12 09:56:03 -06:00
Anton Gilgur
76109fcfe9
fix: missing tsconfig error shouldn't say undefined (#383)
- per the conditional above this line, `file` is falsey, so printing it doesn't make sense
  - per same conditional though, `pluginOptions.tsconfig` exists, so we can print that

- fixes a test TODO/FIXME that had to workaround this bug as well
2022-07-12 09:55:48 -06:00
Anton Gilgur
dcae517e38
fix: add back noErrors = false to emitSkipped (#381)
- apparently `emitSkipped` can indeed happen without there being a semantic or syntactic error
  - so add back the previous unconditional behavior of `noErrors`

- still not clear what exactly triggers `emitSkipped` though, see my TS issue
2022-07-12 09:54:27 -06:00
Anton Gilgur
9c508989b8
docs: mention module: "ES2020" compatibility (#376)
- it's already been supported since eb1dd17babde0b22e9540b12e671eb56d9d6bce0, but the docs and error message were not updated to mention it
  - so add both to make sure users aren't confused
  - also re-order it to be ES2015, ES2020, then ESNext consistently, which is their module order (c.f. https://github.com/microsoft/TypeScript/issues/24082)

- modify test to account for the new error message
  - make it a bit more resilient to change by only testing a substring as well (c.f. https://jestjs.io/docs/expect#tothrowerror)
2022-07-05 22:11:14 -06:00
Anton Gilgur
d078f3f577
clean: remove backward-compat checks for old Rollup versions (#374)
- we require Rollup `>=1.26.3` in the peerDeps and the README and have for years now
  - (and Rollup is currently at `2.75.7`, so this is a pretty low target)
  - as such, we can remove various checks that are legacy backward-compat remnants for old Rollup versions:
    - `this.meta` was added to `options` in `1.1.0`: https://github.com/rollup/rollup/blob/master/CHANGELOG.md#110
    - `this.addWatchFile` was added at least in `1.0.0`: https://github.com/rollup/rollup/blob/master/CHANGELOG.md#100
    - `this.error` and `this.warn` were added to `transform` in `0.41.0`: https://github.com/rollup/rollup/blob/master/CHANGELOG.md#0410

- this simplifies some of the code a decent bit, `RollupContext` in particular
  - see also the usage of `buildEnd` in my other PR

- modify tests to account for these changes; basically just simplify them
  - and remove the check against private internals of the class, as they're private
    - guess I forgot to remove this when I was refactoring the test code?
2022-07-05 21:56:54 -06:00
Anton Gilgur
00b4414401
fix(diagnostics): workaround Rollup duplicating error messages (#373)
* fix(diagnostics): workaround Rollup duplicating error messages

- per my investigation in the linked issues, it seems like Rollup has a bug where it duplicates some error message
  - this occurs when the error has a stack (or frame) which contains the error message itself
    - Rollup prints _both_ the error message _and_ the stack in that case, causing duplication

- this fix adds a workaround for this upstream Rollup bug
  - it detects if there is a stack and if the message is duplicated in the stack
    - if so, it removes the duplication in the stack
  - this workaround should be forward-compatible if this behavior is fixed upstream
    - this code should just end up re-throwing in that case (effectively a no-op)

* fix watch mode by spreading err

- apparently Rollup attaches several properties to the error object, including `watchFiles`
  - so removing them / not spreading causes watch to just stop working

here are some of the additional properties I logged out, for example:
```js
{
    id: '/project-dir/src/difference.ts',
    hook: 'transform',
    code: 'PLUGIN_ERROR',
    plugin: 'rpt2',
    watchFiles: [
      '/project-dir/src/index.ts',
      '/project-dir/tsconfig.json',
      '/project-dir/src/types.ts',
      '/project-dir/src/difference.ts'
    ]
  }
}
```
2022-07-05 21:53:08 -06:00
Anton Gilgur
f048e770be
fix(diagnostics): pretty defaults to true in TS 2.9+ (#372)
- per https://www.typescriptlang.org/tsconfig#pretty
  - TS 2.9 changed the default to `true`: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html#--pretty-output-by-default
    - so this is a legacy remnant of older versions of TS
- this is why `tsc` by default pretty prints, even when `pretty` is unset
  - only if it is _explicitly_ set to `false` does it not do that

- so change rpt2's diagnostic printing to be `pretty` by default as well
  - I think this is a pretty _big_ DX improvement, to be honest
  - I always thought something was up with the error reporting, but saw that there was code for `pretty`, so didn't quite connect the dots until now
    - that while there was code for it, the default was wrong, and so unless I set `pretty: true`, I wasn't getting easier to read printing
      - and given that `pretty: true` is the default, that's a redundant / unnecessary option to set in `tsconfig` that I normally wouldn't ever re-set
2022-07-05 21:52:13 -06:00
Anton Gilgur
8334c9b50f
fix(cache): invalidate codeCache in most cases when imports change (#369)
* fix(cache): invalidate declarations when imports change

- previously, the `checkImports` flag was set to `true` for type-checking, but `false` for compilation
  - I _believe_ it is `false` because the compiled JS shouldn't change if an import changes
    - though I'm not sure if that was the original intent behind the code
  - problematically though, compilation results can include declarations, and those _can_ change if imports change
    - for instance, the types of an import can change the declaration that is output
  - so now, only set it to `false` for compilation if declarations are _not_ needed

* add `!isolatedModules` check as well

- ezolenko gave a good example of enums, which can indeed cause the compiled JS code to change based on imports
  - so also check `!isolatedModules` as well
  - I thought it might be the case that the code wouldn't handle other edge cases, but couldn't think of one off the top of my head
    - ironically, I compared it to Babel, which transpiles per file, and Babel _requires_ `isolatedModules` to work
2022-07-04 23:04:13 -06:00
Anton Gilgur
63a644a762
clean(cache): remove unused checkNewCache parameter (#368)
- it is set to `true` in every usage, so just always check the new cache and remove the parameter entirely
  - rewrite the comments to reflect this change
    - and condense them a bit
  - modify tests a bit to reflect this change as well
2022-06-28 23:42:44 -06:00
Anton Gilgur
67f1d86a96
refactor(cache): simplify noCache condition (#362)
- if there is no cache, we don't need to do any operations on a cache at all, so we can just totally skip all the cache operations and return early
  - this should be a perf improvement, at the very least on memory usage, as lots of stuff isn't created or processed now
    - this may make `clean: true` a more optimal choice for smaller projects, as the FS usage when writing to cache may be slower than the small amount of compilation and type-checking required in small projects

- to start, from the constructor, the only necessary piece when `noCache` is the dependency tree
  - this is needed for `walkTree` and `setDependency` to function, but otherwise is unused when `noCache`
    - this _might_ be able to be further optimized to remove the graph entirely when `noCache`, but that is saved for potential future work and not part of this commit
  - so, we can just move the tree creation further up in the constructor as its previous ordering within the constructor does not actually matter
  - once this is done, we can just early return when `noCache` instead of doing all the cache-related actions, since they're not neeeded when there is no cache
    - no need to set `cacheDir` or any hashes etc since they're not used
      - note that `clean` only uses `cachePrefix` and `cacheRoot`, which are already set, and does not use `cacheDir`
    - no need to `init` the cache as it's not used
      - also slightly change the ordering to move `init` right after its prereqs are done, i.e. setting `cacheDir`, `hashOptions`, etc
        - just keeps with the flow instead of calling it in the middle of the ambient type processing
    - no need to check ambient types as that is only used for cache invalidation (marking things dirty), which is not used when there is no cache
      - note that `isDirty` is literally never called when `noCache`

- from there, since we don't call `checkAmbientTypes` or `init` when `noCache` (the constructor is the only place they are called and they are both `private`), we can entirely remove their `noCache` branches
  - fairly simple for `checkAmbientTypes`, we just remove the tiny if block that sets `ambientTypesDirty`, as, well, "dirty" isn't used when there is no cache
  - for `init`, this means we can entirely remove the creation of `NoCache`, which isn't needed when there is no cache
    - that means we can also remove the implementation and tests for `NoCache`
      - and the reference to it in `CONTRIBUTING.md`

- in `done`, we can also simply skip rolling caches and early return when there is no cache

- the only other tiny change is the non-null assertions for `ambientTypes` and `cacheDir`
  - this matches the existing, simplifying non-null assertions for all the caches, so I did not workaround that
    - _could_ set a default of an empty array for `ambientTypes` etc to workaround this, but thought it better to match existing code style and not add new things
  - this also matches the behavior, as while `ambientTypes` and `cacheDir` could be `null`, this is only if there is no cache, in which case, they are never used
2022-06-24 10:38:49 -06:00
Anton Gilgur
229dea56da
refactor(cache): split a getCached function out (#360)
- basically, refactor the `getDiagnostics` a tiny bit to also handle what the `getCompiled` function needs
  - then just call `getCached` from both instead
  - `getDiagnostics` and `getCompiled` were near identical except for the cache they used and `checkImports`, which are both parameters now
    - `getCompiled` also had a logging statement (called in both `noCache` and w/ cache branches), which was moved to before the call to `getCompiled` instead
    - the `type` param was composed into another function in `getDiagnostics` before the call too `getCached` now
  - this simplifies all the cache code to one main function now

- remove the `markAsDirty` call under `noCache`, as well, "dirty" has no meaning for `noCache` anyway
  - this simplifies that one `if` statement now too
2022-06-24 10:36:19 -06:00
Anton Gilgur
b2584971da
fix(host): getScriptSnapshot must also call fileNames.add (#364)
- 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)
2022-06-24 10:34:42 -06:00
Anton Gilgur
74f6761ff6
docs/clean: formally deprecate rollupCommonJSResolveHack (#367)
* docs/clean: formally deprecate `rollupCommonJSResolveHack`

- this has had no effect since 6fb0e75f5328666dca8ff7b11bc956096351a3eb, released in 0.30.0
  - that changed the code to always return OS native paths via the NodeJS Path API
    - so setting `rollupCommonJSResolveHack` would make no difference either `true` or `false`
      - effectively, it's as if it's always `true` now

- formally state now that this is deprecated in the docs
  - as well as when that occurred and what it means

- also add a warning in `options` similar to the existing one for `objectHashIgnoreUnknownHack`

- remove the `resolve` dependency as well
  - it turns out something in the devDeps still uses it, so it didn't get fully removed in the `package-lock.json`
  - `resolve` was never needed anyway as we could've used NodeJS's native `path.resolve` or `require.resolve` instead
    - `resolve` was created for `browserify` after all, where one can't use NodeJS APIs
      - but we run on NodeJS and can and already do use NodeJS APIs, including both `path.resolve` _and_ `require.resolve`
  - I actually started this commit just to remove the dep, then realized the entire code path is obsolete

* fix lint error -- resolved can now be const
2022-06-24 10:30:32 -06:00
Anton Gilgur
b0e39228b6
fix: don't skip resolving files imported by other plugins (#365)
- previously the `allImportedFiles` Set was _basically_ used to skip any files that were imported by other plugins
  - it only filtered out on `importer` (not `importee`)
  - this is a bit of a problem though, as other plugins that create JS code, or `allowJs` JS code, or heck, even regular JS code that Rollup processes without plugins, may actually import TS files
    - and Rollup's plugin system is designed to handle that scenario, so rpt2 actually _should_ resolve those files
      - notably, rpt2 already _transforms_ those files, it just didn't resolve them
        - which is why using `@rollup/plugin-node-resolve` with a `.ts` extension solved this as a workaround
          - the file would be resolved by `node-resolve` then actually transformed by rpt2
          - but rpt2 should resolve TS files itself, `node-resolve` shouldn't be necessary
    - this caused the issue that extensionless imports from such files wouldn't get resolved to TS files and may cause Rollup to error
      - in particular, this popped up with extensionless imports of TS files from Svelte files

- `resolveId` is actually the last remaining place where `allImportedFiles` was used
  - so after removing it from here, we can just remove it entirely
    - which should be a small optimization

- for reference:
  - `allImportedFiles` would be any `include`d files as well as TS files that have been transformed (at this point in the build) and their references
    - this is a pretty gigantic list as is, so I'm actually not sure that removing this is actually that big of a de-opt
      - and it only affects mixed TS / non-TS codebases too
  - this seems to have been added in b0a0ecb5ee8752a1e60962036beb52e9f5dcfff9, but that commit doesn't actually seem to fix the issue it references
    - see my root cause analyses in the issues
2022-06-24 10:28:18 -06:00
Anton Gilgur
4ea7f10c24
feat: support emitDeclarationOnly (#366)
- when `emitDeclarationOnly` is set, only perform type-checking and emit declarations, don't transform TS
  - `result.code` actually doesn't exist when `emitDeclarationOnly` is set anyway
    - this caused a confusing situation for users who were trying to use Babel (with Babel plugins) on TS and only use rpt2 for declarations
      - instead of getting any JS code, they would just get empty chunks, bc `result.code` is `undefined`
        - that's kind of buggy, it should probably either be forced to `false` or do what we're doing now, which is likely more intuitive / intended
  - so now, instead of getting an empty chunk, rpt2 will just pass to the next plugin, allowing for other plugins on the chain to process TS
    - this opens up some new use cases, like using in tandem with Babel plugins (as the issue illustrates) or using for type-checking and declaration generation while using Vite / ESBuild for compilation

- add a new paragraph to "Declarations" docs about this new feature and what it does and some examples of how it could be used
  - note that these are unexplored / untested integrations, so point that out in the docs too
  - also modify a self-reference further up in the docs to use code backticks for `rollup-plugin-typescript2`
- while at it, also add a line about declaration maps
- and reformat the existing paragraph a bit to match the style and improve readability
  - one sentence per line, which is all on the same paragraph in Markdown anyway
  - add a `<br />` element to add a new-line _within_ the paragraph for better readability / spacing
    - Markdown supports this only with two trailing spaces, which is difficult to see and the trailing whitespace can be trimmed by editors, so prefer `<br />`
2022-06-24 10:25:26 -06:00
Anton Gilgur
4de17cf987
refactor: use optional chaining for sourceMapCallback (#363)
- following other optional chaining simplifications
2022-06-24 10:23:28 -06:00
Anton Gilgur
b9dce9dfd1
refactor: split out a common typecheckFile func (#344)
* refactor: split out a common typecheckFile func

- this is used in 3 places and going to be more for the code I'm adding
  to fix type-only imports
  - so DRY it up and standardize the functionality too
    - some places had `noErrors = false` in one place while others had
      it in another
    - same for `printDiagnostics`
    - but the ordering actually doesn't matter, so just keep it
      consistent and the same
      - and then can split a common function that does both out

- technically, now getDiagnostics is _only_ used in typecheckFile, so
  I could link to the two together, but I'm refactoring that one up
  a little
  - but this a good, small example of how refactoring one part of a
    codebase can make it easier to identify more similar pieces and then
    refactor even more

* fix lint error on shadowed name
2022-06-20 16:39:13 -06:00
Anton Gilgur
fee9547ebc
refactor(cache): simplify clean method (#358)
* refactor(cache): simplify `clean` method

- `cache().clean()` is only called during instantiation in `options`, so we can instead just call it inside of the constructor
- there is no need to call `this.init()` in `clean` as it's only used in the constructor anyway, which already calls `this.init()`
  - and if `noCache` is `true`, `init` is basically a no-op too
    - so technically we don't need to call `init` _at all_ if `noCache`, but that's a larger refactor that I'm splitting into a separate commit/PR

- now that `clean` is just one conditional, we can invert it and return early instead
- it's also not necessary and less efficient to call `emptyDir` before `remove`; `remove` will unlink all the contents anyway
  - docs here: 0220eac966/docs/remove-sync.md
    - though this also just normal FS behavior
- IMO, it's also not necessary to check if it's a directory, we can `remove` it either way
  - and not necessary to log out if we _don't_ clean it
- then also just simplify the logic to use a `filter` instead of a nested `if`
  - which we already do in several places, so this follows existing code style

* undo dir and not clean log removal

- as requested in code review, will go with a safety-first operating assumption

- as such, with safety as modus operandus, make the logging more detailed in these scenarios, since they're not supposed to happen
  - and don't check code coverage on these as they're not supposed to happen in normal usage
2022-06-20 16:37:30 -06:00
Anton Gilgur
9ea15cecee
docs(cache): add a typedoc @returns to createHash (#361)
- follow-up to my previous commit
  - per comments, this has to be FS-safe, so I thought it would be good to explicitly mention that somewhere
2022-06-17 17:35:57 -06:00
Anton Gilgur
42c94b8c9d
refactor(cache): tiny simplification to walkTree (#359)
- the `acyclic` var is literally only used in one place, directly below its instantiation
  - so don't use a var at all instead for simplicity
2022-06-14 10:03:57 -06:00
Anton Gilgur
a31cda15a9
refactor(cache): simplify condition w/ optional chaining (#356)
- as I've done in other places, simplify a condition by using optional chaining syntax (over the previously necessary syntax with `&&` etc)

- also add a new line to the first `.map` here
  - for style consistency and because this is a super long line
  - this wasn't possible before the lodash refactor because it was all one big single statement in the chain
2022-06-14 08:36:04 -06:00
Anton Gilgur
4f93c443ef
refactor(cache): makeName -> createHash for clarity (#355)
* refactor(cache): makeName -> createHash for clarity

- I've actually been confused multiple times as to what `makeName` does when I read through the cache
  - I re-read the code and then am like "oh it's the hash"...
  - so thought renaming it to `createHash` would make things **a lot** clearer
    - `Name` -> `Hash`
    - `make` -> `create` because that's the more common terminology in programming

- also rename variables that reference `makeName`'s return from `name` to `hash`
  - for the same reason around clarity -- this way it's quicker to interpret whenever you see it too
  - not to mention, `name` can be confusing since we also have `id`, which is a path that is very similar to a name too
    - and lots of `fileName`s too
    - so good to disambiguate/differentiate a bit

* rename object-hash default import so no shadowed variables
2022-06-14 08:35:09 -06:00
Anton Gilgur
a3c26998a4
docs(cache): add/change some comments for clarity (#357)
- use typedoc for `isDirty` comment so that it actually appears in IDEs etc
  - and use `@returns` typedoc annotation for better specification
  - modify the comment a little for better grammar: 3 "or"s and no commas -> 1 "or" and commas
  - use more accurate terminology: "global types" -> "ambient types"
    - that's also more consistent in this codebase itself, where there's a legit function named `checkAmbientTypes`

- in `init`, specify that the `RollingCache` error should never actually happen
  - I was a bit confused by when this would happen, then checked the constructor, and the answer is basically never: it's an invariant / redundant error-check
  - also add a new line for style consistency
2022-06-14 08:32:31 -06:00
Anton Gilgur
d32cf839fa
refactor: simplify hosts to directly assign tsModule.sys where possible (#349)
- 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
2022-06-06 18:24:20 -06:00
Anton Gilgur
d9fc987044
refactor: invert another if for readabilty -- in get-options (#348)
- my previous commit was mostly focused on index.ts, this one is for
  get-options-overrides -- in general, I'm just trying to make old code
  more readable as I come across and then realize that the code can be
  re-written better, or, in this case, a conditional inverted
2022-06-06 18:19:29 -06:00
Anton Gilgur
4a0c2977f8
fix: filter "missed" declarations as well (#347)
- these should run through the same `filter` as runs in `transform` etc
  - prior to this, the plugin `exclude` would filter files in
    `transform`, meaning no JS would be output for them, but would still
    output declarations for these very same files that no JS was
    produced for
    - (this would only happen if one were using an `include` glob or
      something that made the file appear twice, i.e. once by Rollup
      in `transform` and once in `parsedConfig.fileNames`)
  - this change makes it so the plugin `exclude` affects both JS
    and DTS output equivalently
    - it was very confusing when it didn't, and users relied on setting
      different `tsconfig` `exclude`s to workaround this (as a
      `tsconfig` `exclude` would make the file not appear in
      `parsedConfig.fileNames`)
2022-06-06 18:18:23 -06:00