Skip to content

Commit

Permalink
Provide plugin/preset typings from plugin-utils (#14499)
Browse files Browse the repository at this point in the history
Co-authored-by: Nicolò Ribaudo <nicolo.ribaudo@gmail.com>
  • Loading branch information
JLHwung and nicolo-ribaudo committed Apr 29, 2022
1 parent 51c8c02 commit c90add7
Show file tree
Hide file tree
Showing 99 changed files with 742 additions and 294 deletions.
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -74,7 +74,7 @@
"semver": "^6.3.0",
"test262-stream": "^1.4.0",
"through2": "^4.0.0",
"typescript": "~4.5.0"
"typescript": "~4.6.3"
},
"workspaces": [
"codemods/*",
Expand Down
4 changes: 2 additions & 2 deletions packages/babel-core/src/config/helpers/config-api.ts
Expand Up @@ -9,7 +9,7 @@ import type {
SimpleType,
} from "../caching";

import type { CallerMetadata } from "../validation/options";
import type { AssumptionName, CallerMetadata } from "../validation/options";

import * as Context from "../cache-contexts";

Expand All @@ -24,7 +24,7 @@ type CallerFactory = (
extractor: (callerMetadata: CallerMetadata | void) => unknown,
) => SimpleType;
type TargetsFunction = () => Targets;
type AssumptionFunction = (name: string) => boolean | void;
type AssumptionFunction = (name: AssumptionName) => boolean | void;

export type ConfigAPI = {
version: string;
Expand Down
11 changes: 11 additions & 0 deletions packages/babel-core/src/config/index.ts
Expand Up @@ -9,6 +9,17 @@ export type {

import type { PluginTarget } from "./validation/options";

import type {
PluginAPI as basePluginAPI,
PresetAPI as basePresetAPI,
} from "./helpers/config-api";
export type { PluginObject } from "./validation/plugins";
type PluginAPI = basePluginAPI & typeof import("..");
type PresetAPI = basePresetAPI & typeof import("..");
export type { PluginAPI, PresetAPI };
// todo: may need to refine PresetObject to be a subset of ValidatedOptions
export type { ValidatedOptions as PresetObject } from "./validation/options";

import loadFullConfig from "./full";
import { loadPartialConfig as loadPartialConfigRunner } from "./partial";

Expand Down
Expand Up @@ -20,6 +20,7 @@ import type {
CallerMetadata,
RootMode,
TargetsListOrObject,
AssumptionName,
} from "./options";

import { assumptionsNames } from "./options";
Expand Down Expand Up @@ -462,7 +463,7 @@ export function assertAssumptions(

for (const name of Object.keys(value)) {
const subLoc = access(loc, name);
if (!assumptionsNames.has(name)) {
if (!assumptionsNames.has(name as AssumptionName)) {
throw new Error(`${msg(subLoc)} is not a supported assumption.`);
}
if (typeof value[name] !== "boolean") {
Expand Down
12 changes: 8 additions & 4 deletions packages/babel-core/src/config/validation/options.ts
Expand Up @@ -28,6 +28,8 @@ import {
} from "./option-assertions";
import type { ValidatorSet, Validator, OptionPath } from "./option-assertions";
import type { UnloadedDescriptor } from "../config-descriptors";
import type { ParserOptions } from "@babel/parser";
import type { GeneratorOptions } from "@babel/generator";

const ROOT_VALIDATORS: ValidatorSet = {
cwd: assertString as Validator<ValidatedOptions["cwd"]>,
Expand Down Expand Up @@ -181,9 +183,9 @@ export type ValidatedOptions = {
sourceFileName?: string;
sourceRoot?: string;
// Deprecate top level parserOpts
parserOpts?: {};
parserOpts?: ParserOptions;
// Deprecate top level generatorOpts
generatorOpts?: {};
generatorOpts?: GeneratorOptions;
};

export type NormalizedOptions = {
Expand Down Expand Up @@ -254,7 +256,7 @@ type EnvPath = Readonly<{

export type NestingPath = RootPath | OverridesPath | EnvPath;

export const assumptionsNames = new Set<string>([
const knownAssumptions = [
"arrayLikeIsIterable",
"constantReexports",
"constantSuper",
Expand All @@ -276,7 +278,9 @@ export const assumptionsNames = new Set<string>([
"setSpreadProperties",
"skipForOfIteratorClosing",
"superIsCallableConstructor",
]);
] as const;
export type AssumptionName = typeof knownAssumptions[number];
export const assumptionsNames = new Set(knownAssumptions);

function getSource(loc: NestingPath): OptionsSource {
return loc.type === "root" ? loc.source : getSource(loc.parent);
Expand Down
21 changes: 12 additions & 9 deletions packages/babel-core/src/config/validation/plugins.ts
Expand Up @@ -11,6 +11,10 @@ import type {
OptionPath,
RootPath,
} from "./option-assertions";
import type { ParserOptions } from "@babel/parser";
import type { Visitor } from "@babel/traverse";
import type PluginPass from "../../transformation/plugin-pass";
import type { ValidatedOptions } from "./options";

// Note: The casts here are just meant to be static assertions to make sure
// that the assertion functions actually assert that the value's type matches
Expand All @@ -31,7 +35,7 @@ const VALIDATORS: ValidatorSet = {
>,
};

function assertVisitorMap(loc: OptionPath, value: unknown): VisitorMap {
function assertVisitorMap(loc: OptionPath, value: unknown): Visitor {
const obj = assertObject(loc, value);
if (obj) {
Object.keys(obj).forEach(prop => assertVisitorHandler(prop, obj[prop]));
Expand All @@ -45,7 +49,7 @@ function assertVisitorMap(loc: OptionPath, value: unknown): VisitorMap {
);
}
}
return obj as VisitorMap;
return obj as Visitor;
}

function assertVisitorHandler(
Expand Down Expand Up @@ -74,17 +78,16 @@ type VisitorHandler =
exit?: Function;
};

export type VisitorMap = {
[x: string]: VisitorHandler;
};

export type PluginObject = {
export type PluginObject<S = PluginPass> = {
name?: string;
manipulateOptions?: (options: unknown, parserOpts: unknown) => void;
manipulateOptions?: (
options: ValidatedOptions,
parserOpts: ParserOptions,
) => void;
pre?: Function;
post?: Function;
inherits?: Function;
visitor?: VisitorMap;
visitor?: Visitor<S>;
parserOverride?: Function;
generatorOverride?: Function;
};
Expand Down
7 changes: 7 additions & 0 deletions packages/babel-core/src/index.ts
Expand Up @@ -29,6 +29,13 @@ export {
loadOptionsAsync,
} from "./config";

export type {
PluginAPI,
PluginObject,
PresetAPI,
PresetObject,
} from "./config";

export { transform, transformSync, transformAsync } from "./transform";
export {
transformFile,
Expand Down
1 change: 0 additions & 1 deletion packages/babel-generator/src/generators/methods.ts
Expand Up @@ -146,7 +146,6 @@ function hasTypesOrComments(
return !!(
node.typeParameters ||
node.returnType ||
// @ts-expect-error
node.predicate ||
param.typeAnnotation ||
param.optional ||
Expand Down
19 changes: 6 additions & 13 deletions packages/babel-generator/src/index.ts
@@ -1,7 +1,7 @@
import SourceMap from "./source-map";
import Printer from "./printer";
import type * as t from "@babel/types";

import type { Opts as jsescOptions } from "jsesc";
import type { Format } from "./printer";
import type { DecodedSourceMap, Mapping } from "@jridgewell/gen-mapping";

Expand Down Expand Up @@ -195,19 +195,12 @@ export interface GeneratorOptions {
/**
* Options for outputting jsesc representation.
*/
jsescOption?: {
/**
* The type of quote to use in the output. If omitted, autodetects based on `ast.tokens`.
*/
quotes?: "single" | "double";

/**
* When enabled, the output is a valid JavaScript string literal wrapped in quotes. The type of quotes can be specified through the quotes setting.
* Defaults to `true`.
*/
wrap?: boolean;
};
jsescOption?: jsescOptions;

/**
* For use with the recordAndTuple token.
*/
recordAndTupleSyntaxType?: "hash" | "bar";
/**
* For use with the Hack-style pipe operator.
* Changes what token is used for pipe bodies’ topic references.
Expand Down
21 changes: 9 additions & 12 deletions packages/babel-helper-create-class-features-plugin/src/index.ts
@@ -1,5 +1,5 @@
import { types as t } from "@babel/core";
import type { File } from "@babel/core";
import type { File, PluginAPI, PluginObject } from "@babel/core";
import type { NodePath } from "@babel/traverse";
import nameFunction from "@babel/helper-function-name";
import splitExportDeclaration from "@babel/helper-split-export-declaration";
Expand All @@ -14,7 +14,6 @@ import { buildDecoratedClass, hasDecorators } from "./decorators";
import { injectInitialization, extractComputedKeys } from "./misc";
import { enableFeature, FEATURES, isLoose, shouldTransform } from "./features";
import { assertFieldTransformed } from "./typescript";
import type { ParserOptions } from "@babel/parser";

export { FEATURES, enableFeature, injectInitialization };

Expand All @@ -33,19 +32,17 @@ interface Options {
name: string;
feature: number;
loose?: boolean;
inherits?: (api: any, options: any) => any;
// same as PluginObject.manipulateOptions
manipulateOptions?: (options: unknown, parserOpts: ParserOptions) => void;
// TODO(flow->ts): change to babel api
api?: { assumption: (key?: string) => boolean | undefined };
inherits?: PluginObject["inherits"];
manipulateOptions?: PluginObject["manipulateOptions"];
api?: PluginAPI;
}

export function createClassFeaturePlugin({
name,
feature,
loose,
manipulateOptions,
// TODO(Babel 8): Remove the default value
// @ts-ignore TODO(Babel 8): Remove the default value
api = { assumption: () => void 0 },
inherits,
}: Options) {
Expand Down Expand Up @@ -188,7 +185,7 @@ export function createClassFeaturePlugin({
const privateNamesMap = buildPrivateNamesMap(props);
const privateNamesNodes = buildPrivateNamesNodes(
privateNamesMap,
privateFieldsAsProperties ?? loose,
(privateFieldsAsProperties ?? loose) as boolean,
state,
);

Expand Down Expand Up @@ -227,9 +224,9 @@ export function createClassFeaturePlugin({
props,
privateNamesMap,
state,
setPublicClassFields ?? loose,
privateFieldsAsProperties ?? loose,
constantSuper ?? loose,
(setPublicClassFields ?? loose) as boolean,
(privateFieldsAsProperties ?? loose) as boolean,
(constantSuper ?? loose) as boolean,
innerBinding,
));
}
Expand Down
Expand Up @@ -3,6 +3,7 @@ import { featuresKey, FEATURES, enableFeature, runtimeKey } from "./features";
import { generateRegexpuOptions, canSkipRegexpu, transformFlags } from "./util";

import { types as t } from "@babel/core";
import type { PluginObject } from "@babel/core";
import annotateAsPure from "@babel/helper-annotate-as-pure";

declare const PACKAGE_JSON: { name: string; version: string };
Expand All @@ -20,8 +21,8 @@ export function createRegExpFeaturePlugin({
name,
feature,
options = {} as any,
manipulateOptions = (() => {}) as (opts: any, parserOpts: any) => void,
}) {
manipulateOptions = (() => {}) as PluginObject["manipulateOptions"],
}): PluginObject {
return {
name,

Expand Down
Expand Up @@ -4,7 +4,7 @@ type RootOptions = {
sourceRoot?: string;
};

type PluginOptions = {
export type PluginOptions = {
moduleId?: string;
moduleIds?: boolean;
getModuleId?: (moduleName: string) => string | null | undefined;
Expand Down
3 changes: 2 additions & 1 deletion packages/babel-helper-module-transforms/src/index.ts
Expand Up @@ -34,6 +34,7 @@ import type {
import type { NodePath } from "@babel/traverse";

export { default as getModuleName } from "./get-module-name";
export type { PluginOptions } from "./get-module-name";

export { hasExports, isSideEffectImport, isModule, rewriteThis };

Expand Down Expand Up @@ -184,7 +185,7 @@ export function wrapInterop(
export function buildNamespaceInitStatements(
metadata: ModuleMetadata,
sourceMetadata: SourceModuleMetadata,
constantReexports: boolean = false,
constantReexports: boolean | void = false,
) {
const statements = [];

Expand Down
40 changes: 24 additions & 16 deletions packages/babel-helper-plugin-utils/src/index.ts
@@ -1,20 +1,24 @@
export function declare<
Args extends
| [any]
| [any, any?]
| [any, any?, any?]
| [any, any]
| [any, any, any?]
| [any, any, any],
Builder extends (...args: Args) => any,
>(
builder: Builder,
// todo(flow->ts) maybe add stricter type for returned function
// reason any is there to not expose exact implementation details in type
// example of issue with this packages/babel-preset-typescript/src/index.ts
): Builder extends (...args: infer A) => any ? (...args: A) => any : never {
import type {
PluginAPI,
PluginObject,
PluginPass,
PresetAPI,
PresetObject,
} from "@babel/core";

export function declare<State = {}, Option = {}>(
builder: (
api: PluginAPI,
options: Option,
dirname: string,
) => PluginObject<State & PluginPass>,
): (
api: PluginAPI,
options: Option,
dirname: string,
) => PluginObject<State & PluginPass> {
// @ts-ignore
return (api, options, dirname) => {
return (api, options: Option, dirname: string) => {
let clonedApi;

for (const name of Object.keys(apiPolyfills)) {
Expand All @@ -30,6 +34,10 @@ export function declare<
};
}

export const declarePreset = declare as <Option = {}>(
builder: (api: PresetAPI, options: Option, dirname: string) => PresetObject,
) => (api: PresetAPI, options: Option, dirname: string) => PresetObject;

const apiPolyfills = {
// Not supported by Babel 7 and early versions of Babel 7 beta.
// It's important that this is polyfilled for older Babel versions
Expand Down
2 changes: 1 addition & 1 deletion packages/babel-parser/src/plugins/flow/index.js
Expand Up @@ -353,7 +353,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
return type;
}

flowParsePredicate(): N.FlowType {
flowParsePredicate(): N.FlowPredicate {
const node = this.startNode();
const moduloLoc = this.state.startLoc;
this.next(); // eat `%`
Expand Down
3 changes: 2 additions & 1 deletion packages/babel-parser/typings/babel-parser.d.ts
Expand Up @@ -182,7 +182,7 @@ export interface DecoratorsPluginOptions {

export interface PipelineOperatorPluginOptions {
proposal: "minimal" | "fsharp" | "hack" | "smart";
topicToken?: "%" | "#" | "@@" | "^^";
topicToken?: "%" | "#" | "@@" | "^^" | "^";
}

export interface RecordAndTuplePluginOptions {
Expand All @@ -191,6 +191,7 @@ export interface RecordAndTuplePluginOptions {

export interface FlowPluginOptions {
all?: boolean;
enums?: boolean;
}

export interface TypeScriptPluginOptions {
Expand Down

0 comments on commit c90add7

Please sign in to comment.