function whitage()

in web/jslint/src/main/resources/data/jslint-2020-03-28.js [4224:4446]


function whitage() {
  var closer = "(end)";
  var free = false;
  var left = global;
  var margin = 0;
  var nr_comments_skipped = 0;
  var open = true;
  var opening = true;
  var right;

  function pop() {
    var previous = stack.pop();
    closer = previous.closer;
    free = previous.free;
    margin = previous.margin;
    open = previous.open;
    opening = previous.opening;
  }

  function push() {
    stack.push({
      closer: closer,
      free: free,
      margin: margin,
      open: open,
      opening: opening
    });
  }

  function expected_at(at) {
    warn("expected_a_at_b_c", right, artifact(right), fudge + at, artifact_column(right));
  }

  function at_margin(fit) {
    var at = margin + fit;

    if (right.from !== at) {
      return expected_at(at);
    }
  }

  function no_space_only() {
    if (left.id !== "(global)" && left.nr + 1 === right.nr && (left.line !== right.line || left.thru !== right.from)) {
      warn("unexpected_space_a_b", right, artifact(left), artifact(right));
    }
  }

  function no_space() {
    if (left.line === right.line) {
      if (left.thru !== right.from && nr_comments_skipped === 0) {
        warn("unexpected_space_a_b", right, artifact(left), artifact(right));
      }
    } else {
      if (open) {
        var at = free ? margin : margin + 8;

        if (right.from < at) {
          expected_at(at);
        }
      } else {
        if (right.from !== margin + 8) {
          expected_at(margin + 8);
        }
      }
    }
  }

  function one_space_only() {
    if (left.line !== right.line || left.thru + 1 !== right.from) {
      warn("expected_space_a_b", right, artifact(left), artifact(right));
    }
  }

  function one_space() {
    if (left.line === right.line || !open) {
      if (left.thru + 1 !== right.from && nr_comments_skipped === 0) {
        warn("expected_space_a_b", right, artifact(left), artifact(right));
      }
    } else {
      if (right.from !== margin) {
        expected_at(margin);
      }
    }
  }

  stack = [];
  tokens.forEach(function (the_token) {
    right = the_token;

    if (right.id === "(comment)" || right.id === "(end)") {
      nr_comments_skipped += 1;
    } else {
      // If left is an opener and right is not the closer, then push the previous
      // state. If the token following the opener is on the next line, then this is
      // an open form. If the tokens are on the same line, then it is a closed form.
      // Open form is more readable, with each item (statement, argument, parameter,
      // etc) starting on its own line. Closed form is more compact. Statement blocks
      // are always in open form.
      var new_closer = opener[left.id];

      if (typeof new_closer === "string") {
        if (new_closer !== right.id) {
          opening = left.open || left.line !== right.line;
          push();
          closer = new_closer;

          if (opening) {
            free = closer === ")" && left.free;
            open = true;
            margin += 4;

            if (right.role === "label") {
              if (right.from !== 0) {
                expected_at(0);
              }
            } else if (right.switch) {
              at_margin(-4);
            } else {
              at_margin(0);
            }
          } else {
            if (right.statement || right.role === "label") {
              warn("expected_line_break_a_b", right, artifact(left), artifact(right));
            }

            free = false;
            open = false;
            no_space_only();
          }
        } else {
          // If left and right are opener and closer, then the placement of right depends
          // on the openness. Illegal pairs (like '{]') have already been detected.
          if (left.line === right.line) {
            no_space();
          } else {
            at_margin(0);
          }
        }
      } else {
        if (right.statement === true) {
          if (left.id === "else") {
            one_space_only();
          } else {
            at_margin(0);
            open = false;
          } // If right is a closer, then pop the previous state.

        } else if (right.id === closer) {
          pop();

          if (opening && right.id !== ";") {
            at_margin(0);
          } else {
            no_space_only();
          }
        } else {
          // Left is not an opener, and right is not a closer.
          // The nature of left and right will determine the space between them.
          // If left is ',' or ';' or right is a statement then if open,
          // right must go at the margin, or if closed, a space between.
          if (right.switch) {
            at_margin(-4);
          } else if (right.role === "label") {
            if (right.from !== 0) {
              expected_at(0);
            }
          } else if (left.id === ",") {
            if (!open || (free || closer === "]") && left.line === right.line) {
              one_space();
            } else {
              at_margin(0);
            } // If right is a ternary operator, line it up on the margin.

          } else if (right.arity === "ternary") {
            if (open) {
              at_margin(0);
            } else {
              warn("use_open", right);
            }
          } else if (right.arity === "binary" && right.id === "(" && free) {
            no_space();
          } else if (left.id === "." || left.id === "?." || left.id === "..." || right.id === "," || right.id === ";" || right.id === ":" || right.arity === "binary" && (right.id === "(" || right.id === "[") || right.arity === "function" && left.id !== "function") {
            no_space_only();
          } else if (right.id === "." || right.id === "?.") {
            no_space_only();
          } else if (left.id === ";") {
            if (open) {
              at_margin(0);
            }
          } else if (left.arity === "ternary" || left.id === "case" || left.id === "catch" || left.id === "else" || left.id === "finally" || left.id === "while" || right.id === "catch" || right.id === "else" || right.id === "finally" || right.id === "while" && !right.statement || left.id === ")" && right.id === "{") {
            one_space_only();
          } else if (left.id === "var" || left.id === "const" || left.id === "let") {
            push();
            closer = ";";
            free = false;
            open = left.open;

            if (open) {
              margin = margin + 4;
              at_margin(0);
            } else {
              one_space_only();
            }
          } else if ( // There is a space between left and right.
          spaceop[left.id] === true || spaceop[right.id] === true || left.arity === "binary" && (left.id === "+" || left.id === "-") || right.arity === "binary" && (right.id === "+" || right.id === "-") || left.id === "function" || left.id === ":" || (left.identifier || left.id === "(string)" || left.id === "(number)") && (right.identifier || right.id === "(string)" || right.id === "(number)") || left.arity === "statement" && right.id !== ";") {
            one_space();
          } else if (left.arity === "unary" && left.id !== "`") {
            no_space_only();
          }
        }
      }

      nr_comments_skipped = 0;
      delete left.calls;
      delete left.dead;
      delete left.free;
      delete left.init;
      delete left.open;
      delete left.used;
      left = right;
    }
  });
} // The jslint function itself.