Software zum Installieren eines Smart-Mirror Frameworks , zum Nutzen von hochschulrelevanten Informationen, auf einem Raspberry-Pi.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

builders.js 5.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. import t from "../../lib/index.js";
  2. import definitions from "../../lib/definitions/index.js";
  3. import formatBuilderName from "../utils/formatBuilderName.js";
  4. import lowerFirst from "../utils/lowerFirst.js";
  5. import stringifyValidator from "../utils/stringifyValidator.js";
  6. function areAllRemainingFieldsNullable(fieldName, fieldNames, fields) {
  7. const index = fieldNames.indexOf(fieldName);
  8. return fieldNames.slice(index).every(_ => isNullable(fields[_]));
  9. }
  10. function hasDefault(field) {
  11. return field.default != null;
  12. }
  13. function isNullable(field) {
  14. return field.optional || hasDefault(field);
  15. }
  16. function sortFieldNames(fields, type) {
  17. return fields.sort((fieldA, fieldB) => {
  18. const indexA = t.BUILDER_KEYS[type].indexOf(fieldA);
  19. const indexB = t.BUILDER_KEYS[type].indexOf(fieldB);
  20. if (indexA === indexB) return fieldA < fieldB ? -1 : 1;
  21. if (indexA === -1) return 1;
  22. if (indexB === -1) return -1;
  23. return indexA - indexB;
  24. });
  25. }
  26. function generateBuilderArgs(type) {
  27. const fields = t.NODE_FIELDS[type];
  28. const fieldNames = sortFieldNames(Object.keys(t.NODE_FIELDS[type]), type);
  29. const builderNames = t.BUILDER_KEYS[type];
  30. const args = [];
  31. fieldNames.forEach(fieldName => {
  32. const field = fields[fieldName];
  33. // Future / annoying TODO:
  34. // MemberExpression.property, ObjectProperty.key and ObjectMethod.key need special cases; either:
  35. // - convert the declaration to chain() like ClassProperty.key and ClassMethod.key,
  36. // - declare an alias type for valid keys, detect the case and reuse it here,
  37. // - declare a disjoint union with, for example, ObjectPropertyBase,
  38. // ObjectPropertyLiteralKey and ObjectPropertyComputedKey, and declare ObjectProperty
  39. // as "ObjectPropertyBase & (ObjectPropertyLiteralKey | ObjectPropertyComputedKey)"
  40. let typeAnnotation = stringifyValidator(field.validate, "t.");
  41. if (isNullable(field) && !hasDefault(field)) {
  42. typeAnnotation += " | null";
  43. }
  44. if (builderNames.includes(fieldName)) {
  45. const bindingIdentifierName = t.toBindingIdentifierName(fieldName);
  46. if (areAllRemainingFieldsNullable(fieldName, builderNames, fields)) {
  47. args.push(
  48. `${bindingIdentifierName}${
  49. isNullable(field) ? "?:" : ":"
  50. } ${typeAnnotation}`
  51. );
  52. } else {
  53. args.push(
  54. `${bindingIdentifierName}: ${typeAnnotation}${
  55. isNullable(field) ? " | undefined" : ""
  56. }`
  57. );
  58. }
  59. }
  60. });
  61. return args;
  62. }
  63. export default function generateBuilders(kind) {
  64. return kind === "uppercase.js"
  65. ? generateUppercaseBuilders()
  66. : generateLowercaseBuilders();
  67. }
  68. function generateLowercaseBuilders() {
  69. let output = `/*
  70. * This file is auto-generated! Do not modify it directly.
  71. * To re-generate run 'make build'
  72. */
  73. import builder from "../builder";
  74. import type * as t from "../..";
  75. /* eslint-disable @typescript-eslint/no-unused-vars */
  76. `;
  77. const reservedNames = new Set(["super", "import"]);
  78. Object.keys(definitions.BUILDER_KEYS).forEach(type => {
  79. const defArgs = generateBuilderArgs(type);
  80. const formatedBuilderName = formatBuilderName(type);
  81. const formatedBuilderNameLocal = reservedNames.has(formatedBuilderName)
  82. ? `_${formatedBuilderName}`
  83. : formatedBuilderName;
  84. output += `${
  85. formatedBuilderNameLocal === formatedBuilderName ? "export " : ""
  86. }function ${formatedBuilderNameLocal}(${defArgs.join(
  87. ", "
  88. )}): t.${type} { return builder("${type}", ...arguments); }\n`;
  89. if (formatedBuilderNameLocal !== formatedBuilderName) {
  90. output += `export { ${formatedBuilderNameLocal} as ${formatedBuilderName} };\n`;
  91. }
  92. // This is needed for backwards compatibility.
  93. // It should be removed in the next major version.
  94. // JSXIdentifier -> jSXIdentifier
  95. if (/^[A-Z]{2}/.test(type)) {
  96. output += `export { ${formatedBuilderNameLocal} as ${lowerFirst(
  97. type
  98. )} }\n`;
  99. }
  100. });
  101. Object.keys(definitions.DEPRECATED_KEYS).forEach(type => {
  102. const newType = definitions.DEPRECATED_KEYS[type];
  103. const formatedBuilderName = formatBuilderName(type);
  104. output += `/** @deprecated */
  105. function ${type}(...args: Array<any>): any {
  106. console.trace("The node type ${type} has been renamed to ${newType}");
  107. return builder("${type}", ...args);
  108. }
  109. export { ${type} as ${formatedBuilderName} };\n`;
  110. // This is needed for backwards compatibility.
  111. // It should be removed in the next major version.
  112. // JSXIdentifier -> jSXIdentifier
  113. if (/^[A-Z]{2}/.test(type)) {
  114. output += `export { ${type} as ${lowerFirst(type)} }\n`;
  115. }
  116. });
  117. return output;
  118. }
  119. function generateUppercaseBuilders() {
  120. let output = `/*
  121. * This file is auto-generated! Do not modify it directly.
  122. * To re-generate run 'make build'
  123. */
  124. /**
  125. * This file is written in JavaScript and not TypeScript because uppercase builders
  126. * conflict with AST types. TypeScript reads the uppercase.d.ts file instead.
  127. */
  128. export {\n`;
  129. Object.keys(definitions.BUILDER_KEYS).forEach(type => {
  130. const formatedBuilderName = formatBuilderName(type);
  131. output += ` ${formatedBuilderName} as ${type},\n`;
  132. });
  133. Object.keys(definitions.DEPRECATED_KEYS).forEach(type => {
  134. const formatedBuilderName = formatBuilderName(type);
  135. output += ` ${formatedBuilderName} as ${type},\n`;
  136. });
  137. output += ` } from './index';\n`;
  138. return output;
  139. }