1. /**
    
  2.  * Copyright (c) Meta Platforms, Inc. and affiliates.
    
  3.  *
    
  4.  * This source code is licensed under the MIT license found in the
    
  5.  * LICENSE file in the root directory of this source tree.
    
  6.  *
    
  7.  * @emails react-core
    
  8.  */
    
  9. 
    
  10. 'use strict';
    
  11. 
    
  12. const fs = require('fs');
    
  13. const path = require('path');
    
  14. const errorMap = JSON.parse(
    
  15.   fs.readFileSync(path.resolve(__dirname, '../error-codes/codes.json'))
    
  16. );
    
  17. const errorMessages = new Set();
    
  18. Object.keys(errorMap).forEach(key => errorMessages.add(errorMap[key]));
    
  19. 
    
  20. function nodeToErrorTemplate(node) {
    
  21.   if (node.type === 'Literal' && typeof node.value === 'string') {
    
  22.     return node.value;
    
  23.   } else if (node.type === 'BinaryExpression' && node.operator === '+') {
    
  24.     const l = nodeToErrorTemplate(node.left);
    
  25.     const r = nodeToErrorTemplate(node.right);
    
  26.     return l + r;
    
  27.   } else if (node.type === 'TemplateLiteral') {
    
  28.     let elements = [];
    
  29.     for (let i = 0; i < node.quasis.length; i++) {
    
  30.       const elementNode = node.quasis[i];
    
  31.       if (elementNode.type !== 'TemplateElement') {
    
  32.         throw new Error('Unsupported type ' + node.type);
    
  33.       }
    
  34.       elements.push(elementNode.value.cooked);
    
  35.     }
    
  36.     return elements.join('%s');
    
  37.   } else {
    
  38.     return '%s';
    
  39.   }
    
  40. }
    
  41. 
    
  42. module.exports = {
    
  43.   meta: {
    
  44.     schema: [],
    
  45.   },
    
  46.   create(context) {
    
  47.     function ErrorCallExpression(node) {
    
  48.       const errorMessageNode = node.arguments[0];
    
  49.       if (errorMessageNode === undefined) {
    
  50.         return;
    
  51.       }
    
  52.       const errorMessage = nodeToErrorTemplate(errorMessageNode);
    
  53.       if (errorMessages.has(errorMessage)) {
    
  54.         return;
    
  55.       }
    
  56.       context.report({
    
  57.         node,
    
  58.         message:
    
  59.           'Error message does not have a corresponding production error code. Add ' +
    
  60.           'the following message to codes.json so it can be stripped ' +
    
  61.           'from the production builds:\n\n' +
    
  62.           errorMessage,
    
  63.       });
    
  64.     }
    
  65. 
    
  66.     return {
    
  67.       NewExpression(node) {
    
  68.         if (node.callee.type === 'Identifier' && node.callee.name === 'Error') {
    
  69.           ErrorCallExpression(node);
    
  70.         }
    
  71.       },
    
  72.       CallExpression(node) {
    
  73.         if (node.callee.type === 'Identifier' && node.callee.name === 'Error') {
    
  74.           ErrorCallExpression(node);
    
  75.         }
    
  76.       },
    
  77.     };
    
  78.   },
    
  79. };