版博士V2.0程序
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 

384 строки
13 KiB

  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.isStaticValueIdentifier = exports.validateNode = void 0;
  4. const errors_1 = require("./errors");
  5. const token_store_1 = require("./token-store");
  6. const utils_1 = require("./utils");
  7. const require_utils_1 = require("./modules/require-utils");
  8. const lineBreakPattern = /\r\n|[\n\r\u2028\u2029]/u;
  9. const octalNumericLiteralPattern = /^0[Oo]/u;
  10. const legacyOctalNumericLiteralPattern = /^0\d/u;
  11. const binaryNumericLiteralPattern = /^0[Bb]/u;
  12. let cacheCodePointEscapeMatcher;
  13. function getCodePointEscapeMatcher() {
  14. if (!cacheCodePointEscapeMatcher) {
  15. const utils = (0, require_utils_1.loadNewest)([
  16. {
  17. getPkg() {
  18. return (0, require_utils_1.requireFromCwd)("eslint-utils/package.json");
  19. },
  20. get() {
  21. return (0, require_utils_1.requireFromCwd)("eslint-utils");
  22. },
  23. },
  24. {
  25. getPkg() {
  26. return (0, require_utils_1.requireFromLinter)("eslint-utils/package.json");
  27. },
  28. get() {
  29. return (0, require_utils_1.requireFromLinter)("eslint-utils");
  30. },
  31. },
  32. {
  33. getPkg() {
  34. return require("eslint-utils/package.json");
  35. },
  36. get() {
  37. return require("eslint-utils");
  38. },
  39. },
  40. ]);
  41. cacheCodePointEscapeMatcher = new utils.PatternMatcher(/\\u\{[\dA-Fa-f]+\}/gu);
  42. }
  43. return cacheCodePointEscapeMatcher;
  44. }
  45. function validateNode(node, tokens, ctx) {
  46. if (node.type === "ObjectExpression") {
  47. validateObjectExpressionNode(node, tokens, ctx);
  48. return;
  49. }
  50. if (node.type === "Property") {
  51. validatePropertyNode(node, tokens, ctx);
  52. return;
  53. }
  54. if (node.type === "ArrayExpression") {
  55. validateArrayExpressionNode(node, tokens, ctx);
  56. return;
  57. }
  58. if (node.type === "Literal") {
  59. validateLiteralNode(node, tokens, ctx);
  60. return;
  61. }
  62. if (node.type === "UnaryExpression") {
  63. validateUnaryExpressionNode(node, tokens, ctx);
  64. return;
  65. }
  66. if (node.type === "Identifier") {
  67. validateIdentifierNode(node, tokens, ctx);
  68. return;
  69. }
  70. if (node.type === "TemplateLiteral") {
  71. validateTemplateLiteralNode(node, tokens, ctx);
  72. return;
  73. }
  74. if (node.type === "TemplateElement") {
  75. validateTemplateElementNode(node, tokens);
  76. return;
  77. }
  78. throw (0, errors_1.throwUnexpectedNodeError)(node, tokens);
  79. }
  80. exports.validateNode = validateNode;
  81. function validateObjectExpressionNode(node, tokens, ctx) {
  82. if (node.type !== "ObjectExpression") {
  83. throw (0, errors_1.throwUnexpectedNodeError)(node, tokens);
  84. }
  85. for (const prop of node.properties) {
  86. setParent(prop, node);
  87. }
  88. if (!ctx.trailingCommas) {
  89. const token = tokens.getTokenBefore(tokens.getLastToken(node));
  90. if (token && (0, token_store_1.isComma)(token)) {
  91. throw (0, errors_1.throwUnexpectedTokenError)(",", token);
  92. }
  93. }
  94. }
  95. function validatePropertyNode(node, tokens, ctx) {
  96. if (node.type !== "Property") {
  97. throw (0, errors_1.throwUnexpectedNodeError)(node, tokens);
  98. }
  99. setParent(node.key, node);
  100. setParent(node.value, node);
  101. if (node.computed) {
  102. throw (0, errors_1.throwUnexpectedNodeError)(node, tokens);
  103. }
  104. if (node.method) {
  105. throw (0, errors_1.throwUnexpectedNodeError)(node.value, tokens);
  106. }
  107. if (node.shorthand) {
  108. throw (0, errors_1.throwExpectedTokenError)(":", node);
  109. }
  110. if (node.kind !== "init") {
  111. throw (0, errors_1.throwExpectedTokenError)(":", tokens.getFirstToken(node));
  112. }
  113. if (node.key.type === "Literal") {
  114. const keyValueType = typeof node.key.value;
  115. if (keyValueType === "number") {
  116. if (!ctx.numberProperties) {
  117. throw (0, errors_1.throwUnexpectedNodeError)(node.key, tokens);
  118. }
  119. }
  120. else if (keyValueType !== "string") {
  121. throw (0, errors_1.throwUnexpectedNodeError)(node.key, tokens);
  122. }
  123. }
  124. else if (node.key.type === "Identifier") {
  125. if (!ctx.unquoteProperties) {
  126. throw (0, errors_1.throwUnexpectedNodeError)(node.key, tokens);
  127. }
  128. }
  129. else {
  130. throw (0, errors_1.throwUnexpectedNodeError)(node.key, tokens);
  131. }
  132. if (node.value.type === "Identifier") {
  133. if (!isStaticValueIdentifier(node.value, ctx)) {
  134. throw (0, errors_1.throwUnexpectedNodeError)(node.value, tokens);
  135. }
  136. }
  137. }
  138. function validateArrayExpressionNode(node, tokens, ctx) {
  139. if (node.type !== "ArrayExpression") {
  140. throw (0, errors_1.throwUnexpectedNodeError)(node, tokens);
  141. }
  142. if (!ctx.trailingCommas) {
  143. const token = tokens.getTokenBefore(tokens.getLastToken(node));
  144. if (token && (0, token_store_1.isComma)(token)) {
  145. throw (0, errors_1.throwUnexpectedTokenError)(",", token);
  146. }
  147. }
  148. node.elements.forEach((child, index) => {
  149. if (!child) {
  150. if (ctx.sparseArrays) {
  151. return;
  152. }
  153. const beforeIndex = index - 1;
  154. const before = beforeIndex >= 0
  155. ? tokens.getLastToken(node.elements[beforeIndex])
  156. : tokens.getFirstToken(node);
  157. throw (0, errors_1.throwUnexpectedTokenError)(",", tokens.getTokenAfter(before, token_store_1.isComma));
  158. }
  159. if (child.type === "Identifier") {
  160. if (!isStaticValueIdentifier(child, ctx)) {
  161. throw (0, errors_1.throwUnexpectedNodeError)(child, tokens);
  162. }
  163. }
  164. setParent(child, node);
  165. });
  166. }
  167. function validateLiteralNode(node, tokens, ctx) {
  168. if (node.type !== "Literal") {
  169. throw (0, errors_1.throwUnexpectedNodeError)(node, tokens);
  170. }
  171. if ((0, utils_1.isRegExpLiteral)(node)) {
  172. if (!ctx.regExpLiterals) {
  173. throw (0, errors_1.throwUnexpectedNodeError)(node, tokens);
  174. }
  175. }
  176. else if (node.bigint) {
  177. if (!ctx.bigintLiterals) {
  178. throw (0, errors_1.throwUnexpectedNodeError)(node, tokens);
  179. }
  180. }
  181. else {
  182. validateLiteral(node, ctx);
  183. }
  184. }
  185. function validateLiteral(node, ctx) {
  186. const value = node.value;
  187. if ((!ctx.invalidJsonNumbers ||
  188. !ctx.leadingOrTrailingDecimalPoints ||
  189. !ctx.numericSeparators) &&
  190. typeof value === "number") {
  191. const text = node.raw;
  192. if (!ctx.leadingOrTrailingDecimalPoints) {
  193. if (text.startsWith(".")) {
  194. throw (0, errors_1.throwUnexpectedTokenError)(".", node);
  195. }
  196. if (text.endsWith(".")) {
  197. throw (0, errors_1.throwUnexpectedTokenError)(".", {
  198. range: [node.range[1] - 1, node.range[1]],
  199. loc: {
  200. start: {
  201. line: node.loc.end.line,
  202. column: node.loc.end.column - 1,
  203. },
  204. end: node.loc.end,
  205. },
  206. });
  207. }
  208. }
  209. if (!ctx.numericSeparators) {
  210. if (text.includes("_")) {
  211. const index = text.indexOf("_");
  212. throw (0, errors_1.throwUnexpectedTokenError)("_", {
  213. range: [node.range[0] + index, node.range[0] + index + 1],
  214. loc: {
  215. start: {
  216. line: node.loc.start.line,
  217. column: node.loc.start.column + index,
  218. },
  219. end: {
  220. line: node.loc.start.line,
  221. column: node.loc.start.column + index + 1,
  222. },
  223. },
  224. });
  225. }
  226. }
  227. if (!ctx.octalNumericLiterals) {
  228. if (octalNumericLiteralPattern.test(text)) {
  229. throw (0, errors_1.throwUnexpectedError)("octal numeric literal", node);
  230. }
  231. }
  232. if (!ctx.legacyOctalNumericLiterals) {
  233. if (legacyOctalNumericLiteralPattern.test(text)) {
  234. throw (0, errors_1.throwUnexpectedError)("legacy octal numeric literal", node);
  235. }
  236. }
  237. if (!ctx.binaryNumericLiterals) {
  238. if (binaryNumericLiteralPattern.test(text)) {
  239. throw (0, errors_1.throwUnexpectedError)("binary numeric literal", node);
  240. }
  241. }
  242. if (!ctx.invalidJsonNumbers) {
  243. try {
  244. JSON.parse(text);
  245. }
  246. catch (_a) {
  247. throw (0, errors_1.throwInvalidNumberError)(text, node);
  248. }
  249. }
  250. }
  251. if ((!ctx.multilineStrings ||
  252. !ctx.singleQuotes ||
  253. !ctx.unicodeCodepointEscapes) &&
  254. typeof value === "string") {
  255. if (!ctx.singleQuotes) {
  256. if (node.raw.startsWith("'")) {
  257. throw (0, errors_1.throwUnexpectedError)("single quoted", node);
  258. }
  259. }
  260. if (!ctx.multilineStrings) {
  261. if (lineBreakPattern.test(node.raw)) {
  262. throw (0, errors_1.throwUnexpectedError)("multiline string", node);
  263. }
  264. }
  265. if (!ctx.unicodeCodepointEscapes) {
  266. if (getCodePointEscapeMatcher().test(node.raw)) {
  267. throw (0, errors_1.throwUnexpectedError)("unicode codepoint escape", node);
  268. }
  269. }
  270. }
  271. return undefined;
  272. }
  273. function validateUnaryExpressionNode(node, tokens, ctx) {
  274. if (node.type !== "UnaryExpression") {
  275. throw (0, errors_1.throwUnexpectedNodeError)(node, tokens);
  276. }
  277. const operator = node.operator;
  278. if (operator === "+") {
  279. if (!ctx.plusSigns) {
  280. throw (0, errors_1.throwUnexpectedTokenError)("+", node);
  281. }
  282. }
  283. else if (operator !== "-") {
  284. throw (0, errors_1.throwUnexpectedNodeError)(node, tokens);
  285. }
  286. const argument = node.argument;
  287. if (argument.type === "Literal") {
  288. if (typeof argument.value !== "number") {
  289. throw (0, errors_1.throwUnexpectedNodeError)(argument, tokens);
  290. }
  291. }
  292. else if (argument.type === "Identifier") {
  293. if (!isNumberIdentifier(argument, ctx)) {
  294. throw (0, errors_1.throwUnexpectedNodeError)(argument, tokens);
  295. }
  296. }
  297. else {
  298. throw (0, errors_1.throwUnexpectedNodeError)(argument, tokens);
  299. }
  300. if (!ctx.spacedSigns) {
  301. if (node.range[0] + 1 < argument.range[0]) {
  302. throw (0, errors_1.throwUnexpectedSpaceError)(tokens.getFirstToken(node));
  303. }
  304. }
  305. setParent(argument, node);
  306. }
  307. function validateIdentifierNode(node, tokens, ctx) {
  308. if (node.type !== "Identifier") {
  309. throw (0, errors_1.throwUnexpectedNodeError)(node, tokens);
  310. }
  311. if (!ctx.escapeSequenceInIdentifier) {
  312. if (node.name.length < node.range[1] - node.range[0]) {
  313. throw (0, errors_1.throwUnexpectedError)("escape sequence", node);
  314. }
  315. }
  316. }
  317. function validateTemplateLiteralNode(node, tokens, ctx) {
  318. if (node.type !== "TemplateLiteral") {
  319. throw (0, errors_1.throwUnexpectedNodeError)(node, tokens);
  320. }
  321. if (!ctx.templateLiterals) {
  322. throw (0, errors_1.throwUnexpectedNodeError)(node, tokens);
  323. }
  324. if (node.expressions.length) {
  325. const token = tokens.getFirstToken(node.quasis[0]);
  326. const loc = {
  327. loc: {
  328. start: {
  329. line: token.loc.end.line,
  330. column: token.loc.end.column - 2,
  331. },
  332. end: token.loc.end,
  333. },
  334. range: [token.range[1] - 2, token.range[1]],
  335. };
  336. throw (0, errors_1.throwUnexpectedTokenError)("$", loc);
  337. }
  338. if (!ctx.unicodeCodepointEscapes) {
  339. if (getCodePointEscapeMatcher().test(node.quasis[0].value.raw)) {
  340. throw (0, errors_1.throwUnexpectedError)("unicode codepoint escape", node);
  341. }
  342. }
  343. for (const q of node.quasis) {
  344. setParent(q, node);
  345. }
  346. }
  347. function validateTemplateElementNode(node, tokens) {
  348. if (node.type !== "TemplateElement") {
  349. throw (0, errors_1.throwUnexpectedNodeError)(node, tokens);
  350. }
  351. const { cooked } = node.value;
  352. if (cooked == null) {
  353. throw (0, errors_1.throwUnexpectedNodeError)(node, tokens);
  354. }
  355. const startOffset = -1;
  356. const endOffset = node.tail ? 1 : 2;
  357. node.start += startOffset;
  358. node.end += endOffset;
  359. node.range[0] += startOffset;
  360. node.range[1] += endOffset;
  361. node.loc.start.column += startOffset;
  362. node.loc.end.column += endOffset;
  363. }
  364. function isStaticValueIdentifier(node, ctx) {
  365. if (isNumberIdentifier(node, ctx)) {
  366. return true;
  367. }
  368. return node.name === "undefined" && ctx.undefinedKeywords;
  369. }
  370. exports.isStaticValueIdentifier = isStaticValueIdentifier;
  371. function isNumberIdentifier(node, ctx) {
  372. if (node.name === "Infinity" && ctx.infinities) {
  373. return true;
  374. }
  375. if (node.name === "NaN" && ctx.nans) {
  376. return true;
  377. }
  378. return false;
  379. }
  380. function setParent(prop, parent) {
  381. ;
  382. prop.parent = parent;
  383. }