WIP: bootstrap and partial real Solana watcher implementation
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.VariableBase = void 0;
|
||||
const ID_1 = require("../ID");
|
||||
const generator = (0, ID_1.createIdGenerator)();
|
||||
class VariableBase {
|
||||
/**
|
||||
* A unique ID for this instance - primarily used to help debugging and testing
|
||||
*/
|
||||
$id = generator();
|
||||
/**
|
||||
* The array of the definitions of this variable.
|
||||
* @public
|
||||
*/
|
||||
defs = [];
|
||||
/**
|
||||
* True if the variable is considered used for the purposes of `no-unused-vars`, false otherwise.
|
||||
* @public
|
||||
*/
|
||||
eslintUsed = false;
|
||||
/**
|
||||
* The array of `Identifier` nodes which define this variable.
|
||||
* If this variable is redeclared, this array includes two or more nodes.
|
||||
* @public
|
||||
*/
|
||||
identifiers = [];
|
||||
/**
|
||||
* The variable name, as given in the source code.
|
||||
* @public
|
||||
*/
|
||||
name;
|
||||
/**
|
||||
* List of {@link Reference} of this variable (excluding parameter entries) in its defining scope and all nested scopes.
|
||||
* For defining occurrences only see {@link Variable#defs}.
|
||||
* @public
|
||||
*/
|
||||
references = [];
|
||||
/**
|
||||
* Reference to the enclosing Scope.
|
||||
*/
|
||||
scope;
|
||||
constructor(name, scope) {
|
||||
this.name = name;
|
||||
this.scope = scope;
|
||||
}
|
||||
}
|
||||
exports.VariableBase = VariableBase;
|
||||
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* @deprecated
|
||||
* @module
|
||||
*/
|
||||
import { pallas as pn, vesta as vn } from './misc.ts';
|
||||
/** @deprecated */
|
||||
export const pallas: typeof pn = pn;
|
||||
/** @deprecated */
|
||||
export const vesta: typeof vn = vn;
|
||||
@@ -0,0 +1,9 @@
|
||||
function _initializerDefineProperty(e, i, r, l) {
|
||||
r && Object.defineProperty(e, i, {
|
||||
enumerable: r.enumerable,
|
||||
configurable: r.configurable,
|
||||
writable: r.writable,
|
||||
value: r.initializer ? r.initializer.call(l) : void 0
|
||||
});
|
||||
}
|
||||
export { _initializerDefineProperty as default };
|
||||
@@ -0,0 +1 @@
|
||||
export default true
|
||||
@@ -0,0 +1,77 @@
|
||||
import type { SourceType, TSESTree } from '@typescript-eslint/types';
|
||||
import type { Scope } from './scope';
|
||||
import type { Variable } from './variable';
|
||||
import { BlockScope, CatchScope, ClassScope, ConditionalTypeScope, ForScope, FunctionExpressionNameScope, FunctionScope, FunctionTypeScope, GlobalScope, MappedTypeScope, ModuleScope, SwitchScope, TSEnumScope, TSModuleScope, TypeScope, WithScope } from './scope';
|
||||
import { ClassFieldInitializerScope } from './scope/ClassFieldInitializerScope';
|
||||
import { ClassStaticBlockScope } from './scope/ClassStaticBlockScope';
|
||||
interface ScopeManagerOptions {
|
||||
globalReturn?: boolean;
|
||||
impliedStrict?: boolean;
|
||||
sourceType?: SourceType;
|
||||
}
|
||||
/**
|
||||
* @see https://eslint.org/docs/latest/developer-guide/scope-manager-interface#scopemanager-interface
|
||||
*/
|
||||
export declare class ScopeManager {
|
||||
#private;
|
||||
currentScope: Scope | null;
|
||||
readonly declaredVariables: WeakMap<TSESTree.Node, Variable[]>;
|
||||
/**
|
||||
* The root scope
|
||||
*/
|
||||
globalScope: GlobalScope | null;
|
||||
readonly nodeToScope: WeakMap<TSESTree.Node, Scope[]>;
|
||||
/**
|
||||
* All scopes
|
||||
* @public
|
||||
*/
|
||||
readonly scopes: Scope[];
|
||||
constructor(options: ScopeManagerOptions);
|
||||
isES6(): boolean;
|
||||
isGlobalReturn(): boolean;
|
||||
isImpliedStrict(): boolean;
|
||||
isModule(): boolean;
|
||||
isStrictModeSupported(): boolean;
|
||||
get variables(): Variable[];
|
||||
/**
|
||||
* Get the variables that a given AST node defines. The gotten variables' `def[].node`/`def[].parent` property is the node.
|
||||
* If the node does not define any variable, this returns an empty array.
|
||||
* @param node An AST node to get their variables.
|
||||
*/
|
||||
getDeclaredVariables(node: TSESTree.Node): Variable[];
|
||||
/**
|
||||
* Get the scope of a given AST node. The gotten scope's `block` property is the node.
|
||||
* This method never returns `function-expression-name` scope. If the node does not have their scope, this returns `null`.
|
||||
*
|
||||
* @param node An AST node to get their scope.
|
||||
* @param inner If the node has multiple scopes, this returns the outermost scope normally.
|
||||
* If `inner` is `true` then this returns the innermost scope.
|
||||
*/
|
||||
acquire(node: TSESTree.Node, inner?: boolean): Scope | null;
|
||||
/**
|
||||
* Adds dynamically created globals to the global scope and resolve their references.
|
||||
* This method is called by ESLint.
|
||||
* @param names Names of the globals to create
|
||||
*/
|
||||
addGlobals(names: string[]): void;
|
||||
nestBlockScope(node: BlockScope['block']): BlockScope;
|
||||
nestCatchScope(node: CatchScope['block']): CatchScope;
|
||||
nestClassFieldInitializerScope(node: ClassFieldInitializerScope['block']): ClassFieldInitializerScope;
|
||||
nestClassScope(node: ClassScope['block']): ClassScope;
|
||||
nestClassStaticBlockScope(node: ClassStaticBlockScope['block']): ClassStaticBlockScope;
|
||||
nestConditionalTypeScope(node: ConditionalTypeScope['block']): ConditionalTypeScope;
|
||||
nestForScope(node: ForScope['block']): ForScope;
|
||||
nestFunctionExpressionNameScope(node: FunctionExpressionNameScope['block']): FunctionExpressionNameScope;
|
||||
nestFunctionScope(node: FunctionScope['block'], isMethodDefinition: boolean): FunctionScope;
|
||||
nestFunctionTypeScope(node: FunctionTypeScope['block']): FunctionTypeScope;
|
||||
nestGlobalScope(node: GlobalScope['block']): GlobalScope;
|
||||
nestMappedTypeScope(node: MappedTypeScope['block']): MappedTypeScope;
|
||||
nestModuleScope(node: ModuleScope['block']): ModuleScope;
|
||||
nestSwitchScope(node: SwitchScope['block']): SwitchScope;
|
||||
nestTSEnumScope(node: TSEnumScope['block']): TSEnumScope;
|
||||
nestTSModuleScope(node: TSModuleScope['block']): TSModuleScope;
|
||||
nestTypeScope(node: TypeScope['block']): TypeScope;
|
||||
nestWithScope(node: WithScope['block']): WithScope;
|
||||
protected nestScope<T extends Scope>(scope: T): T;
|
||||
}
|
||||
export {};
|
||||
@@ -0,0 +1,12 @@
|
||||
'use strict'
|
||||
|
||||
const Range = require('../classes/range')
|
||||
const satisfies = (version, range, options) => {
|
||||
try {
|
||||
range = new Range(range, options)
|
||||
} catch (er) {
|
||||
return false
|
||||
}
|
||||
return range.test(version)
|
||||
}
|
||||
module.exports = satisfies
|
||||
@@ -0,0 +1,203 @@
|
||||
import { runInThisContext } from 'node:vm';
|
||||
import * as spyModule from '@vitest/spy';
|
||||
import { r as resolveTestRunner, a as resolveSnapshotEnvironment, d as detectAsyncLeaks, s as setupChaiConfig } from './index.DXx9Dtk7.js';
|
||||
import { l as loadEnvironment, e as emitModuleRunner, a as listenForErrors } from './init.k9zZ9sLh.js';
|
||||
import { N as NativeModuleRunner } from './nativeModuleRunner.BIakptoF.js';
|
||||
import { T as Traces } from './traces.DT5aQ62U.js';
|
||||
import { V as VitestEvaluatedModules } from './evaluatedModules.Dg1zASAC.js';
|
||||
import { s as startVitestModuleRunner, c as createNodeImportMeta } from './startVitestModuleRunner.DB-7oCpn.js';
|
||||
import { performance as performance$1 } from 'node:perf_hooks';
|
||||
import { startTests, collectTests } from '@vitest/runner';
|
||||
import { s as setupCommonEnv, b as startCoverageInsideWorker, c as stopCoverageInsideWorker } from './setup-common.DYx3LtFI.js';
|
||||
import { g as globalExpect, v as vi } from './test.DNmyFkvJ.js';
|
||||
import { c as closeInspector } from './inspector.CvyFGlXm.js';
|
||||
import { createRequire } from 'node:module';
|
||||
import timers from 'node:timers';
|
||||
import timersPromises from 'node:timers/promises';
|
||||
import util from 'node:util';
|
||||
import { KNOWN_ASSET_TYPES } from '@vitest/utils/constants';
|
||||
import { i as index } from './index.DdgEv5B1.js';
|
||||
import { g as getWorkerState, r as resetModules, p as provideWorkerState, a as getSafeWorkerState } from './utils.BX5Fg8C4.js';
|
||||
|
||||
// this should only be used in Node
|
||||
let globalSetup = false;
|
||||
async function setupGlobalEnv(config, environment) {
|
||||
await setupCommonEnv(config);
|
||||
Object.defineProperty(globalThis, "__vitest_index__", {
|
||||
value: index,
|
||||
enumerable: false
|
||||
});
|
||||
globalExpect.setState({ environment: environment.name });
|
||||
if (globalSetup) return;
|
||||
globalSetup = true;
|
||||
if ((environment.viteEnvironment || environment.name) === "client") {
|
||||
const _require = createRequire(import.meta.url);
|
||||
// always mock "required" `css` files, because we cannot process them
|
||||
_require.extensions[".css"] = resolveCss;
|
||||
_require.extensions[".scss"] = resolveCss;
|
||||
_require.extensions[".sass"] = resolveCss;
|
||||
_require.extensions[".less"] = resolveCss;
|
||||
// since we are using Vite, we can assume how these will be resolved
|
||||
KNOWN_ASSET_TYPES.forEach((type) => {
|
||||
_require.extensions[`.${type}`] = resolveAsset;
|
||||
});
|
||||
process.env.SSR = "";
|
||||
} else process.env.SSR = "1";
|
||||
// @ts-expect-error not typed global for patched timers
|
||||
globalThis.__vitest_required__ = {
|
||||
util,
|
||||
timers,
|
||||
timersPromises
|
||||
};
|
||||
if (!config.disableConsoleIntercept) await setupConsoleLogSpy();
|
||||
}
|
||||
function resolveCss(mod) {
|
||||
mod.exports = "";
|
||||
}
|
||||
function resolveAsset(mod, url) {
|
||||
mod.exports = url;
|
||||
}
|
||||
async function setupConsoleLogSpy() {
|
||||
const { createCustomConsole } = await import('./console.3WNpx0tS.js');
|
||||
globalThis.console = createCustomConsole();
|
||||
}
|
||||
|
||||
// browser shouldn't call this!
|
||||
async function run(method, files, config, moduleRunner, environment, traces) {
|
||||
const workerState = getWorkerState();
|
||||
const [testRunner] = await Promise.all([
|
||||
traces.$("vitest.runtime.runner", () => resolveTestRunner(config, moduleRunner, traces)),
|
||||
traces.$("vitest.runtime.global_env", () => setupGlobalEnv(config, environment)),
|
||||
traces.$("vitest.runtime.coverage.start", () => startCoverageInsideWorker(config.coverage, moduleRunner, { isolate: config.isolate })),
|
||||
traces.$("vitest.runtime.snapshot.environment", async () => {
|
||||
if (!workerState.config.snapshotOptions.snapshotEnvironment) workerState.config.snapshotOptions.snapshotEnvironment = await resolveSnapshotEnvironment(config, moduleRunner);
|
||||
})
|
||||
]);
|
||||
workerState.onCancel((reason) => {
|
||||
closeInspector(config);
|
||||
testRunner.cancel?.(reason);
|
||||
});
|
||||
workerState.durations.prepare = performance$1.now() - workerState.durations.prepare;
|
||||
await traces.$(`vitest.test.runner.${method}`, async () => {
|
||||
for (const file of files) {
|
||||
if (config.isolate) {
|
||||
moduleRunner.mocker?.reset();
|
||||
resetModules(workerState.evaluatedModules, true);
|
||||
}
|
||||
workerState.filepath = file.filepath;
|
||||
if (method === "run") {
|
||||
const collectAsyncLeaks = config.detectAsyncLeaks ? detectAsyncLeaks(file.filepath, workerState.ctx.projectName) : void 0;
|
||||
await traces.$(`vitest.test.runner.${method}.module`, { attributes: { "code.file.path": file.filepath } }, () => startTests([file], testRunner));
|
||||
const leaks = await collectAsyncLeaks?.();
|
||||
if (leaks?.length) workerState.rpc.onAsyncLeaks(leaks);
|
||||
} else await traces.$(`vitest.test.runner.${method}.module`, { attributes: { "code.file.path": file.filepath } }, () => collectTests([file], testRunner));
|
||||
// reset after tests, because user might call `vi.setConfig` in setupFile
|
||||
vi.resetConfig();
|
||||
// mocks should not affect different files
|
||||
vi.restoreAllMocks();
|
||||
}
|
||||
});
|
||||
await traces.$("vitest.runtime.coverage.stop", () => stopCoverageInsideWorker(config.coverage, moduleRunner, { isolate: config.isolate }));
|
||||
}
|
||||
|
||||
let _moduleRunner;
|
||||
const evaluatedModules = new VitestEvaluatedModules();
|
||||
const moduleExecutionInfo = /* @__PURE__ */ new Map();
|
||||
async function startModuleRunner(options) {
|
||||
if (_moduleRunner) return _moduleRunner;
|
||||
process.exit = (code = process.exitCode || 0) => {
|
||||
throw new Error(`process.exit unexpectedly called with "${code}"`);
|
||||
};
|
||||
const state = () => getSafeWorkerState() || options.state;
|
||||
listenForErrors(state);
|
||||
if (options.state.config.experimental.viteModuleRunner === false) {
|
||||
const root = options.state.config.root;
|
||||
let mocker;
|
||||
if (options.state.config.experimental.nodeLoader !== false) {
|
||||
// this additionally imports acorn/magic-string
|
||||
const { NativeModuleMocker } = await import('./nativeModuleMocker.BkNfQMkH.js');
|
||||
mocker = new NativeModuleMocker({
|
||||
async resolveId(id, importer) {
|
||||
// TODO: use import.meta.resolve instead
|
||||
return state().rpc.resolve(id, importer, "__vitest__");
|
||||
},
|
||||
root,
|
||||
moduleDirectories: state().config.deps.moduleDirectories || ["/node_modules/"],
|
||||
traces: options.traces || new Traces({ enabled: false }),
|
||||
getCurrentTestFilepath() {
|
||||
return state().filepath;
|
||||
},
|
||||
spyModule
|
||||
});
|
||||
}
|
||||
_moduleRunner = new NativeModuleRunner(root, mocker);
|
||||
return _moduleRunner;
|
||||
}
|
||||
_moduleRunner = startVitestModuleRunner(options);
|
||||
return _moduleRunner;
|
||||
}
|
||||
let _currentEnvironment;
|
||||
let _environmentTime;
|
||||
/** @experimental */
|
||||
async function setupBaseEnvironment(context) {
|
||||
if (context.config.experimental.viteModuleRunner === false) {
|
||||
const { setupNodeLoaderHooks } = await import('./native.DPzPHdi5.js');
|
||||
await setupNodeLoaderHooks(context);
|
||||
}
|
||||
const startTime = performance.now();
|
||||
const { environment: { name: environmentName, options: environmentOptions }, rpc, config } = context;
|
||||
// we could load @vite/env, but it would take ~8ms, while this takes ~0,02ms
|
||||
if (context.config.serializedDefines) try {
|
||||
runInThisContext(`(() =>{\n${context.config.serializedDefines}})()`, {
|
||||
lineOffset: 1,
|
||||
filename: "virtual:load-defines.js"
|
||||
});
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to load custom "defines": ${error.message}`);
|
||||
}
|
||||
const otel = context.traces;
|
||||
const { environment, loader } = await loadEnvironment(environmentName, config.root, rpc, otel, context.config.experimental.viteModuleRunner);
|
||||
_currentEnvironment = environment;
|
||||
const env = await otel.$("vitest.runtime.environment.setup", { attributes: {
|
||||
"vitest.environment": environment.name,
|
||||
"vitest.environment.vite_environment": environment.viteEnvironment || environment.name
|
||||
} }, () => environment.setup(globalThis, environmentOptions || config.environmentOptions || {}));
|
||||
_environmentTime = performance.now() - startTime;
|
||||
if (config.chaiConfig) setupChaiConfig(config.chaiConfig);
|
||||
return async () => {
|
||||
await otel.$("vitest.runtime.environment.teardown", () => env.teardown(globalThis));
|
||||
await loader?.close();
|
||||
};
|
||||
}
|
||||
/** @experimental */
|
||||
async function runBaseTests(method, state, traces) {
|
||||
const { ctx } = state;
|
||||
state.environment = _currentEnvironment;
|
||||
state.durations.environment = _environmentTime;
|
||||
// state has new context, but we want to reuse existing ones
|
||||
state.evaluatedModules = evaluatedModules;
|
||||
state.moduleExecutionInfo = moduleExecutionInfo;
|
||||
provideWorkerState(globalThis, state);
|
||||
if (ctx.invalidates) ctx.invalidates.forEach((filepath) => {
|
||||
(state.evaluatedModules.fileToModulesMap.get(filepath) || []).forEach((module) => {
|
||||
state.evaluatedModules.invalidateModule(module);
|
||||
});
|
||||
});
|
||||
ctx.files.forEach((i) => {
|
||||
const filepath = i.filepath;
|
||||
(state.evaluatedModules.fileToModulesMap.get(filepath) || []).forEach((module) => {
|
||||
state.evaluatedModules.invalidateModule(module);
|
||||
});
|
||||
});
|
||||
const moduleRunner = await startModuleRunner({
|
||||
state,
|
||||
evaluatedModules: state.evaluatedModules,
|
||||
spyModule,
|
||||
createImportMeta: createNodeImportMeta,
|
||||
traces
|
||||
});
|
||||
emitModuleRunner(moduleRunner);
|
||||
await run(method, ctx.files, ctx.config, moduleRunner, _currentEnvironment, traces);
|
||||
}
|
||||
|
||||
export { runBaseTests as r, setupBaseEnvironment as s };
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"typeFlags.d.ts","sourceRoot":"","sources":["../../src/enums/typeFlags.ts"],"names":[],"mappings":"AACA,eAAO,IAAI,SAAS,EAAE,GAAG,CAAC"}
|
||||
@@ -0,0 +1,53 @@
|
||||
# WebIDL Type Conversions on JavaScript Values
|
||||
|
||||
This package implements, in JavaScript, the algorithms to convert a given JavaScript value according to a given [WebIDL](http://heycam.github.io/webidl/) [type](http://heycam.github.io/webidl/#idl-types).
|
||||
|
||||
The goal is that you should be able to write code like
|
||||
|
||||
```js
|
||||
const conversions = require("webidl-conversions");
|
||||
|
||||
function doStuff(x, y) {
|
||||
x = conversions["boolean"](x);
|
||||
y = conversions["unsigned long"](y);
|
||||
// actual algorithm code here
|
||||
}
|
||||
```
|
||||
|
||||
and your function `doStuff` will behave the same as a WebIDL operation declared as
|
||||
|
||||
```webidl
|
||||
void doStuff(boolean x, unsigned long y);
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
This package's main module's default export is an object with a variety of methods, each corresponding to a different WebIDL type. Each method, when invoked on a JavaScript value, will give back the new JavaScript value that results after passing through the WebIDL conversion rules. (See below for more details on what that means.) Alternately, the method could throw an error, if the WebIDL algorithm is specified to do so: for example `conversions["float"](NaN)` [will throw a `TypeError`](http://heycam.github.io/webidl/#es-float).
|
||||
|
||||
## Status
|
||||
|
||||
All of the numeric types are implemented (float being implemented as double) and some others are as well - check the source for all of them. This list will grow over time in service of the [HTML as Custom Elements](https://github.com/dglazkov/html-as-custom-elements) project, but in the meantime, pull requests welcome!
|
||||
|
||||
I'm not sure yet what the strategy will be for modifiers, e.g. [`[Clamp]`](http://heycam.github.io/webidl/#Clamp). Maybe something like `conversions["unsigned long"](x, { clamp: true })`? We'll see.
|
||||
|
||||
We might also want to extend the API to give better error messages, e.g. "Argument 1 of HTMLMediaElement.fastSeek is not a finite floating-point value" instead of "Argument is not a finite floating-point value." This would require passing in more information to the conversion functions than we currently do.
|
||||
|
||||
## Background
|
||||
|
||||
What's actually going on here, conceptually, is pretty weird. Let's try to explain.
|
||||
|
||||
WebIDL, as part of its madness-inducing design, has its own type system. When people write algorithms in web platform specs, they usually operate on WebIDL values, i.e. instances of WebIDL types. For example, if they were specifying the algorithm for our `doStuff` operation above, they would treat `x` as a WebIDL value of [WebIDL type `boolean`](http://heycam.github.io/webidl/#idl-boolean). Crucially, they would _not_ treat `x` as a JavaScript variable whose value is either the JavaScript `true` or `false`. They're instead working in a different type system altogether, with its own rules.
|
||||
|
||||
Separately from its type system, WebIDL defines a ["binding"](http://heycam.github.io/webidl/#ecmascript-binding) of the type system into JavaScript. This contains rules like: when you pass a JavaScript value to the JavaScript method that manifests a given WebIDL operation, how does that get converted into a WebIDL value? For example, a JavaScript `true` passed in the position of a WebIDL `boolean` argument becomes a WebIDL `true`. But, a JavaScript `true` passed in the position of a [WebIDL `unsigned long`](http://heycam.github.io/webidl/#idl-unsigned-long) becomes a WebIDL `1`. And so on.
|
||||
|
||||
Finally, we have the actual implementation code. This is usually C++, although these days [some smart people are using Rust](https://github.com/servo/servo). The implementation, of course, has its own type system. So when they implement the WebIDL algorithms, they don't actually use WebIDL values, since those aren't "real" outside of specs. Instead, implementations apply the WebIDL binding rules in such a way as to convert incoming JavaScript values into C++ values. For example, if code in the browser called `doStuff(true, true)`, then the implementation code would eventually receive a C++ `bool` containing `true` and a C++ `uint32_t` containing `1`.
|
||||
|
||||
The upside of all this is that implementations can abstract all the conversion logic away, letting WebIDL handle it, and focus on implementing the relevant methods in C++ with values of the correct type already provided. That is payoff of WebIDL, in a nutshell.
|
||||
|
||||
And getting to that payoff is the goal of _this_ project—but for JavaScript implementations, instead of C++ ones. That is, this library is designed to make it easier for JavaScript developers to write functions that behave like a given WebIDL operation. So conceptually, the conversion pipeline, which in its general form is JavaScript values ↦ WebIDL values ↦ implementation-language values, in this case becomes JavaScript values ↦ WebIDL values ↦ JavaScript values. And that intermediate step is where all the logic is performed: a JavaScript `true` becomes a WebIDL `1` in an unsigned long context, which then becomes a JavaScript `1`.
|
||||
|
||||
## Don't Use This
|
||||
|
||||
Seriously, why would you ever use this? You really shouldn't. WebIDL is … not great, and you shouldn't be emulating its semantics. If you're looking for a generic argument-processing library, you should find one with better rules than those from WebIDL. In general, your JavaScript should not be trying to become more like WebIDL; if anything, we should fix WebIDL to make it more like JavaScript.
|
||||
|
||||
The _only_ people who should use this are those trying to create faithful implementations (or polyfills) of web platform interfaces defined in WebIDL.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,20 @@
|
||||
export { CharacterCodes } from "#enums/characterCodes";
|
||||
export { CommentDirectiveType } from "#enums/commentDirectiveType";
|
||||
export { InternalSymbolName } from "#enums/internalSymbolName";
|
||||
export { LanguageVariant } from "#enums/languageVariant";
|
||||
export { ModifierFlags } from "#enums/modifierFlags";
|
||||
export { NodeFlags } from "#enums/nodeFlags";
|
||||
export { RegularExpressionFlags } from "#enums/regularExpressionFlags";
|
||||
export { ScriptKind } from "#enums/scriptKind";
|
||||
export { ScriptTarget } from "#enums/scriptTarget";
|
||||
export { SyntaxKind } from "#enums/syntaxKind";
|
||||
export { TokenFlags } from "#enums/tokenFlags";
|
||||
export * from "./ast.ts";
|
||||
export * from "./astnav.ts";
|
||||
export * from "./clone.ts";
|
||||
export * from "./is.ts";
|
||||
export * from "./jsdoc.ts";
|
||||
export * from "./scanner.ts";
|
||||
export * from "./utils.ts";
|
||||
export * from "./visitor.ts";
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,8 @@
|
||||
"use strict";
|
||||
|
||||
function _type_of(obj) {
|
||||
"@swc/helpers - typeof";
|
||||
|
||||
return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
|
||||
}
|
||||
exports._ = _type_of;
|
||||
@@ -0,0 +1,325 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import { z } from "zod/mini";
|
||||
|
||||
test("recursion with z.lazy", () => {
|
||||
const data = {
|
||||
name: "I",
|
||||
subcategories: [
|
||||
{
|
||||
name: "A",
|
||||
subcategories: [
|
||||
{
|
||||
name: "1",
|
||||
subcategories: [
|
||||
{
|
||||
name: "a",
|
||||
subcategories: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const Category = z.object({
|
||||
name: z.string(),
|
||||
get subcategories(): z.ZodMiniOptional<z.ZodMiniArray<typeof Category>> {
|
||||
return z.optional(z.array(Category));
|
||||
},
|
||||
});
|
||||
Category.parse(data);
|
||||
|
||||
type Category = z.infer<typeof Category>;
|
||||
interface _Category {
|
||||
name: string;
|
||||
subcategories?: _Category[] | undefined;
|
||||
}
|
||||
expectTypeOf<Category>().toEqualTypeOf<_Category>();
|
||||
});
|
||||
|
||||
test("recursion involving union type", () => {
|
||||
const data = {
|
||||
value: 1,
|
||||
next: {
|
||||
value: 2,
|
||||
next: {
|
||||
value: 3,
|
||||
next: {
|
||||
value: 4,
|
||||
next: null,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const LL = z.object({
|
||||
value: z.number(),
|
||||
get next(): z.ZodMiniNullable<typeof LL> {
|
||||
return z.nullable(LL);
|
||||
},
|
||||
});
|
||||
|
||||
LL.parse(data);
|
||||
type LL = z.infer<typeof LL>;
|
||||
type _LL = {
|
||||
value: number;
|
||||
next: _LL | null;
|
||||
};
|
||||
expectTypeOf<LL>().toEqualTypeOf<_LL>();
|
||||
});
|
||||
|
||||
test("mutual recursion - native", () => {
|
||||
const Alazy = z.object({
|
||||
val: z.number(),
|
||||
get b() {
|
||||
return z.optional(Blazy);
|
||||
},
|
||||
});
|
||||
|
||||
const Blazy = z.object({
|
||||
val: z.number(),
|
||||
get a() {
|
||||
return z.optional(Alazy);
|
||||
},
|
||||
});
|
||||
const testData = {
|
||||
val: 1,
|
||||
b: {
|
||||
val: 5,
|
||||
a: {
|
||||
val: 3,
|
||||
b: {
|
||||
val: 4,
|
||||
a: {
|
||||
val: 2,
|
||||
b: {
|
||||
val: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
Alazy.parse(testData);
|
||||
Blazy.parse(testData.b);
|
||||
|
||||
type Alazy = z.infer<typeof Alazy>;
|
||||
type Blazy = z.infer<typeof Blazy>;
|
||||
interface _Alazy {
|
||||
val: number;
|
||||
b?: _Blazy | undefined;
|
||||
}
|
||||
interface _Blazy {
|
||||
val: number;
|
||||
a?: _Alazy | undefined;
|
||||
}
|
||||
expectTypeOf<Alazy>().toEqualTypeOf<_Alazy>();
|
||||
expectTypeOf<Blazy>().toEqualTypeOf<_Blazy>();
|
||||
|
||||
expect(() => Alazy.parse({ val: "asdf" })).toThrow();
|
||||
});
|
||||
|
||||
test("pick and omit with getter", () => {
|
||||
const Category = z.strictObject({
|
||||
name: z.string(),
|
||||
get subcategories() {
|
||||
return z.array(Category);
|
||||
},
|
||||
});
|
||||
|
||||
type Category = z.infer<typeof Category>;
|
||||
interface _Category {
|
||||
name: string;
|
||||
subcategories: _Category[];
|
||||
}
|
||||
expectTypeOf<Category>().toEqualTypeOf<_Category>();
|
||||
|
||||
const PickedCategory = z.pick(Category, { name: true });
|
||||
const OmittedCategory = z.omit(Category, { subcategories: true });
|
||||
type PickedCategory = z.infer<typeof PickedCategory>;
|
||||
type OmittedCategory = z.infer<typeof OmittedCategory>;
|
||||
interface _PickedCategory {
|
||||
name: string;
|
||||
}
|
||||
interface _OmittedCategory {
|
||||
name: string;
|
||||
}
|
||||
expectTypeOf<PickedCategory>().toEqualTypeOf<_PickedCategory>();
|
||||
expectTypeOf<OmittedCategory>().toEqualTypeOf<_OmittedCategory>();
|
||||
|
||||
const picked = { name: "test" };
|
||||
const omitted = { name: "test" };
|
||||
|
||||
PickedCategory.parse(picked);
|
||||
OmittedCategory.parse(omitted);
|
||||
|
||||
expect(() => PickedCategory.parse({ name: "test", subcategories: [] })).toThrow();
|
||||
expect(() => OmittedCategory.parse({ name: "test", subcategories: [] })).toThrow();
|
||||
});
|
||||
|
||||
test("deferred self-recursion", () => {
|
||||
const Feature = z.object({
|
||||
title: z.string(),
|
||||
get features(): z.ZodMiniOptional<z.ZodMiniArray<typeof Feature>> {
|
||||
return z.optional(z.array(Feature)); //.optional();
|
||||
},
|
||||
});
|
||||
type Feature = z.infer<typeof Feature>;
|
||||
|
||||
const Output = z.object({
|
||||
id: z.int(), //.nonnegative(),
|
||||
name: z.string(),
|
||||
features: z.array(Feature), //.array(), // <—
|
||||
});
|
||||
|
||||
type Output = z.output<typeof Output>;
|
||||
|
||||
type _Feature = {
|
||||
title: string;
|
||||
features?: _Feature[] | undefined;
|
||||
};
|
||||
|
||||
type _Output = {
|
||||
id: number;
|
||||
name: string;
|
||||
features: _Feature[];
|
||||
};
|
||||
|
||||
expectTypeOf<Feature>().toEqualTypeOf<_Feature>();
|
||||
expectTypeOf<Output>().toEqualTypeOf<_Output>();
|
||||
});
|
||||
|
||||
test("recursion compatibility", () => {
|
||||
// array
|
||||
const A = z.object({
|
||||
get subcategories() {
|
||||
return z.array(A);
|
||||
},
|
||||
});
|
||||
// tuple
|
||||
const B = z.object({
|
||||
get subcategories() {
|
||||
return z.tuple([B, B]);
|
||||
},
|
||||
});
|
||||
// object
|
||||
const C = z.object({
|
||||
get subcategories() {
|
||||
return z.object({
|
||||
subcategories: C,
|
||||
});
|
||||
},
|
||||
});
|
||||
// union
|
||||
const D = z.object({
|
||||
get subcategories() {
|
||||
return z.union([D, z.string()]);
|
||||
},
|
||||
});
|
||||
// intersection
|
||||
const E = z.object({
|
||||
get subcategories() {
|
||||
return z.intersection(E, E);
|
||||
},
|
||||
});
|
||||
// record
|
||||
const F = z.object({
|
||||
get subcategories() {
|
||||
return z.record(z.string(), F);
|
||||
},
|
||||
});
|
||||
// map
|
||||
const G = z.object({
|
||||
get subcategories() {
|
||||
return z.map(z.string(), G);
|
||||
},
|
||||
});
|
||||
// set
|
||||
const H = z.object({
|
||||
get subcategories() {
|
||||
return z.set(H);
|
||||
},
|
||||
});
|
||||
// optional
|
||||
const I = z.object({
|
||||
get subcategories() {
|
||||
return z.optional(I);
|
||||
},
|
||||
});
|
||||
// nullable
|
||||
const J = z.object({
|
||||
get subcategories() {
|
||||
return z.nullable(J);
|
||||
},
|
||||
});
|
||||
// optional
|
||||
const L = z.object({
|
||||
get subcategories() {
|
||||
return z.optional(L);
|
||||
},
|
||||
});
|
||||
// nullable
|
||||
const M = z.object({
|
||||
get subcategories() {
|
||||
return z.nullable(M);
|
||||
},
|
||||
});
|
||||
// nonoptional
|
||||
const N = z.object({
|
||||
get subcategories() {
|
||||
return z.nonoptional(N);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test("shape stays writeable through object/strictObject/looseObject/extend with getters", () => {
|
||||
const Cat = z.object({
|
||||
name: z.string(),
|
||||
get sub(): z.ZodMiniArray<typeof Cat> {
|
||||
return z.array(Cat);
|
||||
},
|
||||
});
|
||||
type CatShape = (typeof Cat)["shape"];
|
||||
expectTypeOf<CatShape>().toEqualTypeOf<{
|
||||
name: z.ZodMiniString<string>;
|
||||
sub: z.ZodMiniArray<typeof Cat>;
|
||||
}>();
|
||||
|
||||
const StrictCat = z.strictObject({
|
||||
name: z.string(),
|
||||
get sub(): z.ZodMiniArray<typeof StrictCat> {
|
||||
return z.array(StrictCat);
|
||||
},
|
||||
});
|
||||
type StrictShape = (typeof StrictCat)["shape"];
|
||||
expectTypeOf<StrictShape>().toEqualTypeOf<{
|
||||
name: z.ZodMiniString<string>;
|
||||
sub: z.ZodMiniArray<typeof StrictCat>;
|
||||
}>();
|
||||
|
||||
const LooseCat = z.looseObject({
|
||||
name: z.string(),
|
||||
get sub(): z.ZodMiniArray<typeof LooseCat> {
|
||||
return z.array(LooseCat);
|
||||
},
|
||||
});
|
||||
type LooseShape = (typeof LooseCat)["shape"];
|
||||
expectTypeOf<LooseShape>().toEqualTypeOf<{
|
||||
name: z.ZodMiniString<string>;
|
||||
sub: z.ZodMiniArray<typeof LooseCat>;
|
||||
}>();
|
||||
|
||||
const Base = z.object({ name: z.string() });
|
||||
const Extended = z.extend(Base, {
|
||||
get sub(): z.ZodMiniArray<typeof Extended> {
|
||||
return z.array(Extended);
|
||||
},
|
||||
});
|
||||
type ExtendedShape = (typeof Extended)["shape"];
|
||||
expectTypeOf<ExtendedShape>().toEqualTypeOf<{
|
||||
name: z.ZodMiniString<string>;
|
||||
sub: z.ZodMiniArray<typeof Extended>;
|
||||
}>();
|
||||
});
|
||||
@@ -0,0 +1,529 @@
|
||||
/// <reference path="../node/node.d.ts" preserve="true" />
|
||||
import { CompletionItemKind } from "#enums/completionItemKind";
|
||||
import { DiagnosticCategory } from "#enums/diagnosticCategory";
|
||||
import { ElementFlags } from "#enums/elementFlags";
|
||||
import { ModuleKind } from "#enums/moduleKind";
|
||||
import { NodeBuilderFlags } from "#enums/nodeBuilderFlags";
|
||||
import { ObjectFlags } from "#enums/objectFlags";
|
||||
import { SignatureFlags } from "#enums/signatureFlags";
|
||||
import { SignatureKind } from "#enums/signatureKind";
|
||||
import { SymbolFlags } from "#enums/symbolFlags";
|
||||
import { TypeFlags } from "#enums/typeFlags";
|
||||
import { TypePredicateKind } from "#enums/typePredicateKind";
|
||||
import { type __String, type Expression, type Identifier, ModifierFlags, type Node, type Path, type SourceFile, type SyntaxKind, type TypeNode } from "../../ast/index.ts";
|
||||
import type { APIOptions, LSPConnectionOptions } from "../options.ts";
|
||||
import type { CompilerOptions, ConfigResponse, DocumentIdentifier, DocumentPosition, LSPUpdateSnapshotParams, ProjectResponse, SignatureResponse, SourceFileMetadata, SymbolResponse, TypeResponse, UpdateSnapshotParams, UpdateSnapshotResponse } from "../proto.ts";
|
||||
import { SourceFileCache } from "../sourceFileCache.ts";
|
||||
import type { RequestTiming, TimingAccumulators, TimingInfo } from "../timing.ts";
|
||||
import { Client, type ClientSocketOptions, type ClientSpawnOptions } from "./client.ts";
|
||||
import type { AssertsIdentifierTypePredicate, AssertsThisTypePredicate, BigIntLiteralType, BooleanLiteralType, CompletionEntry, CompletionInfo, CompletionOptions, ConditionalType, Diagnostic, FreshableType, IdentifierTypePredicate, IndexedAccessType, IndexInfo, IndexType, InterfaceType, IntersectionType, IntrinsicType, JSDocTagInfo, LiteralType, NumberLiteralType, ObjectType, StringLiteralType, StringMappingType, SubstitutionType, TemplateLiteralType, ThisTypePredicate, TupleType, Type, TypeParameter, TypePredicate, TypePredicateBase, TypeReference, UnionOrIntersectionType, UnionType } from "./types.ts";
|
||||
export { documentURIToFileName, fileNameToDocumentURI } from "../path.ts";
|
||||
export { CompletionItemKind, DiagnosticCategory, ElementFlags, ModifierFlags, ModuleKind, NodeBuilderFlags, ObjectFlags, SignatureFlags, SignatureKind, SymbolFlags, TypeFlags, TypePredicateKind };
|
||||
export type { APIOptions, AssertsIdentifierTypePredicate, AssertsThisTypePredicate, BigIntLiteralType, BooleanLiteralType, ClientSocketOptions, ClientSpawnOptions, CompilerOptions, CompletionEntry, CompletionInfo, CompletionOptions, ConditionalType, Diagnostic, DocumentIdentifier, DocumentPosition, FreshableType, IdentifierTypePredicate, IndexedAccessType, IndexInfo, IndexType, InterfaceType, IntersectionType, IntrinsicType, JSDocTagInfo, LiteralType, LSPConnectionOptions, NumberLiteralType, ObjectType, RequestTiming, SourceFileMetadata, StringLiteralType, StringMappingType, SubstitutionType, TemplateLiteralType, ThisTypePredicate, TimingAccumulators, TimingInfo, TupleType, Type, TypeParameter, TypePredicate, TypePredicateBase, TypeReference, UnionOrIntersectionType, UnionType };
|
||||
export declare class API<FromLSP extends boolean = false> {
|
||||
private client;
|
||||
private sourceFileCache;
|
||||
private toPath;
|
||||
private initialized;
|
||||
private activeSnapshots;
|
||||
private latestSnapshot;
|
||||
readonly internal: InternalAPI;
|
||||
constructor(options?: APIOptions | LSPConnectionOptions);
|
||||
/**
|
||||
* Create an API instance from an existing LSP connection's API session.
|
||||
* Use this when connecting to an API pipe provided by an LSP server via custom/initializeAPISession.
|
||||
*/
|
||||
static fromLSPConnection(options: LSPConnectionOptions): Promise<API<true>>;
|
||||
private ensureInitialized;
|
||||
parseConfigFile(file: DocumentIdentifier): Promise<ConfigResponse>;
|
||||
updateSnapshot(params?: FromLSP extends true ? LSPUpdateSnapshotParams : UpdateSnapshotParams): Promise<Snapshot>;
|
||||
close(): Promise<void>;
|
||||
clearSourceFileCache(): void;
|
||||
/**
|
||||
* Returns a snapshot of collected timing information for requests made
|
||||
* through this API instance: client-measured round-trip latency and bytes
|
||||
* transferred, folded together with the server's own per-request processing
|
||||
* time and an estimated transport overhead (round-trip minus server time).
|
||||
*
|
||||
* Fetching the snapshot issues a lightweight request to the server to
|
||||
* retrieve its timing collection. Collection must be enabled via the
|
||||
* `collectTiming` option; when it is not, the returned snapshot has
|
||||
* `enabled: false` and zeroed totals.
|
||||
*/
|
||||
getTimingInfo(): Promise<TimingInfo>;
|
||||
/** Clears all accumulated timing totals and recent-request history, on both the client and the server. */
|
||||
resetTimingInfo(): Promise<void>;
|
||||
}
|
||||
export declare class InternalAPI {
|
||||
private client;
|
||||
private ensureInitialized;
|
||||
/** @internal */
|
||||
constructor(client: Client, ensureInitialized: () => Promise<void>);
|
||||
startCPUProfile(dir: string): Promise<void>;
|
||||
stopCPUProfile(): Promise<string>;
|
||||
saveHeapProfile(dir: string): Promise<string>;
|
||||
}
|
||||
export declare class Snapshot {
|
||||
readonly id: number;
|
||||
private projectMap;
|
||||
private toPath;
|
||||
private client;
|
||||
private disposed;
|
||||
private onDispose;
|
||||
private snapshotRegistry;
|
||||
constructor(data: UpdateSnapshotResponse, client: Client, sourceFileCache: SourceFileCache, toPath: (fileName: string) => Path, onDispose: () => void);
|
||||
getProjects(): readonly Project[];
|
||||
getProject(configFileName: string): Project | undefined;
|
||||
getDefaultProjectForFile(file: DocumentIdentifier): Promise<Project | undefined>;
|
||||
[globalThis.Symbol.dispose](): void;
|
||||
dispose(): Promise<void>;
|
||||
isDisposed(): boolean;
|
||||
private ensureNotDisposed;
|
||||
}
|
||||
declare class SnapshotObjectRegistry {
|
||||
private readonly symbols;
|
||||
private readonly client;
|
||||
private readonly snapshotId;
|
||||
private readonly resolveProject;
|
||||
constructor(client: Client, snapshotId: number, resolveProject: (projectId: Path) => Project | undefined);
|
||||
/** Resolve a project id (a config file path) to its Project within this snapshot. */
|
||||
getProject(projectId: Path): Project | undefined;
|
||||
getOrCreateSymbol(data: SymbolResponse): Symbol;
|
||||
getSymbol(id: number): Symbol | undefined;
|
||||
clear(): void;
|
||||
fetchSymbol(source: Symbol | Signature | Type, method: string, handle: number | undefined, projectId?: Path): Promise<Symbol>;
|
||||
fetchSymbols(source: Symbol | Signature | Type, method: string, handles?: readonly number[], projectId?: Path): Promise<readonly Symbol[]>;
|
||||
}
|
||||
declare class ProjectObjectRegistry {
|
||||
private client;
|
||||
private snapshotId;
|
||||
private project;
|
||||
private snapshotRegistry;
|
||||
private types;
|
||||
private signatures;
|
||||
constructor(client: Client, snapshotId: number, project: Project, snapshotRegistry: SnapshotObjectRegistry);
|
||||
getOrCreateSymbol(data: SymbolResponse): Symbol;
|
||||
getSymbol(id: number): Symbol | undefined;
|
||||
getOrCreateType(data: TypeResponse): TypeObject;
|
||||
getType(id: number): TypeObject | undefined;
|
||||
getOrCreateSignature(data: SignatureResponse): Signature;
|
||||
getSignature(id: number): Signature | undefined;
|
||||
clear(): void;
|
||||
fetchType<T extends Type>(source: Symbol | Signature | Type, method: string, handle: number | false | undefined): Promise<T>;
|
||||
fetchSymbol(source: Symbol | Signature | Type, method: string, handle: number | undefined): Promise<Symbol>;
|
||||
fetchSignature(source: Symbol | Signature | Type, method: string, handle: number | undefined): Promise<Signature>;
|
||||
fetchTypes(source: Symbol | Signature | Type, method: string, handles?: readonly number[]): Promise<readonly Type[]>;
|
||||
fetchSymbols(source: Symbol | Signature | Type, method: string, handles?: readonly number[]): Promise<readonly Symbol[]>;
|
||||
fetchBaseTypes(source: Type): Promise<readonly Type[]>;
|
||||
}
|
||||
export declare class Project {
|
||||
readonly id: Path;
|
||||
readonly configFileName: string;
|
||||
readonly compilerOptions: CompilerOptions;
|
||||
readonly rootFiles: readonly string[];
|
||||
readonly program: Program;
|
||||
readonly checker: Checker;
|
||||
readonly emitter: Emitter;
|
||||
private client;
|
||||
constructor(data: ProjectResponse, snapshotId: number, client: Client, sourceFileCache: SourceFileCache, toPath: (fileName: string) => Path, snapshotRegistry: SnapshotObjectRegistry);
|
||||
dispose(): void;
|
||||
}
|
||||
export declare class Program {
|
||||
private snapshotId;
|
||||
private project;
|
||||
private client;
|
||||
private sourceFileCache;
|
||||
private toPath;
|
||||
private decoder;
|
||||
private sourceFileMetadataCache;
|
||||
constructor(snapshotId: number, project: Project, client: Client, sourceFileCache: SourceFileCache, toPath: (fileName: string) => Path);
|
||||
getCompilerOptions(): CompilerOptions;
|
||||
getSourceFile(file: DocumentIdentifier): Promise<SourceFile | undefined>;
|
||||
getSourceFileNames(): Promise<readonly string[]>;
|
||||
/**
|
||||
* Returns program-stored metadata for the given source file, or `undefined` if the file
|
||||
* is not part of the program. Metadata is fetched lazily per file and cached on this
|
||||
* `Program` instance.
|
||||
*/
|
||||
getSourceFileMetadata(fileName: string): Promise<SourceFileMetadata | undefined>;
|
||||
/**
|
||||
* Returns program-stored metadata for the source file at the given path, or `undefined`
|
||||
* if the file is not part of the program. Like {@link getSourceFileMetadata}, but skips
|
||||
* the file name to path conversion. Metadata is fetched lazily per file and cached on
|
||||
* this `Program` instance.
|
||||
*/
|
||||
getSourceFileMetadataByPath(path: Path): Promise<SourceFileMetadata | undefined>;
|
||||
private fetchSourceFileMetadata;
|
||||
/**
|
||||
* Returns whether the given source file was loaded as part of an external library
|
||||
* (e.g. a dependency resolved from `node_modules`). The underlying program metadata is
|
||||
* fetched lazily per file and cached on this `Program` instance.
|
||||
*/
|
||||
isSourceFileFromExternalLibrary(file: SourceFile): Promise<boolean>;
|
||||
/**
|
||||
* Returns whether the given source file is a default library file (e.g. `lib.d.ts`).
|
||||
* The underlying program metadata is fetched lazily per file and cached on this
|
||||
* `Program` instance.
|
||||
*/
|
||||
isSourceFileDefaultLibrary(file: SourceFile): Promise<boolean>;
|
||||
/**
|
||||
* Get syntactic (parse) diagnostics for a specific file or all files.
|
||||
* @param file - Optional file to get diagnostics for. If omitted, returns diagnostics for all files.
|
||||
*/
|
||||
getSyntacticDiagnostics(file?: DocumentIdentifier): Promise<readonly Diagnostic[]>;
|
||||
/**
|
||||
* Get binder diagnostics for a specific file or all files.
|
||||
* @param file - Optional file to get diagnostics for. If omitted, returns diagnostics for all files.
|
||||
*/
|
||||
getBindDiagnostics(file?: DocumentIdentifier): Promise<readonly Diagnostic[]>;
|
||||
/**
|
||||
* Get semantic (type-check) diagnostics for a specific file or all files.
|
||||
* @param file - Optional file to get diagnostics for. If omitted, returns diagnostics for all files.
|
||||
*/
|
||||
getSemanticDiagnostics(file?: DocumentIdentifier): Promise<readonly Diagnostic[]>;
|
||||
/**
|
||||
* Get suggestion diagnostics for a specific file or all files.
|
||||
* @param file - Optional file to get diagnostics for. If omitted, returns diagnostics for all files.
|
||||
*/
|
||||
getSuggestionDiagnostics(file?: DocumentIdentifier): Promise<readonly Diagnostic[]>;
|
||||
/**
|
||||
* Get declaration emit diagnostics for a specific file or all files.
|
||||
* @param file - Optional file to get diagnostics for. If omitted, returns diagnostics for all files.
|
||||
*/
|
||||
getDeclarationDiagnostics(file?: DocumentIdentifier): Promise<readonly Diagnostic[]>;
|
||||
/**
|
||||
* Get program-wide diagnostics for the project, including compiler options diagnostics.
|
||||
*/
|
||||
getProgramDiagnostics(): Promise<readonly Diagnostic[]>;
|
||||
/**
|
||||
* Get global (non-file-specific) semantic diagnostics for the project.
|
||||
*/
|
||||
getGlobalDiagnostics(): Promise<readonly Diagnostic[]>;
|
||||
/**
|
||||
* Get config file parsing diagnostics for the project.
|
||||
*/
|
||||
getConfigFileParsingDiagnostics(): Promise<readonly Diagnostic[]>;
|
||||
}
|
||||
export declare class Checker {
|
||||
private snapshotId;
|
||||
private project;
|
||||
private client;
|
||||
private objectRegistry;
|
||||
private wellKnownSymbols;
|
||||
constructor(snapshotId: number, project: Project, client: Client, objectRegistry: ProjectObjectRegistry);
|
||||
dispose(): void;
|
||||
getSymbolAtLocation(node: Node): Promise<Symbol | undefined>;
|
||||
getSymbolAtLocation(nodes: readonly Node[]): Promise<(Symbol | undefined)[]>;
|
||||
getSymbolAtPosition(file: DocumentIdentifier, position: number): Promise<Symbol | undefined>;
|
||||
getSymbolAtPosition(file: DocumentIdentifier, positions: readonly number[]): Promise<(Symbol | undefined)[]>;
|
||||
getTypeOfSymbol(symbol: Symbol): Promise<Type | undefined>;
|
||||
getTypeOfSymbol(symbols: readonly Symbol[]): Promise<(Type | undefined)[]>;
|
||||
/**
|
||||
* Get the declared type of a symbol. Always returns a type; for symbols whose
|
||||
* declared type cannot be determined the checker yields the error type (use
|
||||
* {@link Type.isErrorType} to detect it).
|
||||
*/
|
||||
getDeclaredTypeOfSymbol(symbol: Symbol): Promise<Type>;
|
||||
getReferencesToSymbolInFile(file: DocumentIdentifier, symbol: Symbol): Promise<NodeHandle[]>;
|
||||
getReferencedSymbolsForNode(node: Node, position: number): Promise<ReferencedSymbolEntry[]>;
|
||||
getSignatureUsage(signatureDecl: Node): Promise<SignatureUsage[]>;
|
||||
getCompletionsAtPosition(document: string, position: number, options?: CompletionOptions): Promise<CompletionInfo | undefined>;
|
||||
getTypeAtLocation(node: Node): Promise<Type | undefined>;
|
||||
getTypeAtLocation(nodes: readonly Node[]): Promise<(Type | undefined)[]>;
|
||||
getSignaturesOfType(type: Type, kind: SignatureKind): Promise<readonly Signature[]>;
|
||||
getResolvedSignature(node: Node): Promise<Signature | undefined>;
|
||||
getTypeAtPosition(file: DocumentIdentifier, position: number): Promise<Type | undefined>;
|
||||
getTypeAtPosition(file: DocumentIdentifier, positions: readonly number[]): Promise<(Type | undefined)[]>;
|
||||
resolveName(name: string, meaning: SymbolFlags, location?: Node | DocumentPosition, excludeGlobals?: boolean): Promise<Symbol | undefined>;
|
||||
getResolvedSymbol(node: Identifier): Promise<Symbol | undefined>;
|
||||
getContextualType(node: Expression): Promise<Type | undefined>;
|
||||
getBaseTypeOfLiteralType(type: Type): Promise<Type | undefined>;
|
||||
getNonNullableType(type: Type): Promise<Type | undefined>;
|
||||
getTypeFromTypeNode(node: TypeNode): Promise<Type | undefined>;
|
||||
getWidenedType(type: Type): Promise<Type | undefined>;
|
||||
getParameterType(signature: Signature, index: number): Promise<Type | undefined>;
|
||||
isArrayLikeType(type: Type): Promise<boolean>;
|
||||
isTypeAssignableTo(source: Type, target: Type): Promise<boolean>;
|
||||
getShorthandAssignmentValueSymbol(node: Node): Promise<Symbol | undefined>;
|
||||
/**
|
||||
* Get the type of a symbol as narrowed at a specific location. Always returns
|
||||
* a type; for symbols whose type cannot be determined the checker yields the
|
||||
* error type (use {@link Type.isErrorType} to detect it).
|
||||
*/
|
||||
getTypeOfSymbolAtLocation(symbol: Symbol, location: Node): Promise<Type>;
|
||||
private getIntrinsicType;
|
||||
getAnyType(): Promise<Type>;
|
||||
getStringType(): Promise<Type>;
|
||||
getNumberType(): Promise<Type>;
|
||||
getBooleanType(): Promise<Type>;
|
||||
getVoidType(): Promise<Type>;
|
||||
getUndefinedType(): Promise<Type>;
|
||||
getNullType(): Promise<Type>;
|
||||
getNeverType(): Promise<Type>;
|
||||
getUnknownType(): Promise<Type>;
|
||||
getBigIntType(): Promise<Type>;
|
||||
getESSymbolType(): Promise<Type>;
|
||||
typeToTypeNode(type: Type, enclosingDeclaration?: Node, flags?: number): Promise<TypeNode | undefined>;
|
||||
signatureToSignatureDeclaration(signature: Signature, kind: SyntaxKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): Promise<Node | undefined>;
|
||||
typeToString(type: Type, enclosingDeclaration?: Node, flags?: number): Promise<string>;
|
||||
isContextSensitive(node: Node): Promise<boolean>;
|
||||
isArrayType(type: Type): Promise<boolean>;
|
||||
isTupleType(type: Type): Promise<boolean>;
|
||||
getReturnTypeOfSignature(signature: Signature): Promise<Type | undefined>;
|
||||
getRestTypeOfSignature(signature: Signature): Promise<Type | undefined>;
|
||||
getTypePredicateOfSignature(signature: Signature): Promise<TypePredicate | undefined>;
|
||||
/**
|
||||
* Get the base types of a class or interface type. A type with no base types
|
||||
* yields an empty array.
|
||||
*/
|
||||
getBaseTypes(type: InterfaceType): Promise<readonly Type[]>;
|
||||
getApparentType(type: Type): Promise<Type | undefined>;
|
||||
getPropertiesOfType(type: Type): Promise<readonly Symbol[]>;
|
||||
getIndexInfosOfType(type: Type): Promise<readonly IndexInfo[]>;
|
||||
/**
|
||||
* Get the constraint of a type parameter (the `T` in `<U extends T>`), or
|
||||
* undefined if it has none.
|
||||
*/
|
||||
getConstraintOfTypeParameter(type: TypeParameter): Promise<Type | undefined>;
|
||||
getBaseConstraintOfType(type: Type): Promise<Type | undefined>;
|
||||
getPropertyOfType(type: Type, name: string): Promise<Symbol | undefined>;
|
||||
getConstantValue(node: Node): Promise<string | number | undefined>;
|
||||
getSignatureFromDeclaration(node: Node): Promise<Signature | undefined>;
|
||||
getExportSpecifierLocalTargetSymbol(node: Node): Promise<Symbol | undefined>;
|
||||
/**
|
||||
* Follow all aliases to get the original symbol. Always returns a symbol; for
|
||||
* an unresolved alias the checker yields the unknown symbol (use
|
||||
* {@link Checker.isUnknownSymbol} to detect it).
|
||||
*/
|
||||
getAliasedSymbol(symbol: Symbol): Promise<Symbol>;
|
||||
getImmediateAliasedSymbol(symbol: Symbol): Promise<Symbol | undefined>;
|
||||
/**
|
||||
* Fetch (once, then cache) the handle ids of the per-checker singleton
|
||||
* symbols (unknown, undefined, arguments). These ids are stable for the life
|
||||
* of the project's checker, so identity checks against them are local after
|
||||
* the first call.
|
||||
*/
|
||||
private getWellKnownSymbols;
|
||||
/**
|
||||
* Returns `true` if the symbol is the checker's "unknown" symbol (e.g. the
|
||||
* result of {@link Checker.getAliasedSymbol} on an unresolved alias).
|
||||
*/
|
||||
isUnknownSymbol(symbol: Symbol): Promise<boolean>;
|
||||
/**
|
||||
* Returns `true` if the symbol is the checker's "undefined" symbol.
|
||||
*/
|
||||
isUndefinedSymbol(symbol: Symbol): Promise<boolean>;
|
||||
/**
|
||||
* Returns `true` if the symbol is the checker's "arguments" symbol.
|
||||
*/
|
||||
isArgumentsSymbol(symbol: Symbol): Promise<boolean>;
|
||||
getExportsOfModule(symbol: Symbol): Promise<readonly Symbol[]>;
|
||||
getMemberInModuleExports(symbol: Symbol, name: string): Promise<Symbol | undefined>;
|
||||
getJsDocTagsOfSymbol(symbol: Symbol): Promise<readonly JSDocTagInfo[]>;
|
||||
getDocumentationCommentOfSymbol(symbol: Symbol): Promise<string>;
|
||||
/**
|
||||
* Get the type arguments of a type reference (e.g. the `string` in `Array<string>`).
|
||||
*/
|
||||
getTypeArguments(type: TypeReference): Promise<readonly Type[]>;
|
||||
}
|
||||
export interface PrintNodeOptions {
|
||||
preserveSourceNewlines?: boolean | undefined;
|
||||
neverAsciiEscape?: boolean | undefined;
|
||||
terminateUnterminatedLiterals?: boolean | undefined;
|
||||
}
|
||||
export declare class Emitter {
|
||||
private client;
|
||||
constructor(client: Client);
|
||||
printNode(node: Node, options?: PrintNodeOptions): Promise<string>;
|
||||
}
|
||||
export declare class NodeHandle {
|
||||
/**
|
||||
* The project this handle was produced in, used as the default for {@link resolve}.
|
||||
* Node handles are only meaningful within a project's program, so the producing project
|
||||
* is remembered so callers don't have to pass it explicitly.
|
||||
*/
|
||||
private readonly canonicalProject;
|
||||
readonly index: number;
|
||||
readonly kind: SyntaxKind;
|
||||
readonly path: Path;
|
||||
constructor(handle: string, canonicalProject: Project);
|
||||
/**
|
||||
* Resolve this handle to the actual AST node by fetching the source file from a project
|
||||
* and looking up the node by index. If no project is passed, the project that produced
|
||||
* the handle is used.
|
||||
*/
|
||||
resolve(project?: Project): Promise<Node | undefined>;
|
||||
}
|
||||
/** A symbol definition paired with all of its reference nodes. */
|
||||
export interface ReferencedSymbolEntry {
|
||||
/** The node handle for the symbol's definition. */
|
||||
definition: NodeHandle;
|
||||
/** The resolved symbol for the definition, if available. */
|
||||
symbol?: Symbol | undefined;
|
||||
/** The node handles for each reference to the symbol. */
|
||||
references: NodeHandle[];
|
||||
}
|
||||
/** A single usage of a signature, pairing the reference name with its call expression (if any). */
|
||||
export interface SignatureUsage {
|
||||
/** The node handle for the name reference. */
|
||||
name: NodeHandle;
|
||||
/** The node handle for the call expression, if the reference is invoked. */
|
||||
call?: NodeHandle | undefined;
|
||||
}
|
||||
export declare class Symbol {
|
||||
private objectRegistry;
|
||||
/**
|
||||
* The project this symbol was first observed in, used as the default project for
|
||||
* lookups that need a project context (members/exports/parent). Symbols are shared
|
||||
* snapshot-wide, so these lookups can otherwise be ambiguous about which project to use.
|
||||
*/
|
||||
private readonly canonicalProject;
|
||||
readonly id: number;
|
||||
/** The escaped (`__String`) name, used as the key in member/export tables. */
|
||||
readonly escapedName: __String;
|
||||
/** The display name (escaped underscores removed). */
|
||||
readonly name: string;
|
||||
readonly flags: SymbolFlags;
|
||||
readonly checkFlags: number;
|
||||
readonly declarations: readonly NodeHandle[];
|
||||
readonly valueDeclaration: NodeHandle | undefined;
|
||||
private readonly parent;
|
||||
private readonly exportSymbol;
|
||||
private membersCache;
|
||||
private exportsCache;
|
||||
constructor(data: SymbolResponse, objectRegistry: SnapshotObjectRegistry);
|
||||
getParent(): Promise<Symbol | undefined>;
|
||||
/**
|
||||
* Get this symbol's members keyed by escaped name. The result is cached on
|
||||
* the symbol, so repeated calls do not round-trip to the server.
|
||||
*/
|
||||
getMembers(): Promise<ReadonlyMap<__String, Symbol>>;
|
||||
/**
|
||||
* Get this symbol's exports keyed by escaped name. The result is cached on
|
||||
* the symbol, so repeated calls do not round-trip to the server.
|
||||
*/
|
||||
getExports(): Promise<ReadonlyMap<__String, Symbol>>;
|
||||
private fetchSymbolTable;
|
||||
getExportSymbol(): Promise<Symbol>;
|
||||
getJsDocTags(checker: Checker): Promise<readonly JSDocTagInfo[]>;
|
||||
getDocumentationComment(checker: Checker): Promise<string>;
|
||||
}
|
||||
declare class TypeObject implements Type {
|
||||
private objectRegistry;
|
||||
readonly id: number;
|
||||
readonly flags: TypeFlags;
|
||||
readonly objectFlags: ObjectFlags;
|
||||
readonly symbol: number;
|
||||
readonly value: string | number | boolean | bigint;
|
||||
readonly intrinsicName: string;
|
||||
readonly isThisType: boolean;
|
||||
readonly freshType: number;
|
||||
readonly regularType: number;
|
||||
readonly target: number;
|
||||
readonly typeParameters: readonly number[];
|
||||
readonly outerTypeParameters: readonly number[];
|
||||
readonly localTypeParameters: readonly number[];
|
||||
readonly aliasTypeArguments: readonly number[];
|
||||
readonly aliasSymbol: number;
|
||||
readonly elementFlags: readonly ElementFlags[];
|
||||
readonly fixedLength: number;
|
||||
readonly readonly: boolean;
|
||||
readonly texts: readonly string[];
|
||||
readonly objectType: number;
|
||||
readonly indexType: number;
|
||||
readonly checkType: number;
|
||||
readonly extendsType: number;
|
||||
readonly baseType: number;
|
||||
readonly substConstraint: number;
|
||||
private trueType;
|
||||
private falseType;
|
||||
constructor(data: TypeResponse, objectRegistry: ProjectObjectRegistry);
|
||||
getSymbol(): Promise<Symbol | undefined>;
|
||||
getAliasSymbol(): Promise<Symbol | undefined>;
|
||||
getTarget(): Promise<Type>;
|
||||
getFreshType(): Promise<FreshableType | undefined>;
|
||||
getRegularType(): Promise<FreshableType | undefined>;
|
||||
getTypes(): Promise<readonly Type[] | undefined>;
|
||||
getTypeParameters(): Promise<readonly TypeParameter[]>;
|
||||
getOuterTypeParameters(): Promise<readonly TypeParameter[]>;
|
||||
getLocalTypeParameters(): Promise<readonly TypeParameter[]>;
|
||||
getAliasTypeArguments(): Promise<readonly Type[]>;
|
||||
getObjectType(): Promise<Type>;
|
||||
getIndexType(): Promise<Type>;
|
||||
getCheckType(): Promise<Type>;
|
||||
getExtendsType(): Promise<Type>;
|
||||
getBaseType(): Promise<Type>;
|
||||
getConstraint(): Promise<Type>;
|
||||
getTrueType(): Promise<Type>;
|
||||
getFalseType(): Promise<Type>;
|
||||
/**
|
||||
* Get the base types of this type. Returns `undefined` for any type that is
|
||||
* not a class or interface.
|
||||
*/
|
||||
getBaseTypes(): Promise<readonly Type[] | undefined>;
|
||||
isClassOrInterface(): this is InterfaceType;
|
||||
isUnionType(): this is UnionType;
|
||||
isIntersectionType(): this is IntersectionType;
|
||||
isObjectType(): this is ObjectType;
|
||||
isIntrinsicType(): this is IntrinsicType;
|
||||
isErrorType(): boolean;
|
||||
isLiteralType(): this is LiteralType;
|
||||
isStringLiteralType(): this is StringLiteralType;
|
||||
isNumberLiteralType(): this is NumberLiteralType;
|
||||
isBigIntLiteralType(): this is BigIntLiteralType;
|
||||
isBooleanLiteralType(): this is BooleanLiteralType;
|
||||
isTypeReference(): this is TypeReference;
|
||||
isTupleType(): this is TupleType;
|
||||
isIndexType(): this is IndexType;
|
||||
isIndexedAccessType(): this is IndexedAccessType;
|
||||
isConditionalType(): this is ConditionalType;
|
||||
isSubstitutionType(): this is SubstitutionType;
|
||||
isTemplateLiteralType(): this is TemplateLiteralType;
|
||||
isStringMappingType(): this is StringMappingType;
|
||||
isTypeParameter(): this is TypeParameter;
|
||||
}
|
||||
export declare function isUnionType(type: Type): type is UnionType;
|
||||
export declare function isIntersectionType(type: Type): type is IntersectionType;
|
||||
export declare function isObjectType(type: Type): type is ObjectType;
|
||||
export declare function isClassOrInterfaceType(type: Type): type is InterfaceType;
|
||||
export declare function isIntrinsicType(type: Type): type is IntrinsicType;
|
||||
/**
|
||||
* Whether this is the error type — the placeholder the checker produces when a
|
||||
* type cannot be determined (e.g. an unresolved reference). It is an intrinsic
|
||||
* type named `"error"` (this covers both the singleton error type and the
|
||||
* per-alias error types manufactured for unresolved type alias references).
|
||||
*/
|
||||
export declare function isErrorType(type: Type): boolean;
|
||||
export declare function isLiteralType(type: Type): type is LiteralType;
|
||||
export declare function isStringLiteralType(type: Type): type is StringLiteralType;
|
||||
export declare function isNumberLiteralType(type: Type): type is NumberLiteralType;
|
||||
export declare function isBigIntLiteralType(type: Type): type is BigIntLiteralType;
|
||||
export declare function isBooleanLiteralType(type: Type): type is BooleanLiteralType;
|
||||
export declare function isTypeReference(type: Type): type is TypeReference;
|
||||
export declare function isTupleType(type: Type): type is TupleType;
|
||||
export declare function isIndexType(type: Type): type is IndexType;
|
||||
export declare function isIndexedAccessType(type: Type): type is IndexedAccessType;
|
||||
export declare function isConditionalType(type: Type): type is ConditionalType;
|
||||
export declare function isSubstitutionType(type: Type): type is SubstitutionType;
|
||||
export declare function isTemplateLiteralType(type: Type): type is TemplateLiteralType;
|
||||
export declare function isStringMappingType(type: Type): type is StringMappingType;
|
||||
export declare function isTypeParameter(type: Type): type is TypeParameter;
|
||||
export declare class Signature {
|
||||
private flags;
|
||||
private objectRegistry;
|
||||
readonly id: number;
|
||||
readonly declaration?: NodeHandle | undefined;
|
||||
readonly typeParameters?: readonly number[] | undefined;
|
||||
readonly parameters: readonly number[];
|
||||
readonly thisParameter?: number | undefined;
|
||||
readonly target?: number | undefined;
|
||||
constructor(data: SignatureResponse, project: Project, objectRegistry: ProjectObjectRegistry);
|
||||
getTypeParameters(): Promise<readonly TypeParameter[]>;
|
||||
getParameters(): Promise<readonly Symbol[]>;
|
||||
getThisParameter(): Promise<Symbol | undefined>;
|
||||
getTarget(): Promise<Signature | undefined>;
|
||||
get hasRestParameter(): boolean;
|
||||
get isConstruct(): boolean;
|
||||
get isAbstract(): boolean;
|
||||
}
|
||||
//# sourceMappingURL=api.d.ts.map
|
||||
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* @fileoverview Rule to flag the use of empty character classes in regular expressions
|
||||
* @author Ian Christian Myers
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const { RegExpParser, visitRegExpAST } = require("@eslint-community/regexpp");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const parser = new RegExpParser();
|
||||
const QUICK_TEST_REGEX = /\[\]/u;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../types').Rule.RuleModule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "problem",
|
||||
|
||||
docs: {
|
||||
description:
|
||||
"Disallow empty character classes in regular expressions",
|
||||
recommended: true,
|
||||
url: "https://eslint.org/docs/latest/rules/no-empty-character-class",
|
||||
},
|
||||
|
||||
schema: [],
|
||||
|
||||
messages: {
|
||||
unexpected: "Empty class.",
|
||||
},
|
||||
},
|
||||
|
||||
create(context) {
|
||||
return {
|
||||
"Literal[regex]"(node) {
|
||||
const { pattern, flags } = node.regex;
|
||||
|
||||
if (!QUICK_TEST_REGEX.test(pattern)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let regExpAST;
|
||||
|
||||
try {
|
||||
regExpAST = parser.parsePattern(
|
||||
pattern,
|
||||
0,
|
||||
pattern.length,
|
||||
{
|
||||
unicode: flags.includes("u"),
|
||||
unicodeSets: flags.includes("v"),
|
||||
},
|
||||
);
|
||||
} catch {
|
||||
// Ignore regular expressions that regexpp cannot parse
|
||||
return;
|
||||
}
|
||||
|
||||
visitRegExpAST(regExpAST, {
|
||||
onCharacterClassEnter(characterClass) {
|
||||
if (
|
||||
!characterClass.negate &&
|
||||
characterClass.elements.length === 0
|
||||
) {
|
||||
context.report({ node, messageId: "unexpected" });
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014-2016, Jon Schlinkert
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"objectFlags.enum.js","sourceRoot":"","sources":["../../src/enums/objectFlags.enum.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAE/F,MAAM,CAAN,IAAY,WAgDX;AAhDD,WAAY,WAAW;IACnB,6CAAQ,CAAA;IACR,+CAAc,CAAA;IACd,uDAAkB,CAAA;IAClB,uDAAkB,CAAA;IAClB,+CAAc,CAAA;IACd,wDAAkB,CAAA;IAClB,kDAAe,CAAA;IACf,8DAAqB,CAAA;IACrB,iEAAsB,CAAA;IACtB,iEAAsB,CAAA;IACtB,2HAAmD,CAAA;IACnD,kEAAuB,CAAA;IACvB,kEAAuB,CAAA;IACvB,0DAAmB,CAAA;IACnB,gEAAsB,CAAA;IACtB,iEAAsB,CAAA;IACtB,qEAAwB,CAAA;IACxB,iFAA8B,CAAA;IAC9B,kGAAsC,CAAA;IACtC,4EAA2B,CAAA;IAC3B,4GAA2C,CAAA;IAC3C,6FAAmC,CAAA;IACnC,yEAAyB,CAAA;IACzB,qEAAoC,CAAA;IACpC,0EAAsE,CAAA;IACtE,0EAA0F,CAAA;IAC1F,0EAA0C,CAAA;IAC1C,kGAAqC,CAAA;IACrC,kFAA6B,CAAA;IAC7B,gFAAkK,CAAA;IAClK,uEAAwB,CAAA;IACxB,uEAAwB,CAAA;IACxB,oFAA8B,CAAA;IAC9B,mGAAqC,CAAA;IACrC,2FAAiC,CAAA;IACjC,+EAA2B,CAAA;IAC3B,sEAAsB,CAAA;IACtB,qFAA+B,CAAA;IAC/B,iFAA6B,CAAA;IAC7B,gFAA4B,CAAA;IAC5B,sEAAwD,CAAA;IACxD,sFAA+B,CAAA;IAC/B,gGAAoC,CAAA;IACpC,iFAA4B,CAAA;IAC5B,kGAAqC,CAAA;IACrC,kFAA6B,CAAA;IAC7B,+FAAmC,CAAA;AACvC,CAAC,EAhDW,WAAW,KAAX,WAAW,QAgDtB"}
|
||||
@@ -0,0 +1 @@
|
||||
export { _ as default } from "../esm/_object_spread.js";
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"name": "estraverse",
|
||||
"description": "ECMAScript JS AST traversal functions",
|
||||
"homepage": "https://github.com/estools/estraverse",
|
||||
"main": "estraverse.js",
|
||||
"version": "5.3.0",
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "Yusuke Suzuki",
|
||||
"email": "utatane.tea@gmail.com",
|
||||
"web": "http://github.com/Constellation"
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "http://github.com/estools/estraverse.git"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-preset-env": "^1.6.1",
|
||||
"babel-register": "^6.3.13",
|
||||
"chai": "^2.1.1",
|
||||
"espree": "^1.11.0",
|
||||
"gulp": "^3.8.10",
|
||||
"gulp-bump": "^0.2.2",
|
||||
"gulp-filter": "^2.0.0",
|
||||
"gulp-git": "^1.0.1",
|
||||
"gulp-tag-version": "^1.3.0",
|
||||
"jshint": "^2.5.6",
|
||||
"mocha": "^2.1.0"
|
||||
},
|
||||
"license": "BSD-2-Clause",
|
||||
"scripts": {
|
||||
"test": "npm run-script lint && npm run-script unit-test",
|
||||
"lint": "jshint estraverse.js",
|
||||
"unit-test": "mocha --compilers js:babel-register"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,380 @@
|
||||
const { InvalidArgumentError } = require('./error.js');
|
||||
|
||||
class Option {
|
||||
/**
|
||||
* Initialize a new `Option` with the given `flags` and `description`.
|
||||
*
|
||||
* @param {string} flags
|
||||
* @param {string} [description]
|
||||
*/
|
||||
|
||||
constructor(flags, description) {
|
||||
this.flags = flags;
|
||||
this.description = description || '';
|
||||
|
||||
this.required = flags.includes('<'); // A value must be supplied when the option is specified.
|
||||
this.optional = flags.includes('['); // A value is optional when the option is specified.
|
||||
// variadic test ignores <value,...> et al which might be used to describe custom splitting of single argument
|
||||
this.variadic = /\w\.\.\.[>\]]$/.test(flags); // The option can take multiple values.
|
||||
this.mandatory = false; // The option must have a value after parsing, which usually means it must be specified on command line.
|
||||
const optionFlags = splitOptionFlags(flags);
|
||||
this.short = optionFlags.shortFlag; // May be a short flag, undefined, or even a long flag (if option has two long flags).
|
||||
this.long = optionFlags.longFlag;
|
||||
this.negate = false;
|
||||
if (this.long) {
|
||||
this.negate = this.long.startsWith('--no-');
|
||||
}
|
||||
this.defaultValue = undefined;
|
||||
this.defaultValueDescription = undefined;
|
||||
this.presetArg = undefined;
|
||||
this.envVar = undefined;
|
||||
this.parseArg = undefined;
|
||||
this.hidden = false;
|
||||
this.argChoices = undefined;
|
||||
this.conflictsWith = [];
|
||||
this.implied = undefined;
|
||||
this.helpGroupHeading = undefined; // soft initialised when option added to command
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default value, and optionally supply the description to be displayed in the help.
|
||||
*
|
||||
* @param {*} value
|
||||
* @param {string} [description]
|
||||
* @return {Option}
|
||||
*/
|
||||
|
||||
default(value, description) {
|
||||
this.defaultValue = value;
|
||||
this.defaultValueDescription = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Preset to use when option used without option-argument, especially optional but also boolean and negated.
|
||||
* The custom processing (parseArg) is called.
|
||||
*
|
||||
* @example
|
||||
* new Option('--color').default('GREYSCALE').preset('RGB');
|
||||
* new Option('--donate [amount]').preset('20').argParser(parseFloat);
|
||||
*
|
||||
* @param {*} arg
|
||||
* @return {Option}
|
||||
*/
|
||||
|
||||
preset(arg) {
|
||||
this.presetArg = arg;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add option name(s) that conflict with this option.
|
||||
* An error will be displayed if conflicting options are found during parsing.
|
||||
*
|
||||
* @example
|
||||
* new Option('--rgb').conflicts('cmyk');
|
||||
* new Option('--js').conflicts(['ts', 'jsx']);
|
||||
*
|
||||
* @param {(string | string[])} names
|
||||
* @return {Option}
|
||||
*/
|
||||
|
||||
conflicts(names) {
|
||||
this.conflictsWith = this.conflictsWith.concat(names);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify implied option values for when this option is set and the implied options are not.
|
||||
*
|
||||
* The custom processing (parseArg) is not called on the implied values.
|
||||
*
|
||||
* @example
|
||||
* program
|
||||
* .addOption(new Option('--log', 'write logging information to file'))
|
||||
* .addOption(new Option('--trace', 'log extra details').implies({ log: 'trace.txt' }));
|
||||
*
|
||||
* @param {object} impliedOptionValues
|
||||
* @return {Option}
|
||||
*/
|
||||
implies(impliedOptionValues) {
|
||||
let newImplied = impliedOptionValues;
|
||||
if (typeof impliedOptionValues === 'string') {
|
||||
// string is not documented, but easy mistake and we can do what user probably intended.
|
||||
newImplied = { [impliedOptionValues]: true };
|
||||
}
|
||||
this.implied = Object.assign(this.implied || {}, newImplied);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set environment variable to check for option value.
|
||||
*
|
||||
* An environment variable is only used if when processed the current option value is
|
||||
* undefined, or the source of the current value is 'default' or 'config' or 'env'.
|
||||
*
|
||||
* @param {string} name
|
||||
* @return {Option}
|
||||
*/
|
||||
|
||||
env(name) {
|
||||
this.envVar = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the custom handler for processing CLI option arguments into option values.
|
||||
*
|
||||
* @param {Function} [fn]
|
||||
* @return {Option}
|
||||
*/
|
||||
|
||||
argParser(fn) {
|
||||
this.parseArg = fn;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the option is mandatory and must have a value after parsing.
|
||||
*
|
||||
* @param {boolean} [mandatory=true]
|
||||
* @return {Option}
|
||||
*/
|
||||
|
||||
makeOptionMandatory(mandatory = true) {
|
||||
this.mandatory = !!mandatory;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide option in help.
|
||||
*
|
||||
* @param {boolean} [hide=true]
|
||||
* @return {Option}
|
||||
*/
|
||||
|
||||
hideHelp(hide = true) {
|
||||
this.hidden = !!hide;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @package
|
||||
*/
|
||||
|
||||
_collectValue(value, previous) {
|
||||
if (previous === this.defaultValue || !Array.isArray(previous)) {
|
||||
return [value];
|
||||
}
|
||||
|
||||
previous.push(value);
|
||||
return previous;
|
||||
}
|
||||
|
||||
/**
|
||||
* Only allow option value to be one of choices.
|
||||
*
|
||||
* @param {string[]} values
|
||||
* @return {Option}
|
||||
*/
|
||||
|
||||
choices(values) {
|
||||
this.argChoices = values.slice();
|
||||
this.parseArg = (arg, previous) => {
|
||||
if (!this.argChoices.includes(arg)) {
|
||||
throw new InvalidArgumentError(
|
||||
`Allowed choices are ${this.argChoices.join(', ')}.`,
|
||||
);
|
||||
}
|
||||
if (this.variadic) {
|
||||
return this._collectValue(arg, previous);
|
||||
}
|
||||
return arg;
|
||||
};
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return option name.
|
||||
*
|
||||
* @return {string}
|
||||
*/
|
||||
|
||||
name() {
|
||||
if (this.long) {
|
||||
return this.long.replace(/^--/, '');
|
||||
}
|
||||
return this.short.replace(/^-/, '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return option name, in a camelcase format that can be used
|
||||
* as an object attribute key.
|
||||
*
|
||||
* @return {string}
|
||||
*/
|
||||
|
||||
attributeName() {
|
||||
if (this.negate) {
|
||||
return camelcase(this.name().replace(/^no-/, ''));
|
||||
}
|
||||
return camelcase(this.name());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the help group heading.
|
||||
*
|
||||
* @param {string} heading
|
||||
* @return {Option}
|
||||
*/
|
||||
helpGroup(heading) {
|
||||
this.helpGroupHeading = heading;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if `arg` matches the short or long flag.
|
||||
*
|
||||
* @param {string} arg
|
||||
* @return {boolean}
|
||||
* @package
|
||||
*/
|
||||
|
||||
is(arg) {
|
||||
return this.short === arg || this.long === arg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether a boolean option.
|
||||
*
|
||||
* Options are one of boolean, negated, required argument, or optional argument.
|
||||
*
|
||||
* @return {boolean}
|
||||
* @package
|
||||
*/
|
||||
|
||||
isBoolean() {
|
||||
return !this.required && !this.optional && !this.negate;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class is to make it easier to work with dual options, without changing the existing
|
||||
* implementation. We support separate dual options for separate positive and negative options,
|
||||
* like `--build` and `--no-build`, which share a single option value. This works nicely for some
|
||||
* use cases, but is tricky for others where we want separate behaviours despite
|
||||
* the single shared option value.
|
||||
*/
|
||||
class DualOptions {
|
||||
/**
|
||||
* @param {Option[]} options
|
||||
*/
|
||||
constructor(options) {
|
||||
this.positiveOptions = new Map();
|
||||
this.negativeOptions = new Map();
|
||||
this.dualOptions = new Set();
|
||||
options.forEach((option) => {
|
||||
if (option.negate) {
|
||||
this.negativeOptions.set(option.attributeName(), option);
|
||||
} else {
|
||||
this.positiveOptions.set(option.attributeName(), option);
|
||||
}
|
||||
});
|
||||
this.negativeOptions.forEach((value, key) => {
|
||||
if (this.positiveOptions.has(key)) {
|
||||
this.dualOptions.add(key);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Did the value come from the option, and not from possible matching dual option?
|
||||
*
|
||||
* @param {*} value
|
||||
* @param {Option} option
|
||||
* @returns {boolean}
|
||||
*/
|
||||
valueFromOption(value, option) {
|
||||
const optionKey = option.attributeName();
|
||||
if (!this.dualOptions.has(optionKey)) return true;
|
||||
|
||||
// Use the value to deduce if (probably) came from the option.
|
||||
const preset = this.negativeOptions.get(optionKey).presetArg;
|
||||
const negativeValue = preset !== undefined ? preset : false;
|
||||
return option.negate === (negativeValue === value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert string from kebab-case to camelCase.
|
||||
*
|
||||
* @param {string} str
|
||||
* @return {string}
|
||||
* @private
|
||||
*/
|
||||
|
||||
function camelcase(str) {
|
||||
return str.split('-').reduce((str, word) => {
|
||||
return str + word[0].toUpperCase() + word.slice(1);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Split the short and long flag out of something like '-m,--mixed <value>'
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
|
||||
function splitOptionFlags(flags) {
|
||||
let shortFlag;
|
||||
let longFlag;
|
||||
// short flag, single dash and single character
|
||||
const shortFlagExp = /^-[^-]$/;
|
||||
// long flag, double dash and at least one character
|
||||
const longFlagExp = /^--[^-]/;
|
||||
|
||||
const flagParts = flags.split(/[ |,]+/).concat('guard');
|
||||
// Normal is short and/or long.
|
||||
if (shortFlagExp.test(flagParts[0])) shortFlag = flagParts.shift();
|
||||
if (longFlagExp.test(flagParts[0])) longFlag = flagParts.shift();
|
||||
// Long then short. Rarely used but fine.
|
||||
if (!shortFlag && shortFlagExp.test(flagParts[0]))
|
||||
shortFlag = flagParts.shift();
|
||||
// Allow two long flags, like '--ws, --workspace'
|
||||
// This is the supported way to have a shortish option flag.
|
||||
if (!shortFlag && longFlagExp.test(flagParts[0])) {
|
||||
shortFlag = longFlag;
|
||||
longFlag = flagParts.shift();
|
||||
}
|
||||
|
||||
// Check for unprocessed flag. Fail noisily rather than silently ignore.
|
||||
if (flagParts[0].startsWith('-')) {
|
||||
const unsupportedFlag = flagParts[0];
|
||||
const baseError = `option creation failed due to '${unsupportedFlag}' in option flags '${flags}'`;
|
||||
if (/^-[^-][^-]/.test(unsupportedFlag))
|
||||
throw new Error(
|
||||
`${baseError}
|
||||
- a short flag is a single dash and a single character
|
||||
- either use a single dash and a single character (for a short flag)
|
||||
- or use a double dash for a long option (and can have two, like '--ws, --workspace')`,
|
||||
);
|
||||
if (shortFlagExp.test(unsupportedFlag))
|
||||
throw new Error(`${baseError}
|
||||
- too many short flags`);
|
||||
if (longFlagExp.test(unsupportedFlag))
|
||||
throw new Error(`${baseError}
|
||||
- too many long flags`);
|
||||
|
||||
throw new Error(`${baseError}
|
||||
- unrecognised flag format`);
|
||||
}
|
||||
if (shortFlag === undefined && longFlag === undefined)
|
||||
throw new Error(
|
||||
`option creation failed due to no flags found in '${flags}'.`,
|
||||
);
|
||||
|
||||
return { shortFlag, longFlag };
|
||||
}
|
||||
|
||||
exports.Option = Option;
|
||||
exports.DualOptions = DualOptions;
|
||||
@@ -0,0 +1,221 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.TypeVisitor = void 0;
|
||||
const types_1 = require("@typescript-eslint/types");
|
||||
const definition_1 = require("../definition");
|
||||
const scope_1 = require("../scope");
|
||||
const Visitor_1 = require("./Visitor");
|
||||
class TypeVisitor extends Visitor_1.Visitor {
|
||||
#referencer;
|
||||
constructor(referencer) {
|
||||
super(referencer);
|
||||
this.#referencer = referencer;
|
||||
}
|
||||
static visit(referencer, node) {
|
||||
const typeReferencer = new TypeVisitor(referencer);
|
||||
typeReferencer.visit(node);
|
||||
}
|
||||
///////////////////
|
||||
// Visit helpers //
|
||||
///////////////////
|
||||
visitFunctionType(node) {
|
||||
// arguments and type parameters can only be referenced from within the function
|
||||
this.#referencer.scopeManager.nestFunctionTypeScope(node);
|
||||
this.visit(node.typeParameters);
|
||||
for (const param of node.params) {
|
||||
let didVisitAnnotation = false;
|
||||
this.visitPattern(param, (pattern, info) => {
|
||||
// a parameter name creates a value type variable which can be referenced later via typeof arg
|
||||
this.#referencer
|
||||
.currentScope()
|
||||
.defineIdentifier(pattern, new definition_1.ParameterDefinition(pattern, node, info.rest));
|
||||
if (pattern.typeAnnotation) {
|
||||
this.visit(pattern.typeAnnotation);
|
||||
didVisitAnnotation = true;
|
||||
}
|
||||
});
|
||||
// there are a few special cases where the type annotation is owned by the parameter, not the pattern
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
if (!didVisitAnnotation && 'typeAnnotation' in param) {
|
||||
this.visit(param.typeAnnotation);
|
||||
}
|
||||
}
|
||||
this.visit(node.returnType);
|
||||
this.#referencer.close(node);
|
||||
}
|
||||
visitPropertyKey(node) {
|
||||
if (!node.computed) {
|
||||
return;
|
||||
}
|
||||
// computed members are treated as value references, and TS expects they have a literal type
|
||||
this.#referencer.visit(node.key);
|
||||
}
|
||||
/////////////////////
|
||||
// Visit selectors //
|
||||
/////////////////////
|
||||
Identifier(node) {
|
||||
this.#referencer.currentScope().referenceType(node);
|
||||
}
|
||||
MemberExpression(node) {
|
||||
this.visit(node.object);
|
||||
// don't visit the property
|
||||
}
|
||||
TSCallSignatureDeclaration(node) {
|
||||
this.visitFunctionType(node);
|
||||
}
|
||||
TSConditionalType(node) {
|
||||
// conditional types can define inferred type parameters
|
||||
// which are only accessible from inside the conditional parameter
|
||||
this.#referencer.scopeManager.nestConditionalTypeScope(node);
|
||||
// type parameters inferred in the condition clause are not accessible within the false branch
|
||||
this.visitChildren(node, ['falseType']);
|
||||
this.#referencer.close(node);
|
||||
this.visit(node.falseType);
|
||||
}
|
||||
TSConstructorType(node) {
|
||||
this.visitFunctionType(node);
|
||||
}
|
||||
TSConstructSignatureDeclaration(node) {
|
||||
this.visitFunctionType(node);
|
||||
}
|
||||
TSFunctionType(node) {
|
||||
this.visitFunctionType(node);
|
||||
}
|
||||
TSImportType(node) {
|
||||
// the TS parser allows any type to be the parameter, but it's a syntax error - so we can ignore it
|
||||
this.visit(node.typeArguments);
|
||||
// the qualifier is just part of a standard EntityName, so it should not be visited
|
||||
}
|
||||
TSIndexSignature(node) {
|
||||
for (const param of node.parameters) {
|
||||
if (param.type === types_1.AST_NODE_TYPES.Identifier) {
|
||||
this.visit(param.typeAnnotation);
|
||||
}
|
||||
}
|
||||
this.visit(node.typeAnnotation);
|
||||
}
|
||||
TSInferType(node) {
|
||||
const typeParameter = node.typeParameter;
|
||||
let scope = this.#referencer.currentScope();
|
||||
/*
|
||||
In cases where there is a sub-type scope created within a conditional type, then the generic should be defined in the
|
||||
conditional type's scope, not the child type scope.
|
||||
If we define it within the child type's scope then it won't be able to be referenced outside the child type
|
||||
*/
|
||||
if (scope.type === scope_1.ScopeType.functionType ||
|
||||
scope.type === scope_1.ScopeType.mappedType) {
|
||||
// search up the scope tree to figure out if we're in a nested type scope
|
||||
let currentScope = scope.upper;
|
||||
while (currentScope) {
|
||||
if (currentScope.type === scope_1.ScopeType.functionType ||
|
||||
currentScope.type === scope_1.ScopeType.mappedType) {
|
||||
// ensure valid type parents only
|
||||
currentScope = currentScope.upper;
|
||||
continue;
|
||||
}
|
||||
if (currentScope.type === scope_1.ScopeType.conditionalType) {
|
||||
scope = currentScope;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
scope.defineIdentifier(typeParameter.name, new definition_1.TypeDefinition(typeParameter.name, typeParameter));
|
||||
this.visit(typeParameter.constraint);
|
||||
}
|
||||
TSInterfaceDeclaration(node) {
|
||||
this.#referencer
|
||||
.currentScope()
|
||||
.defineIdentifier(node.id, new definition_1.TypeDefinition(node.id, node));
|
||||
if (node.typeParameters) {
|
||||
// type parameters cannot be referenced from outside their current scope
|
||||
this.#referencer.scopeManager.nestTypeScope(node);
|
||||
this.visit(node.typeParameters);
|
||||
}
|
||||
node.extends.forEach(this.visit, this);
|
||||
this.visit(node.body);
|
||||
if (node.typeParameters) {
|
||||
this.#referencer.close(node);
|
||||
}
|
||||
}
|
||||
TSMappedType(node) {
|
||||
// mapped types key can only be referenced within their return value
|
||||
this.#referencer.scopeManager.nestMappedTypeScope(node);
|
||||
this.#referencer
|
||||
.currentScope()
|
||||
.defineIdentifier(node.key, new definition_1.TypeDefinition(node.key, node));
|
||||
this.visit(node.constraint);
|
||||
this.visit(node.nameType);
|
||||
this.visit(node.typeAnnotation);
|
||||
this.#referencer.close(node);
|
||||
}
|
||||
TSMethodSignature(node) {
|
||||
this.visitPropertyKey(node);
|
||||
this.visitFunctionType(node);
|
||||
}
|
||||
TSNamedTupleMember(node) {
|
||||
this.visit(node.elementType);
|
||||
// we don't visit the label as the label only exists for the purposes of documentation
|
||||
}
|
||||
TSPropertySignature(node) {
|
||||
this.visitPropertyKey(node);
|
||||
this.visit(node.typeAnnotation);
|
||||
}
|
||||
TSQualifiedName(node) {
|
||||
this.visit(node.left);
|
||||
// we don't visit the right as it a name on the thing, not a name to reference
|
||||
}
|
||||
TSTypeAliasDeclaration(node) {
|
||||
this.#referencer
|
||||
.currentScope()
|
||||
.defineIdentifier(node.id, new definition_1.TypeDefinition(node.id, node));
|
||||
if (node.typeParameters) {
|
||||
// type parameters cannot be referenced from outside their current scope
|
||||
this.#referencer.scopeManager.nestTypeScope(node);
|
||||
this.visit(node.typeParameters);
|
||||
}
|
||||
this.visit(node.typeAnnotation);
|
||||
if (node.typeParameters) {
|
||||
this.#referencer.close(node);
|
||||
}
|
||||
}
|
||||
TSTypeParameter(node) {
|
||||
this.#referencer
|
||||
.currentScope()
|
||||
.defineIdentifier(node.name, new definition_1.TypeDefinition(node.name, node));
|
||||
this.visit(node.constraint);
|
||||
this.visit(node.default);
|
||||
}
|
||||
TSTypePredicate(node) {
|
||||
if (node.parameterName.type !== types_1.AST_NODE_TYPES.TSThisType) {
|
||||
this.#referencer.currentScope().referenceValue(node.parameterName);
|
||||
}
|
||||
this.visit(node.typeAnnotation);
|
||||
}
|
||||
// a type query `typeof foo` is a special case that references a _non-type_ variable,
|
||||
TSTypeAnnotation(node) {
|
||||
// check
|
||||
this.visitChildren(node);
|
||||
}
|
||||
TSTypeQuery(node) {
|
||||
let entityName;
|
||||
if (node.exprName.type === types_1.AST_NODE_TYPES.TSQualifiedName) {
|
||||
let iter = node.exprName;
|
||||
while (iter.left.type === types_1.AST_NODE_TYPES.TSQualifiedName) {
|
||||
iter = iter.left;
|
||||
}
|
||||
entityName = iter.left;
|
||||
}
|
||||
else {
|
||||
entityName = node.exprName;
|
||||
if (node.exprName.type === types_1.AST_NODE_TYPES.TSImportType) {
|
||||
this.visit(node.exprName);
|
||||
}
|
||||
}
|
||||
if (entityName.type === types_1.AST_NODE_TYPES.Identifier) {
|
||||
this.#referencer.currentScope().referenceValue(entityName);
|
||||
}
|
||||
this.visit(node.typeArguments);
|
||||
}
|
||||
}
|
||||
exports.TypeVisitor = TypeVisitor;
|
||||
@@ -0,0 +1,2 @@
|
||||
import type { LibDefinition } from '../variable';
|
||||
export declare const es2021_full: LibDefinition;
|
||||
@@ -0,0 +1,74 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
test("basic prefault", () => {
|
||||
const a = z.prefault(z.string().trim(), " default ");
|
||||
expect(a).toBeInstanceOf(z.ZodPrefault);
|
||||
expect(a.parse(" asdf ")).toEqual("asdf");
|
||||
expect(a.parse(undefined)).toEqual("default");
|
||||
|
||||
type inp = z.input<typeof a>;
|
||||
expectTypeOf<inp>().toEqualTypeOf<string | undefined>();
|
||||
type out = z.output<typeof a>;
|
||||
expectTypeOf<out>().toEqualTypeOf<string>();
|
||||
});
|
||||
|
||||
test("prefault inside object", () => {
|
||||
// test optinality
|
||||
const a = z.object({
|
||||
name: z.string().optional(),
|
||||
age: z.number().default(1234),
|
||||
email: z.string().prefault("1234"),
|
||||
});
|
||||
|
||||
type inp = z.input<typeof a>;
|
||||
expectTypeOf<inp>().toEqualTypeOf<{
|
||||
name?: string | undefined;
|
||||
age?: number | undefined;
|
||||
email?: string | undefined;
|
||||
}>();
|
||||
|
||||
type out = z.output<typeof a>;
|
||||
expectTypeOf<out>().toEqualTypeOf<{
|
||||
name?: string | undefined;
|
||||
age: number;
|
||||
email: string;
|
||||
}>();
|
||||
});
|
||||
|
||||
test("object schema with prefault should return shallow clone", () => {
|
||||
const schema = z
|
||||
.object({
|
||||
a: z.string(),
|
||||
})
|
||||
.prefault({ a: "x" });
|
||||
const result1 = schema.parse(undefined);
|
||||
const result2 = schema.parse(undefined);
|
||||
expect(result1).not.toBe(result2);
|
||||
expect(result1).toEqual(result2);
|
||||
});
|
||||
|
||||
test("direction-aware prefault", () => {
|
||||
const schema = z.string().prefault("hello");
|
||||
|
||||
// Forward direction (regular parse): prefault should be applied
|
||||
expect(schema.parse(undefined)).toBe("hello");
|
||||
|
||||
// Reverse direction (encode): prefault should NOT be applied, undefined should fail validation
|
||||
expect(z.safeEncode(schema, undefined as any)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
|
||||
// But valid values should still work in reverse
|
||||
expect(z.encode(schema, "world")).toBe("world");
|
||||
});
|
||||
@@ -0,0 +1,137 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getParsedType = exports.ZodParsedType = exports.objectUtil = exports.util = void 0;
|
||||
var util;
|
||||
(function (util) {
|
||||
util.assertEqual = (_) => { };
|
||||
function assertIs(_arg) { }
|
||||
util.assertIs = assertIs;
|
||||
function assertNever(_x) {
|
||||
throw new Error();
|
||||
}
|
||||
util.assertNever = assertNever;
|
||||
util.arrayToEnum = (items) => {
|
||||
const obj = {};
|
||||
for (const item of items) {
|
||||
obj[item] = item;
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
util.getValidEnumValues = (obj) => {
|
||||
const validKeys = util.objectKeys(obj).filter((k) => typeof obj[obj[k]] !== "number");
|
||||
const filtered = {};
|
||||
for (const k of validKeys) {
|
||||
filtered[k] = obj[k];
|
||||
}
|
||||
return util.objectValues(filtered);
|
||||
};
|
||||
util.objectValues = (obj) => {
|
||||
return util.objectKeys(obj).map(function (e) {
|
||||
return obj[e];
|
||||
});
|
||||
};
|
||||
util.objectKeys = typeof Object.keys === "function" // eslint-disable-line ban/ban
|
||||
? (obj) => Object.keys(obj) // eslint-disable-line ban/ban
|
||||
: (object) => {
|
||||
const keys = [];
|
||||
for (const key in object) {
|
||||
if (Object.prototype.hasOwnProperty.call(object, key)) {
|
||||
keys.push(key);
|
||||
}
|
||||
}
|
||||
return keys;
|
||||
};
|
||||
util.find = (arr, checker) => {
|
||||
for (const item of arr) {
|
||||
if (checker(item))
|
||||
return item;
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
util.isInteger = typeof Number.isInteger === "function"
|
||||
? (val) => Number.isInteger(val) // eslint-disable-line ban/ban
|
||||
: (val) => typeof val === "number" && Number.isFinite(val) && Math.floor(val) === val;
|
||||
function joinValues(array, separator = " | ") {
|
||||
return array.map((val) => (typeof val === "string" ? `'${val}'` : val)).join(separator);
|
||||
}
|
||||
util.joinValues = joinValues;
|
||||
util.jsonStringifyReplacer = (_, value) => {
|
||||
if (typeof value === "bigint") {
|
||||
return value.toString();
|
||||
}
|
||||
return value;
|
||||
};
|
||||
})(util || (exports.util = util = {}));
|
||||
var objectUtil;
|
||||
(function (objectUtil) {
|
||||
objectUtil.mergeShapes = (first, second) => {
|
||||
return {
|
||||
...first,
|
||||
...second, // second overwrites first
|
||||
};
|
||||
};
|
||||
})(objectUtil || (exports.objectUtil = objectUtil = {}));
|
||||
exports.ZodParsedType = util.arrayToEnum([
|
||||
"string",
|
||||
"nan",
|
||||
"number",
|
||||
"integer",
|
||||
"float",
|
||||
"boolean",
|
||||
"date",
|
||||
"bigint",
|
||||
"symbol",
|
||||
"function",
|
||||
"undefined",
|
||||
"null",
|
||||
"array",
|
||||
"object",
|
||||
"unknown",
|
||||
"promise",
|
||||
"void",
|
||||
"never",
|
||||
"map",
|
||||
"set",
|
||||
]);
|
||||
const getParsedType = (data) => {
|
||||
const t = typeof data;
|
||||
switch (t) {
|
||||
case "undefined":
|
||||
return exports.ZodParsedType.undefined;
|
||||
case "string":
|
||||
return exports.ZodParsedType.string;
|
||||
case "number":
|
||||
return Number.isNaN(data) ? exports.ZodParsedType.nan : exports.ZodParsedType.number;
|
||||
case "boolean":
|
||||
return exports.ZodParsedType.boolean;
|
||||
case "function":
|
||||
return exports.ZodParsedType.function;
|
||||
case "bigint":
|
||||
return exports.ZodParsedType.bigint;
|
||||
case "symbol":
|
||||
return exports.ZodParsedType.symbol;
|
||||
case "object":
|
||||
if (Array.isArray(data)) {
|
||||
return exports.ZodParsedType.array;
|
||||
}
|
||||
if (data === null) {
|
||||
return exports.ZodParsedType.null;
|
||||
}
|
||||
if (data.then && typeof data.then === "function" && data.catch && typeof data.catch === "function") {
|
||||
return exports.ZodParsedType.promise;
|
||||
}
|
||||
if (typeof Map !== "undefined" && data instanceof Map) {
|
||||
return exports.ZodParsedType.map;
|
||||
}
|
||||
if (typeof Set !== "undefined" && data instanceof Set) {
|
||||
return exports.ZodParsedType.set;
|
||||
}
|
||||
if (typeof Date !== "undefined" && data instanceof Date) {
|
||||
return exports.ZodParsedType.date;
|
||||
}
|
||||
return exports.ZodParsedType.object;
|
||||
default:
|
||||
return exports.ZodParsedType.unknown;
|
||||
}
|
||||
};
|
||||
exports.getParsedType = getParsedType;
|
||||
Reference in New Issue
Block a user