BVB Source Codes

prettier Show fast-path.js Source code

Return Download prettier: download fast-path.js Source code - Download prettier Source code - Type:.js
  1. "use strict";
  2.  
  3. const assert = require("assert");
  4. const util = require("./util");
  5. const startsWithNoLookaheadToken = util.startsWithNoLookaheadToken;
  6.  
  7. function FastPath(value) {
  8.   assert.ok(this instanceof FastPath);
  9.   this.stack = [value];
  10. }
  11.  
  12. // The name of the current property is always the penultimate element of
  13. // this.stack, and always a String.
  14. FastPath.prototype.getName = function getName() {
  15.   const s = this.stack;
  16.   const len = s.length;
  17.   if (len > 1) {
  18.     return s[len - 2];
  19.   }
  20.   // Since the name is always a string, null is a safe sentinel value to
  21.   // return if we do not know the name of the (root) value.
  22.   return null;
  23. };
  24.  
  25. // The value of the current property is always the final element of
  26. // this.stack.
  27. FastPath.prototype.getValue = function getValue() {
  28.   const s = this.stack;
  29.   return s[s.length - 1];
  30. };
  31.  
  32. function getNodeHelper(path, count) {
  33.   const s = path.stack;
  34.  
  35.   for (let i = s.length - 1; i >= 0; i -= 2) {
  36.     const value = s[i];
  37.  
  38.     if (value && !Array.isArray(value) && --count < 0) {
  39.       return value;
  40.     }
  41.   }
  42.  
  43.   return null;
  44. }
  45.  
  46. FastPath.prototype.getNode = function getNode(count) {
  47.   return getNodeHelper(this, ~~count);
  48. };
  49.  
  50. FastPath.prototype.getParentNode = function getParentNode(count) {
  51.   return getNodeHelper(this, ~~count + 1);
  52. };
  53.  
  54. // Temporarily push properties named by string arguments given after the
  55. // callback function onto this.stack, then call the callback with a
  56. // reference to this (modified) FastPath object. Note that the stack will
  57. // be restored to its original state after the callback is finished, so it
  58. // is probably a mistake to retain a reference to the path.
  59. FastPath.prototype.call = function call(callback /*, name1, name2, ... */) {
  60.   const s = this.stack;
  61.   const origLen = s.length;
  62.   let value = s[origLen - 1];
  63.   const argc = arguments.length;
  64.   for (let i = 1; i < argc; ++i) {
  65.     const name = arguments[i];
  66.     value = value[name];
  67.     s.push(name, value);
  68.   }
  69.   const result = callback(this);
  70.   s.length = origLen;
  71.   return result;
  72. };
  73.  
  74. // Similar to FastPath.prototype.call, except that the value obtained by
  75. // accessing this.getValue()[name1][name2]... should be array-like. The
  76. // callback will be called with a reference to this path object for each
  77. // element of the array.
  78. FastPath.prototype.each = function each(callback /*, name1, name2, ... */) {
  79.   const s = this.stack;
  80.   const origLen = s.length;
  81.   let value = s[origLen - 1];
  82.   const argc = arguments.length;
  83.  
  84.   for (let i = 1; i < argc; ++i) {
  85.     const name = arguments[i];
  86.     value = value[name];
  87.     s.push(name, value);
  88.   }
  89.  
  90.   for (let i = 0; i < value.length; ++i) {
  91.     if (i in value) {
  92.       s.push(i, value[i]);
  93.       // If the callback needs to know the value of i, call
  94.       // path.getName(), assuming path is the parameter name.
  95.       callback(this);
  96.       s.length -= 2;
  97.     }
  98.   }
  99.  
  100.   s.length = origLen;
  101. };
  102.  
  103. // Similar to FastPath.prototype.each, except that the results of the
  104. // callback function invocations are stored in an array and returned at
  105. // the end of the iteration.
  106. FastPath.prototype.map = function map(callback /*, name1, name2, ... */) {
  107.   const s = this.stack;
  108.   const origLen = s.length;
  109.   let value = s[origLen - 1];
  110.   const argc = arguments.length;
  111.  
  112.   for (let i = 1; i < argc; ++i) {
  113.     const name = arguments[i];
  114.     value = value[name];
  115.     s.push(name, value);
  116.   }
  117.  
  118.   const result = new Array(value.length);
  119.  
  120.   for (let i = 0; i < value.length; ++i) {
  121.     if (i in value) {
  122.       s.push(i, value[i]);
  123.       result[i] = callback(this, i);
  124.       s.length -= 2;
  125.     }
  126.   }
  127.  
  128.   s.length = origLen;
  129.  
  130.   return result;
  131. };
  132.  
  133. FastPath.prototype.needsParens = function() {
  134.   const parent = this.getParentNode();
  135.   if (!parent) {
  136.     return false;
  137.   }
  138.  
  139.   const name = this.getName();
  140.   const node = this.getNode();
  141.  
  142.   // If the value of this path is some child of a Node and not a Node
  143.   // itself, then it doesn't need parentheses. Only Node objects (in
  144.   // fact, only Expression nodes) need parentheses.
  145.   if (this.getValue() !== node) {
  146.     return false;
  147.   }
  148.  
  149.   // Only statements don't need parentheses.
  150.   if (isStatement(node)) {
  151.     return false;
  152.   }
  153.  
  154.   // Identifiers never need parentheses.
  155.   if (node.type === "Identifier") {
  156.     return false;
  157.   }
  158.  
  159.   if (parent.type === "ParenthesizedExpression") {
  160.     return false;
  161.   }
  162.  
  163.   // Add parens around the extends clause of a class. It is needed for almost
  164.   // all expressions.
  165.   if (
  166.     (parent.type === "ClassDeclaration" || parent.type === "ClassExpression") &&
  167.     parent.superClass === node &&
  168.     (node.type === "ArrowFunctionExpression" ||
  169.       node.type === "AssignmentExpression" ||
  170.       node.type === "AwaitExpression" ||
  171.       node.type === "BinaryExpression" ||
  172.       node.type === "ConditionalExpression" ||
  173.       node.type === "LogicalExpression" ||
  174.       node.type === "NewExpression" ||
  175.       node.type === "ObjectExpression" ||
  176.       node.type === "ParenthesizedExpression" ||
  177.       node.type === "SequenceExpression" ||
  178.       node.type === "TaggedTemplateExpression" ||
  179.       node.type === "UnaryExpression" ||
  180.       node.type === "UpdateExpression" ||
  181.       node.type === "YieldExpression")
  182.   ) {
  183.     return true;
  184.   }
  185.  
  186.   if (
  187.     (parent.type === "ArrowFunctionExpression" &&
  188.       parent.body === node &&
  189.       startsWithNoLookaheadToken(node, /* forbidFunctionAndClass */ false)) ||
  190.     (parent.type === "ExpressionStatement" &&
  191.       startsWithNoLookaheadToken(node, /* forbidFunctionAndClass */ true))
  192.   ) {
  193.     return true;
  194.   }
  195.  
  196.   switch (node.type) {
  197.     case "CallExpression":
  198.       if (parent.type === "NewExpression" && parent.callee === node) {
  199.         return true;
  200.       }
  201.       return false;
  202.  
  203.     case "SpreadElement":
  204.     case "SpreadProperty":
  205.       return (
  206.         parent.type === "MemberExpression" &&
  207.         name === "object" &&
  208.         parent.object === node
  209.       );
  210.  
  211.     case "UpdateExpression":
  212.       if (parent.type === "UnaryExpression") {
  213.         return (
  214.           node.prefix &&
  215.           ((node.operator === "++" && parent.operator === "+") ||
  216.             (node.operator === "--" && parent.operator === "-"))
  217.         );
  218.       }
  219.     // else fallthrough
  220.     case "UnaryExpression":
  221.       switch (parent.type) {
  222.         case "UnaryExpression":
  223.           return (
  224.             node.operator === parent.operator &&
  225.             (node.operator === "+" || node.operator === "-")
  226.           );
  227.  
  228.         case "MemberExpression":
  229.           return name === "object" && parent.object === node;
  230.  
  231.         case "TaggedTemplateExpression":
  232.           return true;
  233.  
  234.         case "NewExpression":
  235.         case "CallExpression":
  236.           return name === "callee" && parent.callee === node;
  237.  
  238.         case "BinaryExpression":
  239.           return parent.operator === "**" && name === "left";
  240.  
  241.         default:
  242.           return false;
  243.       }
  244.  
  245.     case "BinaryExpression": {
  246.       if (parent.type === "UpdateExpression") {
  247.         return true;
  248.       }
  249.  
  250.       const isLeftOfAForStatement = node => {
  251.         let i = 0;
  252.         while (node) {
  253.           const parent = this.getParentNode(i++);
  254.           if (!parent) {
  255.             return false;
  256.           }
  257.           if (parent.type === "ForStatement" && parent.init === node) {
  258.             return true;
  259.           }
  260.           node = parent;
  261.         }
  262.         return false;
  263.       };
  264.       if (node.operator === "in" && isLeftOfAForStatement(node)) {
  265.         return true;
  266.       }
  267.     }
  268.     // fallthrough
  269.     case "TSTypeAssertionExpression":
  270.     case "TSAsExpression":
  271.     case "LogicalExpression":
  272.       switch (parent.type) {
  273.         case "CallExpression":
  274.         case "NewExpression":
  275.           return name === "callee" && parent.callee === node;
  276.  
  277.         case "ClassDeclaration":
  278.           return name === "superClass" && parent.superClass === node;
  279.         case "TSTypeAssertionExpression":
  280.         case "TaggedTemplateExpression":
  281.         case "UnaryExpression":
  282.         case "SpreadElement":
  283.         case "SpreadProperty":
  284.         case "AwaitExpression":
  285.         case "TSAsExpression":
  286.         case "TSNonNullExpression":
  287.           return true;
  288.  
  289.         case "MemberExpression":
  290.           return name === "object" && parent.object === node;
  291.  
  292.         case "BinaryExpression":
  293.         case "LogicalExpression": {
  294.           if (!node.operator) {
  295.             return true;
  296.           }
  297.  
  298.           const po = parent.operator;
  299.           const pp = util.getPrecedence(po);
  300.           const no = node.operator;
  301.           const np = util.getPrecedence(no);
  302.  
  303.           if (po === "||" && no === "&&") {
  304.             return true;
  305.           }
  306.  
  307.           if (pp > np) {
  308.             return true;
  309.           }
  310.  
  311.           if (no === "**" && po === "**") {
  312.             return name === "left";
  313.           }
  314.  
  315.           if (pp === np && name === "right") {
  316.             assert.strictEqual(parent.right, node);
  317.             return true;
  318.           }
  319.  
  320.           // Add parenthesis when working with binary operators
  321.           // It's not stricly needed but helps with code understanding
  322.           if (["|", "^", "&", ">>", "<<", ">>>"].indexOf(po) !== -1) {
  323.             return true;
  324.           }
  325.  
  326.           return false;
  327.         }
  328.  
  329.         default:
  330.           return false;
  331.       }
  332.  
  333.     case "SequenceExpression":
  334.       switch (parent.type) {
  335.         case "ReturnStatement":
  336.           return false;
  337.  
  338.         case "ForStatement":
  339.           // Although parentheses wouldn't hurt around sequence
  340.           // expressions in the head of for loops, traditional style
  341.           // dictates that e.g. i++, j++ should not be wrapped with
  342.           // parentheses.
  343.           return false;
  344.  
  345.         case "ExpressionStatement":
  346.           return name !== "expression";
  347.  
  348.         default:
  349.           // Otherwise err on the side of overparenthesization, adding
  350.           // explicit exceptions above if this proves overzealous.
  351.           return true;
  352.       }
  353.  
  354.     case "YieldExpression":
  355.       if (
  356.         parent.type === "UnaryExpression" ||
  357.         parent.type === "AwaitExpression" ||
  358.         parent.type === "TSAsExpression"
  359.       ) {
  360.         return true;
  361.       }
  362.     // else fallthrough
  363.     case "AwaitExpression":
  364.       switch (parent.type) {
  365.         case "TaggedTemplateExpression":
  366.         case "BinaryExpression":
  367.         case "LogicalExpression":
  368.         case "SpreadElement":
  369.         case "SpreadProperty":
  370.         case "TSAsExpression":
  371.           return true;
  372.  
  373.         case "MemberExpression":
  374.           return parent.object === node;
  375.  
  376.         case "NewExpression":
  377.         case "CallExpression":
  378.           return parent.callee === node;
  379.  
  380.         case "ConditionalExpression":
  381.           return parent.test === node;
  382.  
  383.         default:
  384.           return false;
  385.       }
  386.  
  387.     case "ArrayTypeAnnotation":
  388.       return parent.type === "NullableTypeAnnotation";
  389.  
  390.     case "IntersectionTypeAnnotation":
  391.     case "UnionTypeAnnotation":
  392.       return (
  393.         parent.type === "ArrayTypeAnnotation" ||
  394.         parent.type === "NullableTypeAnnotation" ||
  395.         parent.type === "IntersectionTypeAnnotation" ||
  396.         parent.type === "UnionTypeAnnotation"
  397.       );
  398.  
  399.     case "NullableTypeAnnotation":
  400.       return parent.type === "ArrayTypeAnnotation";
  401.  
  402.     case "FunctionTypeAnnotation":
  403.       return (
  404.         parent.type === "UnionTypeAnnotation" ||
  405.         parent.type === "IntersectionTypeAnnotation"
  406.       );
  407.  
  408.     case "NumericLiteral":
  409.     case "Literal":
  410.       return (
  411.         parent.type === "MemberExpression" &&
  412.         typeof node.value === "number" &&
  413.         name === "object" &&
  414.         parent.object === node
  415.       );
  416.  
  417.     case "AssignmentExpression": {
  418.       const grandParent = this.getParentNode(1);
  419.  
  420.       if (parent.type === "ArrowFunctionExpression" && parent.body === node) {
  421.         return true;
  422.       } else if (
  423.         parent.type === "ClassProperty" &&
  424.         parent.key === node &&
  425.         parent.computed
  426.       ) {
  427.         return false;
  428.       } else if (
  429.         parent.type === "TSPropertySignature" &&
  430.         parent.name === node
  431.       ) {
  432.         return false;
  433.       } else if (
  434.         parent.type === "ForStatement" &&
  435.         (parent.init === node || parent.update === node)
  436.       ) {
  437.         return false;
  438.       } else if (parent.type === "ExpressionStatement") {
  439.         return node.left.type === "ObjectPattern";
  440.       } else if (parent.type === "TSPropertySignature" && parent.key === node) {
  441.         return false;
  442.       } else if (parent.type === "AssignmentExpression") {
  443.         return false;
  444.       } else if (
  445.         parent.type === "SequenceExpression" &&
  446.         grandParent &&
  447.         grandParent.type === "ForStatement" &&
  448.         (grandParent.init === parent || grandParent.update === parent)
  449.       ) {
  450.         return false;
  451.       }
  452.       return true;
  453.     }
  454.     case "ConditionalExpression":
  455.       switch (parent.type) {
  456.         case "TaggedTemplateExpression":
  457.         case "UnaryExpression":
  458.         case "SpreadElement":
  459.         case "SpreadProperty":
  460.         case "BinaryExpression":
  461.         case "LogicalExpression":
  462.         case "ExportDefaultDeclaration":
  463.         case "AwaitExpression":
  464.         case "JSXSpreadAttribute":
  465.         case "TSTypeAssertionExpression":
  466.         case "TSAsExpression":
  467.         case "TSNonNullExpression":
  468.           return true;
  469.  
  470.         case "NewExpression":
  471.         case "CallExpression":
  472.           return name === "callee" && parent.callee === node;
  473.  
  474.         case "ConditionalExpression":
  475.           return name === "test" && parent.test === node;
  476.  
  477.         case "MemberExpression":
  478.           return name === "object" && parent.object === node;
  479.  
  480.         default:
  481.           return false;
  482.       }
  483.  
  484.     case "FunctionExpression":
  485.       switch (parent.type) {
  486.         case "CallExpression":
  487.           return name === "callee"; // Not strictly necessary, but it's clearer to the reader if IIFEs are wrapped in parentheses.
  488.         case "TaggedTemplateExpression":
  489.           return true; // This is basically a kind of IIFE.
  490.         case "ExportDefaultDeclaration":
  491.           return true;
  492.         default:
  493.           return false;
  494.       }
  495.  
  496.     case "ArrowFunctionExpression":
  497.       switch (parent.type) {
  498.         case "CallExpression":
  499.           return name === "callee";
  500.  
  501.         case "NewExpression":
  502.           return name === "callee";
  503.  
  504.         case "MemberExpression":
  505.           return name === "object";
  506.  
  507.         case "TSAsExpression":
  508.         case "BindExpression":
  509.         case "TaggedTemplateExpression":
  510.         case "UnaryExpression":
  511.         case "LogicalExpression":
  512.         case "BinaryExpression":
  513.         case "AwaitExpression":
  514.         case "TSTypeAssertionExpression":
  515.           return true;
  516.  
  517.         case "ConditionalExpression":
  518.           return name === "test";
  519.  
  520.         default:
  521.           return false;
  522.       }
  523.  
  524.     case "ClassExpression":
  525.       return parent.type === "ExportDefaultDeclaration";
  526.  
  527.     case "StringLiteral":
  528.       return parent.type === "ExpressionStatement"; // To avoid becoming a directive
  529.   }
  530.  
  531.   return false;
  532. };
  533.  
  534. function isStatement(node) {
  535.   return (
  536.     node.type === "BlockStatement" ||
  537.     node.type === "BreakStatement" ||
  538.     node.type === "ClassBody" ||
  539.     node.type === "ClassDeclaration" ||
  540.     node.type === "ClassMethod" ||
  541.     node.type === "ClassProperty" ||
  542.     node.type === "ContinueStatement" ||
  543.     node.type === "DebuggerStatement" ||
  544.     node.type === "DeclareClass" ||
  545.     node.type === "DeclareExportAllDeclaration" ||
  546.     node.type === "DeclareExportDeclaration" ||
  547.     node.type === "DeclareFunction" ||
  548.     node.type === "DeclareInterface" ||
  549.     node.type === "DeclareModule" ||
  550.     node.type === "DeclareModuleExports" ||
  551.     node.type === "DeclareVariable" ||
  552.     node.type === "DoWhileStatement" ||
  553.     node.type === "ExportAllDeclaration" ||
  554.     node.type === "ExportDefaultDeclaration" ||
  555.     node.type === "ExportNamedDeclaration" ||
  556.     node.type === "ExpressionStatement" ||
  557.     node.type === "ForAwaitStatement" ||
  558.     node.type === "ForInStatement" ||
  559.     node.type === "ForOfStatement" ||
  560.     node.type === "ForStatement" ||
  561.     node.type === "FunctionDeclaration" ||
  562.     node.type === "IfStatement" ||
  563.     node.type === "ImportDeclaration" ||
  564.     node.type === "InterfaceDeclaration" ||
  565.     node.type === "LabeledStatement" ||
  566.     node.type === "MethodDefinition" ||
  567.     node.type === "ReturnStatement" ||
  568.     node.type === "SwitchStatement" ||
  569.     node.type === "ThrowStatement" ||
  570.     node.type === "TryStatement" ||
  571.     node.type === "TSAbstractClassDeclaration" ||
  572.     node.type === "TSEnumDeclaration" ||
  573.     node.type === "TSImportEqualsDeclaration" ||
  574.     node.type === "TSInterfaceDeclaration" ||
  575.     node.type === "TSModuleDeclaration" ||
  576.     node.type === "TSNamespaceExportDeclaration" ||
  577.     node.type === "TSNamespaceFunctionDeclaration" ||
  578.     node.type === "TypeAlias" ||
  579.     node.type === "VariableDeclaration" ||
  580.     node.type === "WhileStatement" ||
  581.     node.type === "WithStatement"
  582.   );
  583. }
  584.  
  585. module.exports = FastPath;
  586.  
downloadfast-path.js Source code - Download prettier Source code
Related Source Codes/Software:
storybook - 2017-06-07
ionicons - The premium icon font for Ionic ... 2017-06-07
AsyncDisplayKit - Smooth asynchronous user interfaces for iOS apps. ... 2017-06-07
lottie-android - Render After Effects animations natively on Androi... 2017-06-07
parse-server - Parse-compatible API server module for Node/Expres... 2017-06-07
inferno - An extremely fast, React-like JavaScript library f... 2017-06-08
guetzli - Perceptual JPEG encoder 2017-06-08
cs-video-courses - List of Computer Science courses with video lectur... 2017-06-08
interviews - Everything you need to know to get the job. 2017-06-08
prepack - Prepack is a partial evaluator for JavaScript. Pre... 2017-06-08
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top