summaryrefslogtreecommitdiff
path: root/tools/node_modules/eslint/node_modules/@babel/types/scripts/generators/builders.js
diff options
context:
space:
mode:
Diffstat (limited to 'tools/node_modules/eslint/node_modules/@babel/types/scripts/generators/builders.js')
-rw-r--r--tools/node_modules/eslint/node_modules/@babel/types/scripts/generators/builders.js163
1 files changed, 163 insertions, 0 deletions
diff --git a/tools/node_modules/eslint/node_modules/@babel/types/scripts/generators/builders.js b/tools/node_modules/eslint/node_modules/@babel/types/scripts/generators/builders.js
new file mode 100644
index 0000000000..13e772eb43
--- /dev/null
+++ b/tools/node_modules/eslint/node_modules/@babel/types/scripts/generators/builders.js
@@ -0,0 +1,163 @@
+import t from "../../lib/index.js";
+import definitions from "../../lib/definitions/index.js";
+import formatBuilderName from "../utils/formatBuilderName.js";
+import lowerFirst from "../utils/lowerFirst.js";
+import stringifyValidator from "../utils/stringifyValidator.js";
+
+function areAllRemainingFieldsNullable(fieldName, fieldNames, fields) {
+ const index = fieldNames.indexOf(fieldName);
+ return fieldNames.slice(index).every(_ => isNullable(fields[_]));
+}
+
+function hasDefault(field) {
+ return field.default != null;
+}
+
+function isNullable(field) {
+ return field.optional || hasDefault(field);
+}
+
+function sortFieldNames(fields, type) {
+ return fields.sort((fieldA, fieldB) => {
+ const indexA = t.BUILDER_KEYS[type].indexOf(fieldA);
+ const indexB = t.BUILDER_KEYS[type].indexOf(fieldB);
+ if (indexA === indexB) return fieldA < fieldB ? -1 : 1;
+ if (indexA === -1) return 1;
+ if (indexB === -1) return -1;
+ return indexA - indexB;
+ });
+}
+
+function generateBuilderArgs(type) {
+ const fields = t.NODE_FIELDS[type];
+ const fieldNames = sortFieldNames(Object.keys(t.NODE_FIELDS[type]), type);
+ const builderNames = t.BUILDER_KEYS[type];
+
+ const args = [];
+
+ fieldNames.forEach(fieldName => {
+ const field = fields[fieldName];
+ // Future / annoying TODO:
+ // MemberExpression.property, ObjectProperty.key and ObjectMethod.key need special cases; either:
+ // - convert the declaration to chain() like ClassProperty.key and ClassMethod.key,
+ // - declare an alias type for valid keys, detect the case and reuse it here,
+ // - declare a disjoint union with, for example, ObjectPropertyBase,
+ // ObjectPropertyLiteralKey and ObjectPropertyComputedKey, and declare ObjectProperty
+ // as "ObjectPropertyBase & (ObjectPropertyLiteralKey | ObjectPropertyComputedKey)"
+ let typeAnnotation = stringifyValidator(field.validate, "t.");
+
+ if (isNullable(field) && !hasDefault(field)) {
+ typeAnnotation += " | null";
+ }
+
+ if (builderNames.includes(fieldName)) {
+ const bindingIdentifierName = t.toBindingIdentifierName(fieldName);
+ if (areAllRemainingFieldsNullable(fieldName, builderNames, fields)) {
+ args.push(
+ `${bindingIdentifierName}${
+ isNullable(field) ? "?:" : ":"
+ } ${typeAnnotation}`
+ );
+ } else {
+ args.push(
+ `${bindingIdentifierName}: ${typeAnnotation}${
+ isNullable(field) ? " | undefined" : ""
+ }`
+ );
+ }
+ }
+ });
+
+ return args;
+}
+
+export default function generateBuilders(kind) {
+ return kind === "uppercase.js"
+ ? generateUppercaseBuilders()
+ : generateLowercaseBuilders();
+}
+
+function generateLowercaseBuilders() {
+ let output = `/*
+ * This file is auto-generated! Do not modify it directly.
+ * To re-generate run 'make build'
+ */
+import builder from "../builder";
+import type * as t from "../..";
+
+/* eslint-disable @typescript-eslint/no-unused-vars */
+
+`;
+
+ const reservedNames = new Set(["super", "import"]);
+ Object.keys(definitions.BUILDER_KEYS).forEach(type => {
+ const defArgs = generateBuilderArgs(type);
+ const formatedBuilderName = formatBuilderName(type);
+ const formatedBuilderNameLocal = reservedNames.has(formatedBuilderName)
+ ? `_${formatedBuilderName}`
+ : formatedBuilderName;
+ output += `${
+ formatedBuilderNameLocal === formatedBuilderName ? "export " : ""
+ }function ${formatedBuilderNameLocal}(${defArgs.join(
+ ", "
+ )}): t.${type} { return builder.apply("${type}", arguments); }\n`;
+ if (formatedBuilderNameLocal !== formatedBuilderName) {
+ output += `export { ${formatedBuilderNameLocal} as ${formatedBuilderName} };\n`;
+ }
+
+ // This is needed for backwards compatibility.
+ // It should be removed in the next major version.
+ // JSXIdentifier -> jSXIdentifier
+ if (/^[A-Z]{2}/.test(type)) {
+ output += `export { ${formatedBuilderNameLocal} as ${lowerFirst(
+ type
+ )} }\n`;
+ }
+ });
+
+ Object.keys(definitions.DEPRECATED_KEYS).forEach(type => {
+ const newType = definitions.DEPRECATED_KEYS[type];
+ const formatedBuilderName = formatBuilderName(type);
+ output += `/** @deprecated */
+function ${type}(${generateBuilderArgs(newType).join(", ")}): t.${type} {
+ console.trace("The node type ${type} has been renamed to ${newType}");
+ return builder.apply("${type}", arguments);
+}
+export { ${type} as ${formatedBuilderName} };\n`;
+ // This is needed for backwards compatibility.
+ // It should be removed in the next major version.
+ // JSXIdentifier -> jSXIdentifier
+ if (/^[A-Z]{2}/.test(type)) {
+ output += `export { ${type} as ${lowerFirst(type)} }\n`;
+ }
+ });
+
+ return output;
+}
+
+function generateUppercaseBuilders() {
+ let output = `/*
+ * This file is auto-generated! Do not modify it directly.
+ * To re-generate run 'make build'
+ */
+
+/**
+ * This file is written in JavaScript and not TypeScript because uppercase builders
+ * conflict with AST types. TypeScript reads the uppercase.d.ts file instead.
+ */
+
+ export {\n`;
+
+ Object.keys(definitions.BUILDER_KEYS).forEach(type => {
+ const formatedBuilderName = formatBuilderName(type);
+ output += ` ${formatedBuilderName} as ${type},\n`;
+ });
+
+ Object.keys(definitions.DEPRECATED_KEYS).forEach(type => {
+ const formatedBuilderName = formatBuilderName(type);
+ output += ` ${formatedBuilderName} as ${type},\n`;
+ });
+
+ output += ` } from './index';\n`;
+ return output;
+}