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
|
@@ -126,13 +126,7 @@ function firstCallArgument(call) {
|
|
|
126
126
|
return argument;
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
-
|
|
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 };
|