项目原始demo,不改动
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.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.
 
 
 
 

100 lines
3.6 KiB

  1. /**
  2. * @fileoverview Rule to spot scenarios where a newline looks like it is ending a statement, but is not.
  3. * @author Glen Mailer
  4. */
  5. "use strict";
  6. //------------------------------------------------------------------------------
  7. // Requirements
  8. //------------------------------------------------------------------------------
  9. const astUtils = require("../ast-utils");
  10. //------------------------------------------------------------------------------
  11. // Rule Definition
  12. //------------------------------------------------------------------------------
  13. module.exports = {
  14. meta: {
  15. docs: {
  16. description: "disallow confusing multiline expressions",
  17. category: "Possible Errors",
  18. recommended: true,
  19. url: "https://eslint.org/docs/rules/no-unexpected-multiline"
  20. },
  21. schema: []
  22. },
  23. create(context) {
  24. const FUNCTION_MESSAGE = "Unexpected newline between function and ( of function call.";
  25. const PROPERTY_MESSAGE = "Unexpected newline between object and [ of property access.";
  26. const TAGGED_TEMPLATE_MESSAGE = "Unexpected newline between template tag and template literal.";
  27. const DIVISION_MESSAGE = "Unexpected newline between numerator and division operator.";
  28. const REGEX_FLAG_MATCHER = /^[gimsuy]+$/;
  29. const sourceCode = context.getSourceCode();
  30. /**
  31. * Check to see if there is a newline between the node and the following open bracket
  32. * line's expression
  33. * @param {ASTNode} node The node to check.
  34. * @param {string} msg The error message to use.
  35. * @returns {void}
  36. * @private
  37. */
  38. function checkForBreakAfter(node, msg) {
  39. const openParen = sourceCode.getTokenAfter(node, astUtils.isNotClosingParenToken);
  40. const nodeExpressionEnd = sourceCode.getTokenBefore(openParen);
  41. if (openParen.loc.start.line !== nodeExpressionEnd.loc.end.line) {
  42. context.report({ node, loc: openParen.loc.start, message: msg, data: { char: openParen.value } });
  43. }
  44. }
  45. //--------------------------------------------------------------------------
  46. // Public API
  47. //--------------------------------------------------------------------------
  48. return {
  49. MemberExpression(node) {
  50. if (!node.computed) {
  51. return;
  52. }
  53. checkForBreakAfter(node.object, PROPERTY_MESSAGE);
  54. },
  55. TaggedTemplateExpression(node) {
  56. if (node.tag.loc.end.line === node.quasi.loc.start.line) {
  57. return;
  58. }
  59. context.report({ node, loc: node.loc.start, message: TAGGED_TEMPLATE_MESSAGE });
  60. },
  61. CallExpression(node) {
  62. if (node.arguments.length === 0) {
  63. return;
  64. }
  65. checkForBreakAfter(node.callee, FUNCTION_MESSAGE);
  66. },
  67. "BinaryExpression[operator='/'] > BinaryExpression[operator='/'].left"(node) {
  68. const secondSlash = sourceCode.getTokenAfter(node, token => token.value === "/");
  69. const tokenAfterOperator = sourceCode.getTokenAfter(secondSlash);
  70. if (
  71. tokenAfterOperator.type === "Identifier" &&
  72. REGEX_FLAG_MATCHER.test(tokenAfterOperator.value) &&
  73. secondSlash.range[1] === tokenAfterOperator.range[0]
  74. ) {
  75. checkForBreakAfter(node.left, DIVISION_MESSAGE);
  76. }
  77. }
  78. };
  79. }
  80. };