Pure refactor. `tokens.ts` was getting too large. Split it into 2 files:
* `tokens.ts`: Tokens lifecycle methods - initialization, deserialization, and reset.
* `tokens_methods.ts`: Public methods on `SourceCode` e.g. `sourceCode.getFirstToken`.
Workspaces support (#17809) added overhead on JS side of hashmap lookups. Every call to `lintFile` has to look up details (e.g. registered rules, rule options) from hashmaps keyed by workspace URI.
### Perf
Take a different approach which is optimized for common case of there being only 1 workspace:
* At any time there's 1 "current workspace".
* Store rules, options, and CWD in top-level vars (back to how it was before #17809).
* Switch workspaces only when required. Switching reassigns the values in these top level vars.
Before:
* Get rules, options, and CWD from hashmaps keyed by workspace URI.
After:
* Quick check "is the current workspace the one we need?".
* If so, do nothing - the top-level vars `registeredRules`, `allOptions`, and `cwd` elready contain the right settings for the desired workspace.
* If current workspace is not the right one, look up the details for desired workspace in `workspaces` hash map and write them into the top-level vars.
In CLI, `workspaceUri` passed to `lintFile` etc is `null`, so the quick "in the right workspace?" check is particularly cheap - just `null === null`. So this reduces the overhead that workspace support adds to CLI to just that 1 instruction.
Add of these functions are entirely synchronous, so there's no possibility of a race where 1 call switches out the values in the top-level vars, while another call is busy using them.
### CLI: No call to `createWorkspace`
CLI now doesn't need to call `createWorkspace` at all. The "are we in right workspace?" check always succeeds, so it's irrelevant whether a workspace has been created or not - `workspaces` hashmap is never accessed.
So workspaces is now an LSP-only thing.
### Bundle
This PR also removes all imports from other files from `src-js/workspace/index.ts`. It now only imports `debugAssert`, which is optimized out in release build., leaving no imports at all.
Previously, the imports from other files were causing most of the JS plugins code to get loaded on first call to `createWorkspace`, which broke the lazy loading optimization - Oxlint CLI and LSP were both loading all the JS plugins code eagerly even if the user doesn't use JS plugins.
With this change, the lazy loading optimization is restored. This is visible in the conformance snapshot change in this PR.
Pass `cwd` into `setupFileContext`, so it can be set per file, rather than being a global setting.
This is preamble to #17809. This PR is some of the changes from that one split off, so the diff on #17809 is focused just on that one change.
This PR does nothing in itself, as currently `process.cwd()` is always passed to `setupFileContext`.
Pure refactor. No point passing an object around through functions, when `parserServices` is always an empty object, as Oxlint provides no parser services. Just define it as an empty object inline.
Pure refactor of tests.
Unit tests for `isSpaceBetween` were using `@typescript-eslint/typescript-estree` to parse code snippets.
Instead use Oxc parser, and set up global state the same way as if the file was being linted, instead of mocking `source_code.ts` to get the source text into the linter's internals.
This brings the tests closer to real usage. It also prepares the way for changing how tokens are parsed in a following PR (#16805).
Remove `// @ts-expect-error` and `// @ts-ignore` comments from test fixtures, and use assertions instead. This makes sure that the input to methods under test is what we intend it to be.
Note: Using `assert` rather than `expect`, because `assert` gives TypeScript information about types, which `expect` doesn't seem to be capable of.