eslint-plugin-no-mistakes 0.86.2 → 0.86.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-no-mistakes",
3
- "version": "0.86.2",
3
+ "version": "0.86.3",
4
4
  "description": "ESLint and Oxlint rules that keep code static enough for no-mistakes analyzers and coding agents",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -126,13 +126,7 @@ function firstCallArgument(call) {
126
126
  return argument;
127
127
  }
128
128
 
129
- function stripSqlComments(text) {
130
- return text.replace(/\/\*[\s\S]*?\*\//g, " ").replace(/--[^\n]*/g, " ");
131
- }
132
-
133
- function isManualTransactionText(text) {
134
- return typeof text === "string" && TRANSACTION_COMMAND.test(stripSqlComments(text));
135
- }
129
+ const { isManualTransactionText } = require("./postgres-transaction-statements");
136
130
 
137
131
  module.exports = {
138
132
  DEFAULT_CHUNK_FUNCTION_NAMES,
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+
3
+ // PostgreSQL accepts high-bit identifier bytes in dollar-quote tags, not only ASCII.
4
+ const IDENTIFIER_CONTINUATION = /[a-z0-9_$\u0080-\uffff]/i;
5
+ const DOLLAR_DELIMITER = /^\$(?:[a-z_\u0080-\uffff][a-z0-9_\u0080-\uffff]*)?\$/i;
6
+ const TRANSACTION_COMMAND = /^\s*(?:BEGIN|COMMIT|ROLLBACK)\b/i;
7
+ const SAVEPOINT_ROLLBACK =
8
+ /^\s*ROLLBACK(?:\s+(?:WORK|TRANSACTION))?\s+TO(?:\s+SAVEPOINT)?\s+(?!SAVEPOINT\s*$)(?:[a-z_\u0080-\uffff][a-z0-9_$\u0080-\uffff]*|"(?:[^"]|"")+")\s*$/i;
9
+
10
+ // Preserve quoted text as opaque tokens. Only unquoted semicolons end statements.
11
+ // Comments are whitespace, including nested PostgreSQL block comments.
12
+ function transactionStatements(text) {
13
+ const statements = [];
14
+ let statement = "";
15
+ let malformed = false;
16
+ let index = 0;
17
+ while (index < text.length) {
18
+ const rest = text.slice(index);
19
+ if (rest.startsWith("--")) {
20
+ const end = text.indexOf("\n", index + 2);
21
+ index = end === -1 ? text.length : end;
22
+ statement += " ";
23
+ } else if (rest.startsWith("/*")) {
24
+ let depth = 1;
25
+ index += 2;
26
+ while (index < text.length && depth > 0) {
27
+ if (text.startsWith("/*", index)) {
28
+ depth++;
29
+ index += 2;
30
+ } else if (text.startsWith("*/", index)) {
31
+ depth--;
32
+ index += 2;
33
+ } else index++;
34
+ }
35
+ if (depth !== 0) malformed = true;
36
+ statement += " ";
37
+ } else if (text[index] === '"' || text[index] === "'") {
38
+ const start = index;
39
+ const quote = text[index++];
40
+ const escaped =
41
+ quote === "'" &&
42
+ (text[start - 1] === "E" || text[start - 1] === "e") &&
43
+ (start < 2 || !IDENTIFIER_CONTINUATION.test(text[start - 2]));
44
+ let closed = false;
45
+ while (index < text.length) {
46
+ if (text[index] === "\\") {
47
+ // Plain strings depend on standard_conforming_strings; do not exempt
48
+ // transaction text whose boundary depends on an unknown server setting.
49
+ if (quote === "'" && !escaped) malformed = true;
50
+ if (escaped) {
51
+ index += 2;
52
+ continue;
53
+ }
54
+ }
55
+ if (text[index] === quote) {
56
+ if (text[index + 1] === quote) {
57
+ index += 2;
58
+ continue;
59
+ }
60
+ index++;
61
+ closed = true;
62
+ break;
63
+ }
64
+ index++;
65
+ }
66
+ if (!closed) malformed = true;
67
+ statement += text.slice(start, index);
68
+ } else if (
69
+ text[index] === "$" &&
70
+ (index === 0 || !IDENTIFIER_CONTINUATION.test(text[index - 1]))
71
+ ) {
72
+ const delimiter = DOLLAR_DELIMITER.exec(rest)?.[0];
73
+ if (!delimiter) {
74
+ statement += text[index++];
75
+ continue;
76
+ }
77
+ const end = text.indexOf(delimiter, index + delimiter.length);
78
+ if (end === -1) {
79
+ malformed = true;
80
+ statement += rest;
81
+ index = text.length;
82
+ } else {
83
+ statement += text.slice(index, end + delimiter.length);
84
+ index = end + delimiter.length;
85
+ }
86
+ } else if (text[index] === ";") {
87
+ statements.push(statement);
88
+ statement = "";
89
+ index++;
90
+ } else statement += text[index++];
91
+ }
92
+ statements.push(statement);
93
+ return { statements, malformed };
94
+ }
95
+
96
+ function isManualTransactionText(text) {
97
+ if (typeof text !== "string") return false;
98
+ const { statements, malformed } = transactionStatements(text);
99
+ if (malformed && /\b(?:BEGIN|COMMIT|ROLLBACK)\b/i.test(text)) return true;
100
+ return statements.some(
101
+ (statement) => TRANSACTION_COMMAND.test(statement) && !SAVEPOINT_ROLLBACK.test(statement),
102
+ );
103
+ }
104
+
105
+ module.exports = { isManualTransactionText };