@sasjs/lint 4.6.1 → 4.8.0
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/README.md +30 -0
- package/package.json +1 -1
- package/rules/file/hasDoxygenHeader.js +1 -1
- package/rules/file/hasMacroNameInMend.js +22 -10
- package/rules/file/hasMacroNameInMend.js.map +1 -1
- package/rules/file/hasMacroParentheses.js +6 -3
- package/rules/file/hasMacroParentheses.js.map +1 -1
- package/rules/file/index.d.ts +1 -0
- package/rules/file/index.js +3 -1
- package/rules/file/index.js.map +1 -1
- package/rules/file/lineEndings.js +7 -5
- package/rules/file/lineEndings.js.map +1 -1
- package/rules/file/minMacroNameLength.js +2 -4
- package/rules/file/minMacroNameLength.js.map +1 -1
- package/rules/file/noMacroIfInOpenCode.d.ts +11 -0
- package/rules/file/noMacroIfInOpenCode.js +84 -0
- package/rules/file/noMacroIfInOpenCode.js.map +1 -0
- package/rules/file/noNestedCommentsInHeader.js +1 -1
- package/rules/file/noNestedMacros.js +2 -2
- package/rules/file/noNestedMacros.js.map +1 -1
- package/rules/file/noSingleAsteriskComments.js +1 -1
- package/rules/file/noSingleAsteriskComments.js.map +1 -1
- package/rules/file/strictMacroDefinition.js +121 -46
- package/rules/file/strictMacroDefinition.js.map +1 -1
- package/rules/line/noBannedStrings.js +1 -1
- package/rules/line/noBannedStrings.js.map +1 -1
- package/rules/line/noEncodedPasswords.js +1 -1
- package/rules/line/noEncodedPasswords.js.map +1 -1
- package/rules/line/noGremlins.js +1 -1
- package/rules/line/noGremlins.js.map +1 -1
- package/rules/line/noTabs.js +1 -1
- package/sasjslint-schema.json +17 -0
- package/types/Diagnostic.d.ts +5 -0
- package/types/LintConfig.js +6 -0
- package/types/LintConfig.js.map +1 -1
- package/utils/escapeRegExp.d.ts +2 -0
- package/utils/escapeRegExp.js +7 -0
- package/utils/escapeRegExp.js.map +1 -0
- package/utils/getColumnNumber.d.ts +14 -1
- package/utils/getColumnNumber.js +20 -3
- package/utils/getColumnNumber.js.map +1 -1
- package/utils/getLintConfig.d.ts +1 -0
- package/utils/getLintConfig.js +1 -0
- package/utils/getLintConfig.js.map +1 -1
- package/utils/index.d.ts +1 -0
- package/utils/index.js +1 -0
- package/utils/index.js.map +1 -1
- package/utils/parseMacros.js +45 -20
- package/utils/parseMacros.js.map +1 -1
- package/utils/trimComments.d.ts +21 -1
- package/utils/trimComments.js +52 -30
- package/utils/trimComments.js.map +1 -1
package/utils/parseMacros.js
CHANGED
|
@@ -3,10 +3,32 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.parseMacros = void 0;
|
|
4
4
|
const trimComments_1 = require("./trimComments");
|
|
5
5
|
const splitLines_1 = require("./splitLines");
|
|
6
|
+
/** The `%macro` statement, in any capitalisation. */
|
|
7
|
+
const macroStatement = /^%macro\b/i;
|
|
8
|
+
/** The `%mend` statement, in any capitalisation. */
|
|
9
|
+
const mendStatement = /^%mend\b/i;
|
|
10
|
+
/**
|
|
11
|
+
* The name in a `%macro` declaration, as written.
|
|
12
|
+
*
|
|
13
|
+
* The name runs to the first character that cannot belong to it: whitespace, an
|
|
14
|
+
* opening parenthesis, the `/` that introduces the options, or an end of
|
|
15
|
+
* statement. Reading it by pattern rather than from a fixed offset is what makes
|
|
16
|
+
* `%MACRO`, `%macro s` and `%macro\ts` yield the same name - the keyword and the
|
|
17
|
+
* whitespace before the name can each be a different length.
|
|
18
|
+
*/
|
|
19
|
+
const declarationName = /^%macro\b\s*([^\s(;/]*)/i;
|
|
20
|
+
/** The name in a `%mend` statement, as written. */
|
|
21
|
+
const mendName = /^%mend\b\s*([^\s;]*)/i;
|
|
22
|
+
/** The name a macro statement carries, or an empty string when it has none. */
|
|
23
|
+
const getName = (statement, pattern) => {
|
|
24
|
+
const match = pattern.exec(statement);
|
|
25
|
+
return match ? match[1].trim() : '';
|
|
26
|
+
};
|
|
6
27
|
const parseMacros = (text, config) => {
|
|
7
28
|
const lines = (0, splitLines_1.splitLines)(text);
|
|
8
29
|
const macros = [];
|
|
9
30
|
let isCommentStarted = false;
|
|
31
|
+
let isQuoteStarted = '';
|
|
10
32
|
let macroStack = [];
|
|
11
33
|
let isReadingMacroDefinition = false;
|
|
12
34
|
let isStatementContinues = true;
|
|
@@ -14,8 +36,14 @@ const parseMacros = (text, config) => {
|
|
|
14
36
|
let tempMacroDeclarationLines = [];
|
|
15
37
|
let tempStartLineNumbers = [];
|
|
16
38
|
lines.forEach((line, lineIndex) => {
|
|
17
|
-
|
|
18
|
-
|
|
39
|
+
// The state a line STARTS in belongs to the line's statements, and the state
|
|
40
|
+
// it ENDS in belongs to the next line. Reading the second into the statement
|
|
41
|
+
// loop swallowed the code that precedes a comment opening mid-line
|
|
42
|
+
// (sasjs/lint#274).
|
|
43
|
+
const stateBeforeLine = isCommentStarted;
|
|
44
|
+
const { statement: trimmedLine, commentStarted: stateAfterLine, quoteStarted: quoteAfterLine } = (0, trimComments_1.trimComments)(line, stateBeforeLine, false, isQuoteStarted);
|
|
45
|
+
isCommentStarted = stateAfterLine;
|
|
46
|
+
isQuoteStarted = quoteAfterLine;
|
|
19
47
|
isStatementContinues = !trimmedLine.endsWith(';');
|
|
20
48
|
const statements = trimmedLine.split(';');
|
|
21
49
|
if (isReadingMacroDefinition) {
|
|
@@ -31,8 +59,11 @@ const parseMacros = (text, config) => {
|
|
|
31
59
|
});
|
|
32
60
|
}
|
|
33
61
|
statements.forEach((statement, statementIndex) => {
|
|
34
|
-
|
|
35
|
-
|
|
62
|
+
// The statements were split from the line's ALREADY trimmed text, so they
|
|
63
|
+
// carry no comment and no quoted value: trimming them again either swallowed
|
|
64
|
+
// the code after a comment that closes at the start of the line (`... */
|
|
65
|
+
// %macro foo;`) or re-read a `/*` inside a multi-line string as a comment.
|
|
66
|
+
const trimmedStatement = statement.trim();
|
|
36
67
|
if (isReadingMacroDefinition) {
|
|
37
68
|
tempMacroDeclaration =
|
|
38
69
|
tempMacroDeclaration +
|
|
@@ -41,12 +72,7 @@ const parseMacros = (text, config) => {
|
|
|
41
72
|
tempStartLineNumbers.push(lineIndex + 1);
|
|
42
73
|
if (!Object.is(statements.length - 1, statementIndex)) {
|
|
43
74
|
isReadingMacroDefinition = false;
|
|
44
|
-
const name = tempMacroDeclaration
|
|
45
|
-
.slice(7, tempMacroDeclaration.length)
|
|
46
|
-
.trim()
|
|
47
|
-
.split('/')[0]
|
|
48
|
-
.split('(')[0]
|
|
49
|
-
.trim();
|
|
75
|
+
const name = getName(tempMacroDeclaration, declarationName);
|
|
50
76
|
macroStack.push({
|
|
51
77
|
name,
|
|
52
78
|
startLineNumbers: tempStartLineNumbers,
|
|
@@ -63,7 +89,7 @@ const parseMacros = (text, config) => {
|
|
|
63
89
|
});
|
|
64
90
|
}
|
|
65
91
|
}
|
|
66
|
-
if (
|
|
92
|
+
if (macroStatement.test(trimmedStatement)) {
|
|
67
93
|
const startLineNumber = lineIndex + 1;
|
|
68
94
|
if (isStatementContinues &&
|
|
69
95
|
Object.is(statements.length - 1, statementIndex)) {
|
|
@@ -73,12 +99,7 @@ const parseMacros = (text, config) => {
|
|
|
73
99
|
isReadingMacroDefinition = true;
|
|
74
100
|
return;
|
|
75
101
|
}
|
|
76
|
-
const name = trimmedStatement
|
|
77
|
-
.slice(7, trimmedStatement.length)
|
|
78
|
-
.trim()
|
|
79
|
-
.split('/')[0]
|
|
80
|
-
.split('(')[0]
|
|
81
|
-
.trim();
|
|
102
|
+
const name = getName(trimmedStatement, declarationName);
|
|
82
103
|
macroStack.push({
|
|
83
104
|
name,
|
|
84
105
|
startLineNumbers: [startLineNumber],
|
|
@@ -94,12 +115,16 @@ const parseMacros = (text, config) => {
|
|
|
94
115
|
termination: ''
|
|
95
116
|
});
|
|
96
117
|
}
|
|
97
|
-
else if (
|
|
118
|
+
else if (mendStatement.test(trimmedStatement)) {
|
|
98
119
|
if (macroStack.length) {
|
|
99
120
|
const macro = macroStack.pop();
|
|
100
|
-
const mendMacroName = trimmedStatement
|
|
121
|
+
const mendMacroName = getName(trimmedStatement, mendName);
|
|
101
122
|
macro.endLineNumber = lineIndex + 1;
|
|
102
|
-
|
|
123
|
+
// SAS matches a macro name without regard to case, so `%mend s` closes
|
|
124
|
+
// `%macro S()`. The name is kept as written for the rules that point at
|
|
125
|
+
// it, and only the comparison folds the case.
|
|
126
|
+
macro.hasMacroNameInMend =
|
|
127
|
+
mendMacroName.toLowerCase() === macro.name.toLowerCase();
|
|
103
128
|
macro.mismatchedMendMacroName = macro.hasMacroNameInMend
|
|
104
129
|
? ''
|
|
105
130
|
: mendMacroName;
|
package/utils/parseMacros.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parseMacros.js","sourceRoot":"","sources":["../../src/utils/parseMacros.ts"],"names":[],"mappings":";;;AACA,iDAA6C;AAC7C,6CAAyC;
|
|
1
|
+
{"version":3,"file":"parseMacros.js","sourceRoot":"","sources":["../../src/utils/parseMacros.ts"],"names":[],"mappings":";;;AACA,iDAA6C;AAC7C,6CAAyC;AAEzC,qDAAqD;AACrD,MAAM,cAAc,GAAG,YAAY,CAAA;AACnC,oDAAoD;AACpD,MAAM,aAAa,GAAG,WAAW,CAAA;AACjC;;;;;;;;GAQG;AACH,MAAM,eAAe,GAAG,0BAA0B,CAAA;AAClD,mDAAmD;AACnD,MAAM,QAAQ,GAAG,uBAAuB,CAAA;AAExC,+EAA+E;AAC/E,MAAM,OAAO,GAAG,CAAC,SAAiB,EAAE,OAAe,EAAU,EAAE;IAC7D,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;IAErC,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;AACrC,CAAC,CAAA;AAEM,MAAM,WAAW,GAAG,CAAC,IAAY,EAAE,MAAmB,EAAW,EAAE;IACxE,MAAM,KAAK,GAAG,IAAA,uBAAU,EAAC,IAAI,CAAC,CAAA;IAC9B,MAAM,MAAM,GAAY,EAAE,CAAA;IAE1B,IAAI,gBAAgB,GAAG,KAAK,CAAA;IAC5B,IAAI,cAAc,GAAG,EAAE,CAAA;IACvB,IAAI,UAAU,GAAY,EAAE,CAAA;IAC5B,IAAI,wBAAwB,GAAG,KAAK,CAAA;IACpC,IAAI,oBAAoB,GAAG,IAAI,CAAA;IAC/B,IAAI,oBAAoB,GAAG,EAAE,CAAA;IAC7B,IAAI,yBAAyB,GAAa,EAAE,CAAA;IAC5C,IAAI,oBAAoB,GAAa,EAAE,CAAA;IACvC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE;QAChC,6EAA6E;QAC7E,6EAA6E;QAC7E,mEAAmE;QACnE,oBAAoB;QACpB,MAAM,eAAe,GAAG,gBAAgB,CAAA;QACxC,MAAM,EACJ,SAAS,EAAE,WAAW,EACtB,cAAc,EAAE,cAAc,EAC9B,YAAY,EAAE,cAAc,EAC7B,GAAG,IAAA,2BAAY,EAAC,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,cAAc,CAAC,CAAA;QAC9D,gBAAgB,GAAG,cAAc,CAAA;QACjC,cAAc,GAAG,cAAc,CAAA;QAE/B,oBAAoB,GAAG,CAAC,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAA;QAEjD,MAAM,UAAU,GAAa,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QAEnD,IAAI,wBAAwB,EAAE,CAAC;YAC7B,6FAA6F;YAC7F,iDAAiD;YACjD,UAAU,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,cAAc,EAAE,EAAE;gBAC/C,IAAI,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;oBACnC,MAAM,IAAI,GAAG,UAAU,CAAC,cAAc,CAAC,CAAA;oBACvC,MAAM,gBAAgB,GAAG,GAAG,SAAS,IACnC,UAAU,CAAC,cAAc,GAAG,CAAC,CAC/B,EAAE,CAAA;oBACF,UAAU,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC,EAAE,gBAAgB,CAAC,CAAA;oBACtD,UAAU,CAAC,MAAM,CAAC,cAAc,GAAG,CAAC,EAAE,CAAC,CAAC,CAAA;gBAC1C,CAAC;YACH,CAAC,CAAC,CAAA;QACJ,CAAC;QAED,UAAU,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,cAAc,EAAE,EAAE;YAC/C,0EAA0E;YAC1E,6EAA6E;YAC7E,yEAAyE;YACzE,2EAA2E;YAC3E,MAAM,gBAAgB,GAAG,SAAS,CAAC,IAAI,EAAE,CAAA;YAEzC,IAAI,wBAAwB,EAAE,CAAC;gBAC7B,oBAAoB;oBAClB,oBAAoB;wBACpB,CAAC,gBAAgB,CAAC,CAAC,CAAC,GAAG,GAAG,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;gBAClD,yBAAyB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;gBACpC,oBAAoB,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAA;gBAExC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,cAAc,CAAC,EAAE,CAAC;oBACtD,wBAAwB,GAAG,KAAK,CAAA;oBAEhC,MAAM,IAAI,GAAG,OAAO,CAAC,oBAAoB,EAAE,eAAe,CAAC,CAAA;oBAC3D,UAAU,CAAC,IAAI,CAAC;wBACd,IAAI;wBACJ,gBAAgB,EAAE,oBAAoB;wBACtC,aAAa,EAAE,IAAI;wBACnB,WAAW,EAAE,UAAU,CAAC,MAAM;4BAC5B,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI;4BACxC,CAAC,CAAC,EAAE;wBACN,kBAAkB,EAAE,KAAK;wBACzB,uBAAuB,EAAE,EAAE;wBAC3B,gBAAgB,EAAE,yBAAyB;wBAC3C,eAAe,EAAE,EAAE;wBACnB,WAAW,EAAE,oBAAoB;wBACjC,WAAW,EAAE,EAAE;qBAChB,CAAC,CAAA;gBACJ,CAAC;YACH,CAAC;YAED,IAAI,cAAc,CAAC,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC;gBAC1C,MAAM,eAAe,GAAG,SAAS,GAAG,CAAC,CAAA;gBAErC,IACE,oBAAoB;oBACpB,MAAM,CAAC,EAAE,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,cAAc,CAAC,EAChD,CAAC;oBACD,oBAAoB,GAAG,gBAAgB,CAAA;oBACvC,yBAAyB,GAAG,CAAC,IAAI,CAAC,CAAA;oBAClC,oBAAoB,GAAG,CAAC,eAAe,CAAC,CAAA;oBACxC,wBAAwB,GAAG,IAAI,CAAA;oBAC/B,OAAM;gBACR,CAAC;gBAED,MAAM,IAAI,GAAG,OAAO,CAAC,gBAAgB,EAAE,eAAe,CAAC,CAAA;gBACvD,UAAU,CAAC,IAAI,CAAC;oBACd,IAAI;oBACJ,gBAAgB,EAAE,CAAC,eAAe,CAAC;oBACnC,aAAa,EAAE,IAAI;oBACnB,WAAW,EAAE,UAAU,CAAC,MAAM;wBAC5B,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI;wBACxC,CAAC,CAAC,EAAE;oBACN,kBAAkB,EAAE,KAAK;oBACzB,uBAAuB,EAAE,EAAE;oBAC3B,gBAAgB,EAAE,CAAC,IAAI,CAAC;oBACxB,eAAe,EAAE,EAAE;oBACnB,WAAW,EAAE,gBAAgB;oBAC7B,WAAW,EAAE,EAAE;iBAChB,CAAC,CAAA;YACJ,CAAC;iBAAM,IAAI,aAAa,CAAC,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC;gBAChD,IAAI,UAAU,CAAC,MAAM,EAAE,CAAC;oBACtB,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAW,CAAA;oBACvC,MAAM,aAAa,GAAG,OAAO,CAAC,gBAAgB,EAAE,QAAQ,CAAC,CAAA;oBACzD,KAAK,CAAC,aAAa,GAAG,SAAS,GAAG,CAAC,CAAA;oBACnC,uEAAuE;oBACvE,wEAAwE;oBACxE,8CAA8C;oBAC9C,KAAK,CAAC,kBAAkB;wBACtB,aAAa,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,CAAA;oBAC1D,KAAK,CAAC,uBAAuB,GAAG,KAAK,CAAC,kBAAkB;wBACtD,CAAC,CAAC,EAAE;wBACJ,CAAC,CAAC,aAAa,CAAA;oBACjB,KAAK,CAAC,eAAe,GAAG,IAAI,CAAA;oBAC5B,KAAK,CAAC,WAAW,GAAG,gBAAgB,CAAA;oBACpC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;gBACpB,CAAC;qBAAM,CAAC;oBACN,MAAM,CAAC,IAAI,CAAC;wBACV,IAAI,EAAE,EAAE;wBACR,gBAAgB,EAAE,EAAE;wBACpB,aAAa,EAAE,SAAS,GAAG,CAAC;wBAC5B,WAAW,EAAE,EAAE;wBACf,kBAAkB,EAAE,KAAK;wBACzB,uBAAuB,EAAE,EAAE;wBAC3B,gBAAgB,EAAE,EAAE;wBACpB,eAAe,EAAE,IAAI;wBACrB,WAAW,EAAE,EAAE;wBACf,WAAW,EAAE,gBAAgB;qBAC9B,CAAC,CAAA;gBACJ,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,MAAM,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,CAAA;IAE1B,OAAO,MAAM,CAAA;AACf,CAAC,CAAA;AAlJY,QAAA,WAAW,eAkJvB"}
|
package/utils/trimComments.d.ts
CHANGED
|
@@ -1,4 +1,24 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Removes the block comments from a statement, or from one line of a statement.
|
|
3
|
+
*
|
|
4
|
+
* The scan tracks two states the previous implementation did not:
|
|
5
|
+
*
|
|
6
|
+
* - a quoted value, because SAS accepts both quote characters, so an opening
|
|
7
|
+
* comment marker inside a string is data rather than the start of a comment;
|
|
8
|
+
* - a comment that is still open at the end of the text, which is reported back
|
|
9
|
+
* as `commentStarted` so the caller carries it into the next line. The old
|
|
10
|
+
* implementation lost that state when the opening marker had no closing
|
|
11
|
+
* delimiter on the same line, and returned the comment's content as code
|
|
12
|
+
* (sasjs/lint#274).
|
|
13
|
+
*
|
|
14
|
+
* A quoted value is carried across lines too (`quoteStarted`), because a SAS
|
|
15
|
+
* literal really does continue onto the next physical line: measured on a live
|
|
16
|
+
* engine, `x = "ab` / `cd";` is one string and `length(x)` is 4. An UNTERMINATED
|
|
17
|
+
* quote is carried as far as the text goes, which is also what the engine does -
|
|
18
|
+
* it consumes the rest of the file as string content.
|
|
19
|
+
*/
|
|
20
|
+
export declare const trimComments: (statement: string, commentStarted?: boolean, trimEnd?: boolean, quoteStarted?: string) => {
|
|
2
21
|
statement: string;
|
|
3
22
|
commentStarted: boolean;
|
|
23
|
+
quoteStarted: string;
|
|
4
24
|
};
|
package/utils/trimComments.js
CHANGED
|
@@ -1,40 +1,62 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.trimComments = void 0;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Removes the block comments from a statement, or from one line of a statement.
|
|
6
|
+
*
|
|
7
|
+
* The scan tracks two states the previous implementation did not:
|
|
8
|
+
*
|
|
9
|
+
* - a quoted value, because SAS accepts both quote characters, so an opening
|
|
10
|
+
* comment marker inside a string is data rather than the start of a comment;
|
|
11
|
+
* - a comment that is still open at the end of the text, which is reported back
|
|
12
|
+
* as `commentStarted` so the caller carries it into the next line. The old
|
|
13
|
+
* implementation lost that state when the opening marker had no closing
|
|
14
|
+
* delimiter on the same line, and returned the comment's content as code
|
|
15
|
+
* (sasjs/lint#274).
|
|
16
|
+
*
|
|
17
|
+
* A quoted value is carried across lines too (`quoteStarted`), because a SAS
|
|
18
|
+
* literal really does continue onto the next physical line: measured on a live
|
|
19
|
+
* engine, `x = "ab` / `cd";` is one string and `length(x)` is 4. An UNTERMINATED
|
|
20
|
+
* quote is carried as far as the text goes, which is also what the engine does -
|
|
21
|
+
* it consumes the rest of the file as string content.
|
|
22
|
+
*/
|
|
23
|
+
const trimComments = (statement, commentStarted = false, trimEnd = false, quoteStarted = '') => {
|
|
24
|
+
const text = statement || '';
|
|
25
|
+
let result = '';
|
|
26
|
+
let quote = quoteStarted;
|
|
27
|
+
let inComment = commentStarted;
|
|
28
|
+
for (let index = 0; index < text.length; index++) {
|
|
29
|
+
const character = text[index];
|
|
30
|
+
if (inComment) {
|
|
31
|
+
if (character === '*' && text[index + 1] === '/') {
|
|
32
|
+
inComment = false;
|
|
33
|
+
index++;
|
|
34
|
+
}
|
|
35
|
+
continue;
|
|
15
36
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
37
|
+
if (quote) {
|
|
38
|
+
result += character;
|
|
39
|
+
if (character === quote)
|
|
40
|
+
quote = '';
|
|
41
|
+
continue;
|
|
19
42
|
}
|
|
20
|
-
|
|
21
|
-
|
|
43
|
+
if (character === "'" || character === '"') {
|
|
44
|
+
quote = character;
|
|
45
|
+
result += character;
|
|
46
|
+
continue;
|
|
22
47
|
}
|
|
48
|
+
if (character === '/' && text[index + 1] === '*') {
|
|
49
|
+
inComment = true;
|
|
50
|
+
index++;
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
result += character;
|
|
23
54
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const completeStatement = statementBeforeCommentStarts + result.statement;
|
|
30
|
-
return {
|
|
31
|
-
statement: trimEnd
|
|
32
|
-
? completeStatement.trimEnd()
|
|
33
|
-
: completeStatement.trim(),
|
|
34
|
-
commentStarted: result.commentStarted
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
return { statement: trimmed, commentStarted: false };
|
|
55
|
+
return {
|
|
56
|
+
statement: trimEnd ? result.trimEnd() : result.trim(),
|
|
57
|
+
commentStarted: inComment,
|
|
58
|
+
quoteStarted: quote
|
|
59
|
+
};
|
|
38
60
|
};
|
|
39
61
|
exports.trimComments = trimComments;
|
|
40
62
|
//# sourceMappingURL=trimComments.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trimComments.js","sourceRoot":"","sources":["../../src/utils/trimComments.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"trimComments.js","sourceRoot":"","sources":["../../src/utils/trimComments.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACI,MAAM,YAAY,GAAG,CAC1B,SAAiB,EACjB,iBAA0B,KAAK,EAC/B,UAAmB,KAAK,EACxB,eAAuB,EAAE,EAC6C,EAAE;IACxE,MAAM,IAAI,GAAG,SAAS,IAAI,EAAE,CAAA;IAC5B,IAAI,MAAM,GAAG,EAAE,CAAA;IACf,IAAI,KAAK,GAAG,YAAY,CAAA;IACxB,IAAI,SAAS,GAAG,cAAc,CAAA;IAE9B,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;QACjD,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,CAAA;QAE7B,IAAI,SAAS,EAAE,CAAC;YACd,IAAI,SAAS,KAAK,GAAG,IAAI,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;gBACjD,SAAS,GAAG,KAAK,CAAA;gBACjB,KAAK,EAAE,CAAA;YACT,CAAC;YAED,SAAQ;QACV,CAAC;QAED,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,IAAI,SAAS,CAAA;YACnB,IAAI,SAAS,KAAK,KAAK;gBAAE,KAAK,GAAG,EAAE,CAAA;YACnC,SAAQ;QACV,CAAC;QAED,IAAI,SAAS,KAAK,GAAG,IAAI,SAAS,KAAK,GAAG,EAAE,CAAC;YAC3C,KAAK,GAAG,SAAS,CAAA;YACjB,MAAM,IAAI,SAAS,CAAA;YACnB,SAAQ;QACV,CAAC;QAED,IAAI,SAAS,KAAK,GAAG,IAAI,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YACjD,SAAS,GAAG,IAAI,CAAA;YAChB,KAAK,EAAE,CAAA;YACP,SAAQ;QACV,CAAC;QAED,MAAM,IAAI,SAAS,CAAA;IACrB,CAAC;IAED,OAAO;QACL,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE;QACrD,cAAc,EAAE,SAAS;QACzB,YAAY,EAAE,KAAK;KACpB,CAAA;AACH,CAAC,CAAA;AAjDY,QAAA,YAAY,gBAiDxB"}
|