@sasjs/lint 4.3.3 → 4.5.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 CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  Our goal is to help SAS developers everywhere spend less time on code reviews, bug fixing and arguing about standards - and more time delivering extraordinary business value.
10
10
 
11
- *Note:* The SASjs project and its repositories are not affiliated with SAS Institute.
11
+ _Note:_ The SASjs project and its repositories are not affiliated with SAS Institute.
12
12
 
13
13
  # Linting
14
14
 
@@ -22,6 +22,7 @@ Configuration is via a `.sasjslint` file with the following structure (these are
22
22
  ```json
23
23
  {
24
24
  "allowedGremlins": [],
25
+ "bannedStrings": ["error ", "error:", "warning ", "warning:"],
25
26
  "defaultHeader": "/**{lineEnding} @file{lineEnding} @brief <Your brief here>{lineEnding}{lineEnding} <h4> SAS Macros </h4>{lineEnding}{lineEnding}**/",
26
27
  "hasDoxygenHeader": true,
27
28
  "hasMacroNameInMend": true,
@@ -36,8 +37,10 @@ Configuration is via a `.sasjslint` file with the following structure (these are
36
37
  "maxDataLineLength": 80,
37
38
  "maxHeaderLineLength": 80,
38
39
  "maxLineLength": 80,
40
+ "noBannedStrings": true,
39
41
  "noEncodedPasswords": true,
40
42
  "noGremlins": true,
43
+ "noNestedCommentsInHeader": true,
41
44
  "noNestedMacros": true,
42
45
  "noSingleAsteriskComments": false,
43
46
  "noSpacesInFileNames": true,
@@ -64,7 +67,7 @@ Each setting can have three states:
64
67
 
65
68
  For more details, and the default state, see the description of each rule below. It is also possible to change whether a rule returns ERROR or WARN using the `severityLevel` object.
66
69
 
67
- Configuring a non-zero return code (ERROR) is helpful when running `sasjs lint` as part of a git pre-commit hook. An example is available [here](https://github.com/sasjs/template_jobs/blob/main/.git-hooks/pre-commit).
70
+ Configuring a non-zero return code (ERROR) is helpful when running `sasjs lint` as part of a git pre-commit hook. An example is available [here](https://github.com/sasjs/template_jobs/blob/main/.git-hooks/pre-commit).
68
71
 
69
72
  ## Per-file overrides
70
73
 
@@ -91,7 +94,7 @@ One exception: `ignoreList` is evaluated before a file is read, so an entry a he
91
94
 
92
95
  ### allowedGremlins
93
96
 
94
- An array of hex codes that represents allowed gremlins (invisible / undesirable characters). To allow all gremlins, you can also set the `noGremlins` rule to `false`. The full gremlin list is [here](https://github.com/sasjs/lint/blob/main/src/utils/gremlinCharacters.ts).
97
+ An array of hex codes that represents allowed gremlins (invisible / undesirable characters). To allow all gremlins, you can also set the `noGremlins` rule to `false`. The full gremlin list is [here](https://github.com/sasjs/lint/blob/main/src/utils/gremlinCharacters.ts).
95
98
 
96
99
  Example:
97
100
 
@@ -102,6 +105,21 @@ Example:
102
105
  }
103
106
  ```
104
107
 
108
+ ### bannedStrings
109
+
110
+ An array of strings for the [`noBannedStrings`](#nobannedstrings) rule to report. Matching is case insensitive, and each entry is matched literally rather than as a regular expression, so a trailing space means what it says: `"error "` matches `error ` but not `errors`, `error_flag` or `error:`. Each default entry ends the word with the space or the colon that follows it in a log line.
111
+
112
+ The default list is `["error ", "error:", "warning ", "warning:"]`. An explicit list replaces it, so `"bannedStrings": []` reports nothing.
113
+
114
+ Example:
115
+
116
+ ```json
117
+ {
118
+ "noBannedStrings": true,
119
+ "bannedStrings": ["error ", "error:", "warning ", "warning:", "{sas001}"]
120
+ }
121
+ ```
122
+
105
123
  ### defaultHeader
106
124
 
107
125
  This isn't a rule, but a formatting setting, which applies to SAS program that do NOT begin with `/**`. It can be triggered by running `sasjs lint fix` in the SASjs CLI, or by hitting "save" when using the SASjs VS Code extension (with "formatOnSave" in place)
@@ -138,7 +156,9 @@ If creating a new value, use `{lineEnding}` instead of `\n`, eg as follows:
138
156
 
139
157
  ### hasDoxygenHeader
140
158
 
141
- The SASjs framework recommends the use of Doxygen headers for describing all types of SAS program. This check will identify files where a doxygen header does not begin in the first line.
159
+ The SASjs framework recommends the use of Doxygen headers for describing all types of SAS program. This check identifies files where a Doxygen header does not begin on the first line, where it opens with a single asterisk, and where it closes with one.
160
+
161
+ The closing half matters beyond style. This rule set and `sasjs compile` both locate the header's end by its `**/` terminator, so a header closed with a plain `*/` has no end they can find - a comment inside such a header can truncate it without being reported by [`noNestedCommentsInHeader`](#nonestedcommentsinheader). The fix widens the close marker to `**/`, which puts the header back where that check can see it. A header whose body already holds a comment opener is left alone: the first close marker may belong to that comment, and that decision belongs to the author.
142
162
 
143
163
  - Default: true
144
164
  - Severity: WARNING
@@ -165,6 +185,7 @@ This will require macros to have the options listed as "requiredMacroOptions." T
165
185
  - severity: WARNING
166
186
 
167
187
  Example
188
+
168
189
  ```json
169
190
  {
170
191
  "hasRequiredMacroOptions": true,
@@ -294,6 +315,29 @@ See also:
294
315
  - [maxDataLineLength](#maxdatalinelength)
295
316
  - [maxHeaderLineLength](#maxheaderlinelength)
296
317
 
318
+ ### noBannedStrings
319
+
320
+ Reports every line that contains one of the strings in [`bannedStrings`](#bannedstrings), anywhere in the line - in a comment, in a string literal, or in code, because the text is read the way a person or a log scanner reads it rather than as SAS tokens.
321
+
322
+ The point is the log. A comment such as `/* returns the error message as text */` contains `error `, and so does a real `ERROR:` line, so a grep of the SAS log - and any log scanner built on one, including the checks people run before they look at a job - returns the comment along with the failure. The same applies to a `%put` that copies a sentence out of the documentation. Keeping those words out of the source means a match in the log is a message that came from somewhere real.
323
+
324
+ Three boundaries are deliberate. The line that carries a `@sasjslint` override is configuration rather than prose, so a file that adds a banned string does not report its own setting. Source data is left alone: a `datalines` payload may hold the text `error ` in a value, and that is data rather than something a developer can reword. And matching is case insensitive, so `Error`, `ERROR` and `error` are the same banned string; the diagnostic quotes the text as written. There is no setting to make it case sensitive: the words being caught are log lookalikes, and the log does not preserve the case an author typed either.
325
+
326
+ The entry is matched as text, so it is not anchored to a word boundary. `saserror = 1` therefore satisfies `"error "`, because the identifier ends with the word and the space before the `=` is the trailing space the entry asks for. Listing `"error "` is what keeps `errors` and `error_flag` out, and every default entry is written the same way for that reason.
327
+
328
+ The rule is a warning by default. A single file can switch it off or downgrade it with a `@sasjslint` block in its header, which is the usual way to keep a legacy program out of scope:
329
+
330
+ ```sas
331
+ /**
332
+ @file
333
+ @brief Legacy job, comments left as written
334
+ @sasjslint {"noBannedStrings": false}
335
+ **/
336
+ ```
337
+
338
+ - Default: true
339
+ - Severity: WARNING
340
+
297
341
  ### noEncodedPasswords
298
342
 
299
343
  This rule will highlight any rows that contain a `{sas00X}` type password, or `{sasenc}`. These passwords (especially 001 and 002) are NOT secure, and should NEVER be pushed to source control or saved to the filesystem without special permissions applied.
@@ -310,6 +354,17 @@ The list of characters can be found in this file: [https://github.com/sasjs/lint
310
354
  - Default: true
311
355
  - Severity: WARNING
312
356
 
357
+ ### noNestedCommentsInHeader
358
+
359
+ A doxygen header is a SAS block comment, and SAS block comments do not nest: the first close marker ends the comment. A `/* ... */` inside the header therefore closes the header early, and the rest of it - `@param` lines, and any code in a usage example - is compiled as SAS. Header text that holds `/*/`, such as a glob like `src/*/file.sas`, ends the header the same way.
360
+
361
+ This rule reports such a header as a warning. `sasjs compile` fails on the truncation (sasjs/utils#288), so the rule surfaces it in the editor rather than in the build; set `severityLevel` to `error` to make `sasjs lint` fail on it as well.
362
+
363
+ Two boundaries are deliberate. Only the header a file opens with is inspected, which is the one `sasjs compile` reads - a file that opens with code has no header to truncate, and `hasDoxygenHeader` covers that shape. And the header's end is identified by its `**/` terminator standing alone on its line, so a header closed with a plain `*/` is not inspected: nothing there says the header was meant to continue. [`hasDoxygenHeader`](#hasdoxygenheader) reports that closing style and its fix writes the `**/` form, which is what puts the header back in view here. The same bound has one cost worth knowing: a truncated header whose own text holds a line-leading `/**` is not reported, because that opener is indistinguishable from a second header in the same file.
364
+
365
+ - Default: true
366
+ - Severity: WARNING
367
+
313
368
  ### noNestedMacros
314
369
 
315
370
  Where macros are defined inside other macros, they are recompiled every time the outer macro is invoked. Hence, it is widely considered inefficient, and bad practice, to nest macro definitions.
@@ -495,13 +550,14 @@ Contact [Allan Bowe](https://www.linkedin.com/in/allanbowe/) for further details
495
550
 
496
551
  # Further resources
497
552
 
498
- * Using the linter on terminal: https://vid.4gl.io/w/vmJspCjcBoc5QtzwZkZRvi
499
- * Longer intro to sasjs lint: https://vid.4gl.io/w/nDtkQFV1E8rtaa2BuM6U5s
500
- * CLI docs: https://cli.sasjs.io/lint
553
+ - Using the linter on terminal: https://vid.4gl.io/w/vmJspCjcBoc5QtzwZkZRvi
554
+ - Longer intro to sasjs lint: https://vid.4gl.io/w/nDtkQFV1E8rtaa2BuM6U5s
555
+ - CLI docs: https://cli.sasjs.io/lint
501
556
 
502
557
  # Contributors ✨
503
558
 
504
559
  <!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
560
+
505
561
  [![All Contributors](https://img.shields.io/badge/all_contributors-9-orange.svg?style=flat-square)](#contributors-)
506
562
  <!-- ALL-CONTRIBUTORS-BADGE:END -->
507
563
 
package/package.json CHANGED
@@ -97,7 +97,7 @@
97
97
  "@sasjs/utils": "^4.0.0",
98
98
  "ignore": "7.0.11"
99
99
  },
100
- "version": "4.3.3",
100
+ "version": "4.5.0",
101
101
  "devEngines": {
102
102
  "runtime": {
103
103
  "name": "node",
@@ -1,5 +1,2 @@
1
1
  import { FileLintRule } from '../../types/LintRule';
2
- /**
3
- * Lint rule that checks for the presence of a Doxygen header in a given file.
4
- */
5
2
  export declare const hasDoxygenHeader: FileLintRule;
@@ -6,65 +6,116 @@ const LineEndings_1 = require("../../types/LineEndings");
6
6
  const LintRuleType_1 = require("../../types/LintRuleType");
7
7
  const Severity_1 = require("../../types/Severity");
8
8
  const getLintConfig_1 = require("../../utils/getLintConfig");
9
+ const getPosition_1 = require("../../utils/getPosition");
9
10
  const name = 'hasDoxygenHeader';
10
- const description = 'Enforce the presence of a Doxygen header at the start of each file.';
11
+ const description = 'Enforce a Doxygen header at the start of each file, in the /** ... **/ form.';
11
12
  const message = 'File missing Doxygen header';
12
13
  const messageForSingleAsterisk = 'File not following Doxygen header style, use double asterisks';
13
- const test = (value, config) => {
14
+ const messageForSingleAsteriskClose = 'File not following Doxygen header style, close with double asterisks';
15
+ const CLOSE = '*/';
16
+ /**
17
+ * Finds a header that opens in the Doxygen form but closes with a single
18
+ * asterisk, which is the closer half of the same style the opening check
19
+ * enforces.
20
+ *
21
+ * A header that holds a comment opener of its own is left alone: the first
22
+ * close marker may belong to that comment rather than to the header, and that
23
+ * ambiguity belongs to the author, not to a formatter.
24
+ *
25
+ * @returns the index of the close marker to widen, or `null`.
26
+ */
27
+ const singleAsteriskClose = (value, start) => {
28
+ const close = value.indexOf(CLOSE, start + 2);
29
+ if (close === -1)
30
+ return null;
31
+ // Already closed in the Doxygen form.
32
+ if (value[close - 1] === '*')
33
+ return null;
34
+ // A comment opener before the close makes the extent ambiguous.
35
+ if (value.slice(start + 2, close).includes('/*'))
36
+ return null;
37
+ return close;
38
+ };
39
+ const diagnose = (value, config) => {
14
40
  var _a;
15
41
  const severity = (config === null || config === void 0 ? void 0 : config.severityLevel[name]) || Severity_1.Severity.Warning;
16
42
  try {
17
- const hasFileHeader = value.trimStart().startsWith('/**');
18
- if (hasFileHeader)
19
- return [];
43
+ const start = value.search(/\S/);
44
+ if (value.trimStart().startsWith('/**')) {
45
+ const close = singleAsteriskClose(value, start);
46
+ if (close === null)
47
+ return null;
48
+ const { lineNumber, columnNumber } = (0, getPosition_1.getPosition)(value, close);
49
+ return {
50
+ message: messageForSingleAsteriskClose,
51
+ lineNumber,
52
+ startColumnNumber: columnNumber,
53
+ endColumnNumber: columnNumber + 2,
54
+ severity,
55
+ close
56
+ };
57
+ }
20
58
  const hasFileHeaderWithSingleAsterisk = value.trimStart().startsWith('/*');
21
59
  if (hasFileHeaderWithSingleAsterisk)
22
- return [
23
- {
24
- message: messageForSingleAsterisk,
25
- lineNumber: ((_a = value.split('/*')[0].match(/\r\n|\n/g)) !== null && _a !== void 0 ? _a : []).length + 1,
26
- startColumnNumber: 1,
27
- endColumnNumber: 1,
28
- severity
29
- }
30
- ];
31
- return [
32
- {
33
- message,
34
- lineNumber: 1,
60
+ return {
61
+ message: messageForSingleAsterisk,
62
+ lineNumber: ((_a = value.split('/*')[0].match(/\r\n|\n/g)) !== null && _a !== void 0 ? _a : []).length + 1,
35
63
  startColumnNumber: 1,
36
64
  endColumnNumber: 1,
37
- severity
38
- }
39
- ];
65
+ severity,
66
+ close: -1
67
+ };
68
+ return {
69
+ message,
70
+ lineNumber: 1,
71
+ startColumnNumber: 1,
72
+ endColumnNumber: 1,
73
+ severity,
74
+ close: -1
75
+ };
40
76
  }
41
77
  catch (e) {
42
- return [
43
- {
44
- message,
45
- lineNumber: 1,
46
- startColumnNumber: 1,
47
- endColumnNumber: 1,
48
- severity
49
- }
50
- ];
78
+ return {
79
+ message,
80
+ lineNumber: 1,
81
+ startColumnNumber: 1,
82
+ endColumnNumber: 1,
83
+ severity,
84
+ close: -1
85
+ };
51
86
  }
52
87
  };
88
+ const test = (value, config) => {
89
+ const diagnosis = diagnose(value, config);
90
+ if (!diagnosis)
91
+ return [];
92
+ return [
93
+ {
94
+ message: diagnosis.message,
95
+ lineNumber: diagnosis.lineNumber,
96
+ startColumnNumber: diagnosis.startColumnNumber,
97
+ endColumnNumber: diagnosis.endColumnNumber,
98
+ severity: diagnosis.severity
99
+ }
100
+ ];
101
+ };
53
102
  const fix = (value, config) => {
54
- const result = test(value, config);
55
- if (result.length === 0) {
103
+ const diagnosis = diagnose(value, config);
104
+ if (!diagnosis)
56
105
  return value;
57
- }
58
- else if (result[0].message == messageForSingleAsterisk)
106
+ if (diagnosis.message == messageForSingleAsterisk)
59
107
  return value.replace('/*', '/**');
108
+ if (diagnosis.message == messageForSingleAsteriskClose)
109
+ return `${value.slice(0, diagnosis.close)}*${value.slice(diagnosis.close)}`;
60
110
  config = config || new types_1.LintConfig(getLintConfig_1.DefaultLintConfiguration);
61
111
  const lineEndingConfig = (config === null || config === void 0 ? void 0 : config.lineEndings) || LineEndings_1.LineEndings.LF;
62
112
  const lineEnding = lineEndingConfig === LineEndings_1.LineEndings.LF ? '\n' : '\r\n';
63
113
  return `${config === null || config === void 0 ? void 0 : config.defaultHeader.replace(/{lineEnding}/g, lineEnding)}${lineEnding}${value}`;
64
114
  };
65
- /**
66
- * Lint rule that checks for the presence of a Doxygen header in a given file.
67
- */
115
+ // Lint rule that checks for a Doxygen header in the double-asterisk form at the
116
+ // start of a given file: the opening check, the closing check, and the fix that
117
+ // widens a single-asterisk close so the truncation rule can locate the header's
118
+ // end.
68
119
  exports.hasDoxygenHeader = {
69
120
  type: LintRuleType_1.LintRuleType.File,
70
121
  name,
@@ -1 +1 @@
1
- {"version":3,"file":"hasDoxygenHeader.js","sourceRoot":"","sources":["../../../src/rules/file/hasDoxygenHeader.ts"],"names":[],"mappings":";;;AAAA,uCAAwC;AACxC,yDAAqD;AAErD,2DAAuD;AACvD,mDAA+C;AAC/C,6DAAoE;AAEpE,MAAM,IAAI,GAAG,kBAAkB,CAAA;AAC/B,MAAM,WAAW,GACf,qEAAqE,CAAA;AACvE,MAAM,OAAO,GAAG,6BAA6B,CAAA;AAC7C,MAAM,wBAAwB,GAC5B,+DAA+D,CAAA;AAEjE,MAAM,IAAI,GAAG,CAAC,KAAa,EAAE,MAAmB,EAAE,EAAE;;IAClD,MAAM,QAAQ,GAAG,CAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,aAAa,CAAC,IAAI,CAAC,KAAI,mBAAQ,CAAC,OAAO,CAAA;IAEhE,IAAI,CAAC;QACH,MAAM,aAAa,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;QACzD,IAAI,aAAa;YAAE,OAAO,EAAE,CAAA;QAE5B,MAAM,+BAA+B,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;QAC1E,IAAI,+BAA+B;YACjC,OAAO;gBACL;oBACE,OAAO,EAAE,wBAAwB;oBACjC,UAAU,EACR,CAAC,MAAA,KAAK,CAAC,KAAK,CAAC,IAAI,CAAE,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC,UAAU,CAAC,mCAAI,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC;oBAC7D,iBAAiB,EAAE,CAAC;oBACpB,eAAe,EAAE,CAAC;oBAClB,QAAQ;iBACT;aACF,CAAA;QAEH,OAAO;YACL;gBACE,OAAO;gBACP,UAAU,EAAE,CAAC;gBACb,iBAAiB,EAAE,CAAC;gBACpB,eAAe,EAAE,CAAC;gBAClB,QAAQ;aACT;SACF,CAAA;IACH,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO;YACL;gBACE,OAAO;gBACP,UAAU,EAAE,CAAC;gBACb,iBAAiB,EAAE,CAAC;gBACpB,eAAe,EAAE,CAAC;gBAClB,QAAQ;aACT;SACF,CAAA;IACH,CAAC;AACH,CAAC,CAAA;AAED,MAAM,GAAG,GAAG,CAAC,KAAa,EAAE,MAAmB,EAAU,EAAE;IACzD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;IAClC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,KAAK,CAAA;IACd,CAAC;SAAM,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,IAAI,wBAAwB;QACtD,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IAEnC,MAAM,GAAG,MAAM,IAAI,IAAI,kBAAU,CAAC,wCAAwB,CAAC,CAAA;IAC3D,MAAM,gBAAgB,GAAG,CAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,WAAW,KAAI,yBAAW,CAAC,EAAE,CAAA;IAC9D,MAAM,UAAU,GAAG,gBAAgB,KAAK,yBAAW,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAA;IAEtE,OAAO,GAAG,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,aAAa,CAAC,OAAO,CACrC,eAAe,EACf,UAAU,CACX,GAAG,UAAU,GAAG,KAAK,EAAE,CAAA;AAC1B,CAAC,CAAA;AAED;;GAEG;AACU,QAAA,gBAAgB,GAAiB;IAC5C,IAAI,EAAE,2BAAY,CAAC,IAAI;IACvB,IAAI;IACJ,WAAW;IACX,OAAO;IACP,IAAI;IACJ,GAAG;CACJ,CAAA"}
1
+ {"version":3,"file":"hasDoxygenHeader.js","sourceRoot":"","sources":["../../../src/rules/file/hasDoxygenHeader.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,7 @@ export { hasDoxygenHeader } from './hasDoxygenHeader';
2
2
  export { hasMacroNameInMend } from './hasMacroNameInMend';
3
3
  export { hasMacroParentheses } from './hasMacroParentheses';
4
4
  export { lineEndings } from './lineEndings';
5
+ export { noNestedCommentsInHeader } from './noNestedCommentsInHeader';
5
6
  export { noNestedMacros } from './noNestedMacros';
6
7
  export { noUndeclaredMacros } from './noUndeclaredMacros';
7
8
  export { noUnusedMacros } from './noUnusedMacros';
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.noSingleAsteriskComments = exports.hasRequiredMacroOptions = exports.strictMacroDefinition = exports.noUnusedLibnames = exports.noUnusedMacros = exports.noUndeclaredMacros = exports.noNestedMacros = exports.lineEndings = exports.hasMacroParentheses = exports.hasMacroNameInMend = exports.hasDoxygenHeader = void 0;
3
+ exports.noSingleAsteriskComments = exports.hasRequiredMacroOptions = exports.strictMacroDefinition = exports.noUnusedLibnames = exports.noUnusedMacros = exports.noUndeclaredMacros = exports.noNestedMacros = exports.noNestedCommentsInHeader = exports.lineEndings = exports.hasMacroParentheses = exports.hasMacroNameInMend = exports.hasDoxygenHeader = void 0;
4
4
  var hasDoxygenHeader_1 = require("./hasDoxygenHeader");
5
5
  Object.defineProperty(exports, "hasDoxygenHeader", { enumerable: true, get: function () { return hasDoxygenHeader_1.hasDoxygenHeader; } });
6
6
  var hasMacroNameInMend_1 = require("./hasMacroNameInMend");
@@ -9,6 +9,8 @@ var hasMacroParentheses_1 = require("./hasMacroParentheses");
9
9
  Object.defineProperty(exports, "hasMacroParentheses", { enumerable: true, get: function () { return hasMacroParentheses_1.hasMacroParentheses; } });
10
10
  var lineEndings_1 = require("./lineEndings");
11
11
  Object.defineProperty(exports, "lineEndings", { enumerable: true, get: function () { return lineEndings_1.lineEndings; } });
12
+ var noNestedCommentsInHeader_1 = require("./noNestedCommentsInHeader");
13
+ Object.defineProperty(exports, "noNestedCommentsInHeader", { enumerable: true, get: function () { return noNestedCommentsInHeader_1.noNestedCommentsInHeader; } });
12
14
  var noNestedMacros_1 = require("./noNestedMacros");
13
15
  Object.defineProperty(exports, "noNestedMacros", { enumerable: true, get: function () { return noNestedMacros_1.noNestedMacros; } });
14
16
  var noUndeclaredMacros_1 = require("./noUndeclaredMacros");
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/rules/file/index.ts"],"names":[],"mappings":";;;AAAA,uDAAqD;AAA5C,oHAAA,gBAAgB,OAAA;AACzB,2DAAyD;AAAhD,wHAAA,kBAAkB,OAAA;AAC3B,6DAA2D;AAAlD,0HAAA,mBAAmB,OAAA;AAC5B,6CAA2C;AAAlC,0GAAA,WAAW,OAAA;AACpB,mDAAiD;AAAxC,gHAAA,cAAc,OAAA;AACvB,2DAAyD;AAAhD,wHAAA,kBAAkB,OAAA;AAC3B,mDAAiD;AAAxC,gHAAA,cAAc,OAAA;AACvB,uDAAqD;AAA5C,oHAAA,gBAAgB,OAAA;AACzB,iEAA+D;AAAtD,8HAAA,qBAAqB,OAAA;AAC9B,qEAAmE;AAA1D,kIAAA,uBAAuB,OAAA;AAChC,uEAAqE;AAA5D,oIAAA,wBAAwB,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/rules/file/index.ts"],"names":[],"mappings":";;;AAAA,uDAAqD;AAA5C,oHAAA,gBAAgB,OAAA;AACzB,2DAAyD;AAAhD,wHAAA,kBAAkB,OAAA;AAC3B,6DAA2D;AAAlD,0HAAA,mBAAmB,OAAA;AAC5B,6CAA2C;AAAlC,0GAAA,WAAW,OAAA;AACpB,uEAAqE;AAA5D,oIAAA,wBAAwB,OAAA;AACjC,mDAAiD;AAAxC,gHAAA,cAAc,OAAA;AACvB,2DAAyD;AAAhD,wHAAA,kBAAkB,OAAA;AAC3B,mDAAiD;AAAxC,gHAAA,cAAc,OAAA;AACvB,uDAAqD;AAA5C,oHAAA,gBAAgB,OAAA;AACzB,iEAA+D;AAAtD,8HAAA,qBAAqB,OAAA;AAC9B,qEAAmE;AAA1D,kIAAA,uBAAuB,OAAA;AAChC,uEAAqE;AAA5D,oIAAA,wBAAwB,OAAA"}
@@ -0,0 +1,6 @@
1
+ import { FileLintRule } from '../../types/LintRule';
2
+ /**
3
+ * Lint rule that flags a close marker inside the Doxygen header, which SAS
4
+ * reads as the end of the header.
5
+ */
6
+ export declare const noNestedCommentsInHeader: FileLintRule;
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.noNestedCommentsInHeader = void 0;
4
+ const LintRuleType_1 = require("../../types/LintRuleType");
5
+ const Severity_1 = require("../../types/Severity");
6
+ const getPosition_1 = require("../../utils/getPosition");
7
+ const name = 'noNestedCommentsInHeader';
8
+ const description = 'Disallow a close marker inside the Doxygen header. SAS block comments do not nest and end at the first close marker, so anything after one in the header is compiled as SAS. The header end is identified by its `**/` terminator standing alone on its line, so a project that closes headers with a plain close marker is not inspected.';
9
+ const message = 'Doxygen header contains a nested block comment';
10
+ const messageForTerminator = 'Doxygen header contains /*/, which SAS reads as a comment terminator';
11
+ const messageForText = 'Doxygen header contains a close marker as text';
12
+ const CLOSE = '*/';
13
+ const TERMINATOR = '**/';
14
+ const LATER_HEADER = /^[ \t]*\/\*\*/m;
15
+ // Finds the double-asterisk terminator that belongs to this header.
16
+ //
17
+ // It has to stand alone on its line, because the house style writes it that way
18
+ // and a terminator inside a statement ends that statement's comment. It also has
19
+ // to arrive before another header opens: one behind a later opener closes that
20
+ // header, not this one. A plain comment inside the same header does not
21
+ // disqualify a candidate - that comment is part of the text that leaked.
22
+ //
23
+ // The cost of the second bound: a truncated header whose own text holds a
24
+ // line-leading `/**` is not reported, because that opener is not
25
+ // distinguishable from a second header in the same file.
26
+ const ownTerminator = (value, close) => {
27
+ let candidate = value.indexOf(TERMINATOR, close - 1);
28
+ while (candidate !== -1) {
29
+ const lineStart = value.lastIndexOf('\n', candidate - 1) + 1;
30
+ const lineLeading = !value.slice(lineStart, candidate).trim();
31
+ // Another header opens before this candidate, so nothing beyond it can be
32
+ // this header's end.
33
+ if (LATER_HEADER.test(value.slice(close + 2, candidate)))
34
+ return null;
35
+ if (lineLeading)
36
+ return candidate;
37
+ candidate = value.indexOf(TERMINATOR, candidate + 1);
38
+ }
39
+ return null;
40
+ };
41
+ /**
42
+ * Finds the close marker that ends a Doxygen header early.
43
+ *
44
+ * A header is a SAS block comment, and SAS block comments do not nest: the
45
+ * first close marker ends the comment, so anything after it in the header -
46
+ * `@param` lines, code in a usage example - is compiled as SAS. The marker can
47
+ * belong to a nested comment, come straight after its opener as text, or be
48
+ * bare text.
49
+ *
50
+ * Only the header the file opens with is inspected, which is the header
51
+ * `sasjs compile` reads: a file that opens with code has no header to truncate,
52
+ * and `hasDoxygenHeader` is the rule for that shape.
53
+ *
54
+ * `@sasjs/utils` runs the same three boundaries when it strips a header at
55
+ * compile time (sasjs/utils#288): the file's opening header only, a terminator
56
+ * standing alone on its line, and no later opener in between. The two functions
57
+ * are line-for-line equivalents, so a file this rule passes does not fail the
58
+ * build on this shape and the other way round.
59
+ */
60
+ const test = (value, config) => {
61
+ const severity = (config === null || config === void 0 ? void 0 : config.severityLevel[name]) || Severity_1.Severity.Warning;
62
+ if (!value)
63
+ return [];
64
+ const start = value.search(/\S/);
65
+ if (start === -1 || !value.startsWith('/**', start))
66
+ return [];
67
+ const close = value.indexOf(CLOSE, start + 2);
68
+ if (close === -1)
69
+ return [];
70
+ const terminator = ownTerminator(value, close);
71
+ // A header that closed at its own terminator was not cut short, and one with
72
+ // no terminator carries no evidence that it was meant to continue.
73
+ if (terminator === null || terminator === close - 1)
74
+ return [];
75
+ const nestedComment = value.indexOf('/*', start + 2);
76
+ const nested = nestedComment !== -1 && nestedComment < close ? nestedComment : null;
77
+ const literalSequence = nested !== null && nested === close - 1;
78
+ const reported = nested !== null && nested !== void 0 ? nested : close;
79
+ const { lineNumber, columnNumber } = (0, getPosition_1.getPosition)(value, reported);
80
+ return [
81
+ {
82
+ message: literalSequence
83
+ ? messageForTerminator
84
+ : nested === null
85
+ ? messageForText
86
+ : message,
87
+ lineNumber,
88
+ startColumnNumber: columnNumber,
89
+ endColumnNumber: columnNumber + 2,
90
+ severity
91
+ }
92
+ ];
93
+ };
94
+ /**
95
+ * Lint rule that flags a close marker inside the Doxygen header, which SAS
96
+ * reads as the end of the header.
97
+ */
98
+ exports.noNestedCommentsInHeader = {
99
+ type: LintRuleType_1.LintRuleType.File,
100
+ name,
101
+ description,
102
+ message,
103
+ test
104
+ };
105
+ //# sourceMappingURL=noNestedCommentsInHeader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"noNestedCommentsInHeader.js","sourceRoot":"","sources":["../../../src/rules/file/noNestedCommentsInHeader.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ export { noBannedStrings } from './noBannedStrings';
1
2
  export { noGremlins } from './noGremlins';
2
3
  export { indentationMultiple } from './indentationMultiple';
3
4
  export { maxLineLength } from './maxLineLength';
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.noTrailingSpaces = exports.noTabs = exports.noEncodedPasswords = exports.maxLineLength = exports.indentationMultiple = exports.noGremlins = void 0;
3
+ exports.noTrailingSpaces = exports.noTabs = exports.noEncodedPasswords = exports.maxLineLength = exports.indentationMultiple = exports.noGremlins = exports.noBannedStrings = void 0;
4
+ var noBannedStrings_1 = require("./noBannedStrings");
5
+ Object.defineProperty(exports, "noBannedStrings", { enumerable: true, get: function () { return noBannedStrings_1.noBannedStrings; } });
4
6
  var noGremlins_1 = require("./noGremlins");
5
7
  Object.defineProperty(exports, "noGremlins", { enumerable: true, get: function () { return noGremlins_1.noGremlins; } });
6
8
  var indentationMultiple_1 = require("./indentationMultiple");
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/rules/line/index.ts"],"names":[],"mappings":";;;AAAA,2CAAyC;AAAhC,wGAAA,UAAU,OAAA;AACnB,6DAA2D;AAAlD,0HAAA,mBAAmB,OAAA;AAC5B,iDAA+C;AAAtC,8GAAA,aAAa,OAAA;AACtB,2DAAyD;AAAhD,wHAAA,kBAAkB,OAAA;AAC3B,mCAAiC;AAAxB,gGAAA,MAAM,OAAA;AACf,uDAAqD;AAA5C,oHAAA,gBAAgB,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/rules/line/index.ts"],"names":[],"mappings":";;;AAAA,qDAAmD;AAA1C,kHAAA,eAAe,OAAA;AACxB,2CAAyC;AAAhC,wGAAA,UAAU,OAAA;AACnB,6DAA2D;AAAlD,0HAAA,mBAAmB,OAAA;AAC5B,iDAA+C;AAAtC,8GAAA,aAAa,OAAA;AACtB,2DAAyD;AAAhD,wHAAA,kBAAkB,OAAA;AAC3B,mCAAiC;AAAxB,gGAAA,MAAM,OAAA;AACf,uDAAqD;AAA5C,oHAAA,gBAAgB,OAAA"}
@@ -0,0 +1,6 @@
1
+ import { LineLintRule } from '../../types/LintRule';
2
+ /**
3
+ * Lint rule that checks a given line of text for strings configured in
4
+ * `bannedStrings`.
5
+ */
6
+ export declare const noBannedStrings: LineLintRule;
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.noBannedStrings = void 0;
4
+ const LintRuleType_1 = require("../../types/LintRuleType");
5
+ const Severity_1 = require("../../types/Severity");
6
+ const utils_1 = require("../../utils");
7
+ const name = 'noBannedStrings';
8
+ const description = 'Disallow configured strings, such as words that look like log messages';
9
+ const message = 'Line contains a banned string';
10
+ /**
11
+ * Escapes a configured string so that it is matched literally. The list is
12
+ * user supplied, so `{sas001}`, `(c)` and `[x]` have to survive the trip
13
+ * through the RegExp constructor.
14
+ */
15
+ const escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
16
+ /**
17
+ * The line that carries a per-file override is configuration rather than prose.
18
+ * A file that adds a banned string writes that string in the override, so
19
+ * without this the rule reports its own configuration.
20
+ */
21
+ const overrideLine = /^[^\w]*@sasjslint\s*\{/;
22
+ const test = (value, lineNumber, config, options) => {
23
+ const diagnostics = [];
24
+ // Source data is data, not code: a `datalines` payload may legitimately hold
25
+ // the text `error ` in a value, and it is not something a developer can edit
26
+ // away without changing the data.
27
+ if (options === null || options === void 0 ? void 0 : options.isDataLine)
28
+ return diagnostics;
29
+ if (overrideLine.test(value))
30
+ return diagnostics;
31
+ const severity = (config === null || config === void 0 ? void 0 : config.severityLevel[name]) || Severity_1.Severity.Warning;
32
+ const bannedStrings = (config === null || config === void 0 ? void 0 : config.bannedStrings) || utils_1.defaultBannedStrings;
33
+ if (!bannedStrings.length)
34
+ return diagnostics;
35
+ // Longest first, so a project that lists both `error:` and `error` reports the
36
+ // more specific match rather than only the prefix of it.
37
+ const patterns = [...bannedStrings].sort((a, b) => b.length - a.length);
38
+ const claimed = new Array(value.length).fill(false);
39
+ for (const bannedString of patterns) {
40
+ // `g` to find every occurrence, `i` so that `Error`, `ERROR` and `error` are
41
+ // the same banned string - case sensitivity is opt out, not opt in.
42
+ const regex = new RegExp(escapeRegExp(bannedString), 'gi');
43
+ let match;
44
+ while ((match = regex.exec(value))) {
45
+ const start = match.index;
46
+ const end = start + match[0].length;
47
+ // A span already reported by a longer banned string is not reported again.
48
+ if (claimed.slice(start, end).some(Boolean))
49
+ continue;
50
+ for (let index = start; index < end; index++)
51
+ claimed[index] = true;
52
+ diagnostics.push({
53
+ message: `${message}: "${match[0]}"`,
54
+ lineNumber,
55
+ startColumnNumber: start + 1,
56
+ endColumnNumber: end + 1,
57
+ severity
58
+ });
59
+ }
60
+ }
61
+ return diagnostics.sort((a, b) => a.startColumnNumber - b.startColumnNumber);
62
+ };
63
+ /**
64
+ * Lint rule that checks a given line of text for strings configured in
65
+ * `bannedStrings`.
66
+ */
67
+ exports.noBannedStrings = {
68
+ type: LintRuleType_1.LintRuleType.Line,
69
+ name,
70
+ description,
71
+ message,
72
+ test
73
+ };
74
+ //# sourceMappingURL=noBannedStrings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"noBannedStrings.js","sourceRoot":"","sources":["../../../src/rules/line/noBannedStrings.ts"],"names":[],"mappings":"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"}
@@ -6,6 +6,7 @@
6
6
  "description": "The SASjs Lint Config file provides the settings for customising SAS code style in your project. A SAS file can override these settings for itself with a `@sasjslint` block in its Doxygen header.",
7
7
  "default": {
8
8
  "allowedGremlins": [],
9
+ "bannedStrings": ["error ", "error:", "warning ", "warning:"],
9
10
  "defaultHeader": "/**{lineEnding} @file{lineEnding} @brief <Your brief here>{lineEnding}{lineEnding} <h4> SAS Macros </h4>{lineEnding}{lineEnding}**/",
10
11
  "hasDoxygenHeader": true,
11
12
  "hasMacroNameInMend": true,
@@ -20,8 +21,10 @@
20
21
  "maxDataLineLength": 80,
21
22
  "maxHeaderLineLength": 80,
22
23
  "maxLineLength": 80,
24
+ "noBannedStrings": true,
23
25
  "noEncodedPasswords": true,
24
26
  "noGremlins": true,
27
+ "noNestedCommentsInHeader": true,
25
28
  "noNestedMacros": true,
26
29
  "noSingleAsteriskComments": false,
27
30
  "noSpacesInFileNames": true,
@@ -49,6 +52,7 @@
49
52
  "noTabs": true,
50
53
  "indentationMultiple": 4,
51
54
  "hasMacroNameInMend": true,
55
+ "noNestedCommentsInHeader": true,
52
56
  "noNestedMacros": true,
53
57
  "noSingleAsteriskComments": false,
54
58
  "noUndeclaredMacros": true,
@@ -63,6 +67,14 @@
63
67
  }
64
68
  ],
65
69
  "properties": {
70
+ "noBannedStrings": {
71
+ "$id": "#/properties/noBannedStrings",
72
+ "type": "boolean",
73
+ "title": "noBannedStrings",
74
+ "description": "Reports lines that contain a string listed in bannedStrings, such as a word that looks like a log message. Matching is case insensitive. Shows a warning when one is present.",
75
+ "default": true,
76
+ "examples": [true, false]
77
+ },
66
78
  "noEncodedPasswords": {
67
79
  "$id": "#/properties/noEncodedPasswords",
68
80
  "type": "boolean",
@@ -95,6 +107,21 @@
95
107
  "default": [true],
96
108
  "examples": [true, false]
97
109
  },
110
+ "bannedStrings": {
111
+ "$id": "#/properties/bannedStrings",
112
+ "type": "array",
113
+ "items": {
114
+ "type": "string",
115
+ "minLength": 1
116
+ },
117
+ "title": "bannedStrings",
118
+ "description": "An array of strings for the noBannedStrings rule to report. Matching is case insensitive, and each entry is matched literally, so a trailing space means what it says.",
119
+ "default": ["error ", "error:", "warning ", "warning:"],
120
+ "examples": [
121
+ ["error ", "error:", "warning ", "warning:"],
122
+ ["{sas001}", "TODO"]
123
+ ]
124
+ },
98
125
  "allowedGremlins": {
99
126
  "$id": "#/properties/allowedGremlins",
100
127
  "type": "array",
@@ -163,6 +190,14 @@
163
190
  "default": 80,
164
191
  "examples": [60, 80, 120]
165
192
  },
193
+ "noNestedCommentsInHeader": {
194
+ "$id": "#/properties/noNestedCommentsInHeader",
195
+ "type": "boolean",
196
+ "title": "noNestedCommentsInHeader",
197
+ "description": "Disallows a close marker inside the Doxygen header, which SAS reads as the end of the header - the rest of it is then compiled as SAS. Covers a nested block comment, a literal sequence in header text and a bare close marker. Shows a warning for such a header.",
198
+ "default": true,
199
+ "examples": [true, false]
200
+ },
166
201
  "noNestedMacros": {
167
202
  "$id": "#/properties/noNestedMacros",
168
203
  "type": "boolean",
@@ -250,7 +285,10 @@
250
285
  "title": "ignoreList",
251
286
  "description": "An array of paths or path patterns to ignore when linting. Any files or matching patterns in the .gitignore file will also be ignored.",
252
287
  "default": [],
253
- "examples": [["sasjsbuild/", "sasjsresults/"], ["sasjs/tests", "tmp/scratch.sas"]]
288
+ "examples": [
289
+ ["sasjsbuild/", "sasjsresults/"],
290
+ ["sasjs/tests", "tmp/scratch.sas"]
291
+ ]
254
292
  },
255
293
  "ignoredLibnames": {
256
294
  "$id": "#/properties/ignoredLibnames",
@@ -303,6 +341,13 @@
303
341
  }
304
342
  ],
305
343
  "properties": {
344
+ "noBannedStrings": {
345
+ "$id": "#/properties/severityLevel/noBannedStrings",
346
+ "title": "noBannedStrings",
347
+ "type": "string",
348
+ "enum": ["error", "warn"],
349
+ "default": "warn"
350
+ },
306
351
  "noEncodedPasswords": {
307
352
  "$id": "#/properties/severityLevel/noEncodedPasswords",
308
353
  "title": "noEncodedPasswords",
@@ -359,6 +404,13 @@
359
404
  "enum": ["error", "warn"],
360
405
  "default": "warn"
361
406
  },
407
+ "noNestedCommentsInHeader": {
408
+ "$id": "#/properties/severityLevel/noNestedCommentsInHeader",
409
+ "title": "noNestedCommentsInHeader",
410
+ "type": "string",
411
+ "enum": ["error", "warn"],
412
+ "default": "warn"
413
+ },
362
414
  "noNestedMacros": {
363
415
  "$id": "#/properties/severityLevel/noNestedMacros",
364
416
  "title": "noNestedMacros",
@@ -28,6 +28,7 @@ export declare class LintConfig {
28
28
  readonly requiredMacroOptions: string[];
29
29
  readonly ignoredLibnames: string[];
30
30
  readonly ignoredMacros: string[];
31
+ readonly bannedStrings: string[];
31
32
  constructor(json?: any);
32
33
  /**
33
34
  * Returns a new configuration with an override merged over this one, so a
@@ -32,6 +32,7 @@ class LintConfig {
32
32
  this.requiredMacroOptions = [];
33
33
  this.ignoredLibnames = [];
34
34
  this.ignoredMacros = [];
35
+ this.bannedStrings = [];
35
36
  this.source = json !== null && json !== void 0 ? json : {};
36
37
  if (json === null || json === void 0 ? void 0 : json.ignoreList) {
37
38
  if (Array.isArray(json.ignoreList)) {
@@ -70,6 +71,28 @@ class LintConfig {
70
71
  if ((json === null || json === void 0 ? void 0 : json.noEncodedPasswords) !== false) {
71
72
  this.lineLintRules.push(line_1.noEncodedPasswords);
72
73
  }
74
+ // The default list is seeded only when the setting is absent, so an empty
75
+ // array is an explicit "report nothing" rather than a fallback to the
76
+ // defaults - the same contract `ignoredMacros` follows.
77
+ if ((json === null || json === void 0 ? void 0 : json.bannedStrings) === undefined) {
78
+ this.bannedStrings.push(...utils_1.defaultBannedStrings);
79
+ }
80
+ else if (!Array.isArray(json.bannedStrings)) {
81
+ throw new Error(`Property "bannedStrings" can only be an array of strings.`);
82
+ }
83
+ else {
84
+ json.bannedStrings.forEach((item) => {
85
+ if (typeof item === 'string' && item.length) {
86
+ this.bannedStrings.push(item);
87
+ }
88
+ else {
89
+ throw new Error(`Property "bannedStrings" has invalid type of values. It can contain only non-empty strings.`);
90
+ }
91
+ });
92
+ }
93
+ if ((json === null || json === void 0 ? void 0 : json.noBannedStrings) !== false) {
94
+ this.lineLintRules.push(line_1.noBannedStrings);
95
+ }
73
96
  this.lineLintRules.push(line_1.noTabs);
74
97
  if ((json === null || json === void 0 ? void 0 : json.noTabs) === false || (json === null || json === void 0 ? void 0 : json.noTabIndentation) === false) {
75
98
  this.lineLintRules.pop();
@@ -115,6 +138,9 @@ class LintConfig {
115
138
  if ((json === null || json === void 0 ? void 0 : json.hasMacroNameInMend) !== false) {
116
139
  this.fileLintRules.push(file_1.hasMacroNameInMend);
117
140
  }
141
+ if ((json === null || json === void 0 ? void 0 : json.noNestedCommentsInHeader) !== false) {
142
+ this.fileLintRules.push(file_1.noNestedCommentsInHeader);
143
+ }
118
144
  if ((json === null || json === void 0 ? void 0 : json.noNestedMacros) !== false) {
119
145
  this.fileLintRules.push(file_1.noNestedMacros);
120
146
  }
@@ -210,6 +236,9 @@ class LintConfig {
210
236
  if (source.ignoredMacros === undefined) {
211
237
  source.ignoredMacros = [...this.ignoredMacros];
212
238
  }
239
+ if (source.bannedStrings === undefined) {
240
+ source.bannedStrings = [...this.bannedStrings];
241
+ }
213
242
  return new LintConfig((0, mergeLintConfig_1.mergeLintConfig)(source, json));
214
243
  }
215
244
  }
@@ -1 +1 @@
1
- {"version":3,"file":"LintConfig.js","sourceRoot":"","sources":["../../src/types/LintConfig.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"LintConfig.js","sourceRoot":"","sources":["../../src/types/LintConfig.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * The strings reported by `noBannedStrings` when a project does not configure
3
+ * its own list.
4
+ *
5
+ * These are words that look like a log message. A comment or a `%put` that
6
+ * holds one turns up in a grep of the SAS log, and in any log scanner built on
7
+ * one, so a real problem is easy to lose among the matches that were only
8
+ * prose.
9
+ *
10
+ * Each entry ends a word: `error ` and `error:` carry the space or the colon
11
+ * that follows the word in a log line. A bare `error` would also match
12
+ * `error_flag`, `errors` and `saserror`, which are ordinary identifiers rather
13
+ * than log lookalikes, so the list is built from the delimited forms.
14
+ */
15
+ export declare const defaultBannedStrings: string[];
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defaultBannedStrings = void 0;
4
+ /**
5
+ * The strings reported by `noBannedStrings` when a project does not configure
6
+ * its own list.
7
+ *
8
+ * These are words that look like a log message. A comment or a `%put` that
9
+ * holds one turns up in a grep of the SAS log, and in any log scanner built on
10
+ * one, so a real problem is easy to lose among the matches that were only
11
+ * prose.
12
+ *
13
+ * Each entry ends a word: `error ` and `error:` carry the space or the colon
14
+ * that follows the word in a log line. A bare `error` would also match
15
+ * `error_flag`, `errors` and `saserror`, which are ordinary identifiers rather
16
+ * than log lookalikes, so the list is built from the delimited forms.
17
+ */
18
+ exports.defaultBannedStrings = ['error ', 'error:', 'warning ', 'warning:'];
19
+ //# sourceMappingURL=defaultBannedStrings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaultBannedStrings.js","sourceRoot":"","sources":["../../src/utils/defaultBannedStrings.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;GAaG;AACU,QAAA,oBAAoB,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,CAAC,CAAA"}
@@ -11,6 +11,7 @@ export declare const getDefaultHeader: () => string;
11
11
  */
12
12
  export declare const DefaultLintConfiguration: {
13
13
  allowedGremlins: never[];
14
+ bannedStrings: string[];
14
15
  defaultHeader: string;
15
16
  hasDoxygenHeader: boolean;
16
17
  hasMacroNameInMend: boolean;
@@ -25,8 +26,10 @@ export declare const DefaultLintConfiguration: {
25
26
  maxDataLineLength: number;
26
27
  maxHeaderLineLength: number;
27
28
  maxLineLength: number;
29
+ noBannedStrings: boolean;
28
30
  noEncodedPasswords: boolean;
29
31
  noGremlins: boolean;
32
+ noNestedCommentsInHeader: boolean;
30
33
  noNestedMacros: boolean;
31
34
  noSingleAsteriskComments: boolean;
32
35
  noSpacesInFileNames: boolean;
@@ -20,6 +20,7 @@ const LintConfig_1 = require("../types/LintConfig");
20
20
  const file_1 = require("@sasjs/utils/file");
21
21
  const getProjectRoot_1 = require("./getProjectRoot");
22
22
  const LineEndings_1 = require("../types/LineEndings");
23
+ const defaultBannedStrings_1 = require("./defaultBannedStrings");
23
24
  const defaultIgnoredMacros_1 = require("./defaultIgnoredMacros");
24
25
  const getDefaultHeader = () => `/**{lineEnding} @file{lineEnding} @brief <Your brief here>{lineEnding}{lineEnding} <h4> SAS Macros </h4>{lineEnding}{lineEnding}**/`;
25
26
  exports.getDefaultHeader = getDefaultHeader;
@@ -33,6 +34,7 @@ exports.getDefaultHeader = getDefaultHeader;
33
34
  */
34
35
  exports.DefaultLintConfiguration = {
35
36
  allowedGremlins: [],
37
+ bannedStrings: [...defaultBannedStrings_1.defaultBannedStrings],
36
38
  defaultHeader: (0, exports.getDefaultHeader)(),
37
39
  hasDoxygenHeader: true,
38
40
  hasMacroNameInMend: true,
@@ -47,8 +49,10 @@ exports.DefaultLintConfiguration = {
47
49
  maxDataLineLength: 80,
48
50
  maxHeaderLineLength: 80,
49
51
  maxLineLength: 80,
52
+ noBannedStrings: true,
50
53
  noEncodedPasswords: true,
51
54
  noGremlins: true,
55
+ noNestedCommentsInHeader: true,
52
56
  noNestedMacros: true,
53
57
  noSingleAsteriskComments: false,
54
58
  noSpacesInFileNames: true,
@@ -1 +1 @@
1
- {"version":3,"file":"getLintConfig.js","sourceRoot":"","sources":["../../src/utils/getLintConfig.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAuDA,sCASC;AAhED,gDAAuB;AACvB,4CAAmB;AACnB,oDAAgD;AAChD,4CAA4C;AAC5C,qDAAiD;AACjD,sDAAkD;AAClD,iEAA6D;AAEtD,MAAM,gBAAgB,GAAG,GAAG,EAAE,CACnC,wIAAwI,CAAA;AAD7H,QAAA,gBAAgB,oBAC6G;AAE1I;;;;;;;GAOG;AACU,QAAA,wBAAwB,GAAG;IACtC,eAAe,EAAE,EAAE;IACnB,aAAa,EAAE,IAAA,wBAAgB,GAAE;IACjC,gBAAgB,EAAE,IAAI;IACtB,kBAAkB,EAAE,IAAI;IACxB,mBAAmB,EAAE,IAAI;IACzB,uBAAuB,EAAE,KAAK;IAC9B,UAAU,EAAE,EAAE;IACd,eAAe,EAAE,EAAE;IACnB,aAAa,EAAE,CAAC,GAAG,2CAAoB,CAAC;IACxC,mBAAmB,EAAE,CAAC;IACtB,WAAW,EAAE,yBAAW,CAAC,GAAG;IAC5B,kBAAkB,EAAE,IAAI;IACxB,iBAAiB,EAAE,EAAE;IACrB,mBAAmB,EAAE,EAAE;IACvB,aAAa,EAAE,EAAE;IACjB,kBAAkB,EAAE,IAAI;IACxB,UAAU,EAAE,IAAI;IAChB,cAAc,EAAE,IAAI;IACpB,wBAAwB,EAAE,KAAK;IAC/B,mBAAmB,EAAE,IAAI;IACzB,MAAM,EAAE,IAAI;IACZ,gBAAgB,EAAE,IAAI;IACtB,kBAAkB,EAAE,IAAI;IACxB,gBAAgB,EAAE,KAAK;IACvB,cAAc,EAAE,IAAI;IACpB,oBAAoB,EAAE,EAAE;IACxB,aAAa,EAAE,EAAE;IACjB,qBAAqB,EAAE,IAAI;CAC5B,CAAA;AAED;;;;GAIG;AACH,SAAsB,aAAa;;QACjC,MAAM,WAAW,GAAG,MAAM,IAAA,+BAAc,GAAE,CAAA;QAC1C,MAAM,gBAAgB,GAAG,WAAW,IAAI,YAAE,CAAC,OAAO,EAAE,CAAA;QACpD,MAAM,aAAa,GAAG,MAAM,IAAA,eAAQ,EAClC,cAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,YAAY,CAAC,CAC1C,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;YACZ,OAAO,IAAI,CAAC,SAAS,CAAC,gCAAwB,CAAC,CAAA;QACjD,CAAC,CAAC,CAAA;QACF,OAAO,IAAI,uBAAU,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAA;IAClD,CAAC;CAAA"}
1
+ {"version":3,"file":"getLintConfig.js","sourceRoot":"","sources":["../../src/utils/getLintConfig.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AA2DA,sCASC;AApED,gDAAuB;AACvB,4CAAmB;AACnB,oDAAgD;AAChD,4CAA4C;AAC5C,qDAAiD;AACjD,sDAAkD;AAClD,iEAA6D;AAC7D,iEAA6D;AAEtD,MAAM,gBAAgB,GAAG,GAAG,EAAE,CACnC,wIAAwI,CAAA;AAD7H,QAAA,gBAAgB,oBAC6G;AAE1I;;;;;;;GAOG;AACU,QAAA,wBAAwB,GAAG;IACtC,eAAe,EAAE,EAAE;IACnB,aAAa,EAAE,CAAC,GAAG,2CAAoB,CAAC;IACxC,aAAa,EAAE,IAAA,wBAAgB,GAAE;IACjC,gBAAgB,EAAE,IAAI;IACtB,kBAAkB,EAAE,IAAI;IACxB,mBAAmB,EAAE,IAAI;IACzB,uBAAuB,EAAE,KAAK;IAC9B,UAAU,EAAE,EAAE;IACd,eAAe,EAAE,EAAE;IACnB,aAAa,EAAE,CAAC,GAAG,2CAAoB,CAAC;IACxC,mBAAmB,EAAE,CAAC;IACtB,WAAW,EAAE,yBAAW,CAAC,GAAG;IAC5B,kBAAkB,EAAE,IAAI;IACxB,iBAAiB,EAAE,EAAE;IACrB,mBAAmB,EAAE,EAAE;IACvB,aAAa,EAAE,EAAE;IACjB,eAAe,EAAE,IAAI;IACrB,kBAAkB,EAAE,IAAI;IACxB,UAAU,EAAE,IAAI;IAChB,wBAAwB,EAAE,IAAI;IAC9B,cAAc,EAAE,IAAI;IACpB,wBAAwB,EAAE,KAAK;IAC/B,mBAAmB,EAAE,IAAI;IACzB,MAAM,EAAE,IAAI;IACZ,gBAAgB,EAAE,IAAI;IACtB,kBAAkB,EAAE,IAAI;IACxB,gBAAgB,EAAE,KAAK;IACvB,cAAc,EAAE,IAAI;IACpB,oBAAoB,EAAE,EAAE;IACxB,aAAa,EAAE,EAAE;IACjB,qBAAqB,EAAE,IAAI;CAC5B,CAAA;AAED;;;;GAIG;AACH,SAAsB,aAAa;;QACjC,MAAM,WAAW,GAAG,MAAM,IAAA,+BAAc,GAAE,CAAA;QAC1C,MAAM,gBAAgB,GAAG,WAAW,IAAI,YAAE,CAAC,OAAO,EAAE,CAAA;QACpD,MAAM,aAAa,GAAG,MAAM,IAAA,eAAQ,EAClC,cAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,YAAY,CAAC,CAC1C,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;YACZ,OAAO,IAAI,CAAC,SAAS,CAAC,gCAAwB,CAAC,CAAA;QACjD,CAAC,CAAC,CAAA;QACF,OAAO,IAAI,uBAAU,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAA;IAClD,CAAC;CAAA"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Reports the one-based line and column of a character index.
3
+ *
4
+ * The lines come from `splitLines`, so a file with either line ending reads
5
+ * correctly; a reader that splits on `\n` alone reports the wrong position for
6
+ * a CRLF file.
7
+ *
8
+ * @param {string} text - the text the index belongs to.
9
+ * @param {number} index - the index to locate.
10
+ */
11
+ export declare const getPosition: (text: string, index: number) => {
12
+ lineNumber: number;
13
+ columnNumber: number;
14
+ };
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getPosition = void 0;
4
+ const splitLines_1 = require("./splitLines");
5
+ /**
6
+ * Reports the one-based line and column of a character index.
7
+ *
8
+ * The lines come from `splitLines`, so a file with either line ending reads
9
+ * correctly; a reader that splits on `\n` alone reports the wrong position for
10
+ * a CRLF file.
11
+ *
12
+ * @param {string} text - the text the index belongs to.
13
+ * @param {number} index - the index to locate.
14
+ */
15
+ const getPosition = (text, index) => {
16
+ if (index <= 0)
17
+ return { lineNumber: 1, columnNumber: 1 };
18
+ const lines = (0, splitLines_1.splitLines)(text.slice(0, index));
19
+ return {
20
+ lineNumber: lines.length,
21
+ columnNumber: lines[lines.length - 1].length + 1
22
+ };
23
+ };
24
+ exports.getPosition = getPosition;
25
+ //# sourceMappingURL=getPosition.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getPosition.js","sourceRoot":"","sources":["../../src/utils/getPosition.ts"],"names":[],"mappings":";;;AAAA,6CAAyC;AAEzC;;;;;;;;;GASG;AACI,MAAM,WAAW,GAAG,CAAC,IAAY,EAAE,KAAa,EAAE,EAAE;IACzD,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,EAAE,UAAU,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,CAAA;IAEzD,MAAM,KAAK,GAAG,IAAA,uBAAU,EAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAA;IAE9C,OAAO;QACL,UAAU,EAAE,KAAK,CAAC,MAAM;QACxB,YAAY,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC;KACjD,CAAA;AACH,CAAC,CAAA;AATY,QAAA,WAAW,eASvB"}
package/utils/index.d.ts CHANGED
@@ -5,10 +5,12 @@ export * from './gremlinCharacters';
5
5
  export * from './isIgnored';
6
6
  export * from './listSasFiles';
7
7
  export * from './splitText';
8
+ export * from './getPosition';
8
9
  export * from './splitLines';
9
10
  export * from './getIndicesOf';
10
11
  export * from './getHeaderLinesCount';
11
12
  export * from './getDataSectionsDetail';
13
+ export * from './defaultBannedStrings';
12
14
  export * from './defaultIgnoredMacros';
13
15
  export * from './headerMacros';
14
16
  export * from './mergeLintConfig';
package/utils/index.js CHANGED
@@ -21,10 +21,12 @@ __exportStar(require("./gremlinCharacters"), exports);
21
21
  __exportStar(require("./isIgnored"), exports);
22
22
  __exportStar(require("./listSasFiles"), exports);
23
23
  __exportStar(require("./splitText"), exports);
24
+ __exportStar(require("./getPosition"), exports);
24
25
  __exportStar(require("./splitLines"), exports);
25
26
  __exportStar(require("./getIndicesOf"), exports);
26
27
  __exportStar(require("./getHeaderLinesCount"), exports);
27
28
  __exportStar(require("./getDataSectionsDetail"), exports);
29
+ __exportStar(require("./defaultBannedStrings"), exports);
28
30
  __exportStar(require("./defaultIgnoredMacros"), exports);
29
31
  __exportStar(require("./headerMacros"), exports);
30
32
  __exportStar(require("./mergeLintConfig"), exports);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,iDAA8B;AAC9B,kDAA+B;AAC/B,mDAAgC;AAChC,sDAAmC;AACnC,8CAA2B;AAC3B,iDAA8B;AAC9B,8CAA2B;AAC3B,+CAA4B;AAC5B,iDAA8B;AAC9B,wDAAqC;AACrC,0DAAuC;AACvC,yDAAsC;AACtC,iDAA8B;AAC9B,oDAAiC;AACjC,kDAA+B;AAC/B,sDAAmC;AACnC,oDAAiC;AACjC,8CAA2B"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,iDAA8B;AAC9B,kDAA+B;AAC/B,mDAAgC;AAChC,sDAAmC;AACnC,8CAA2B;AAC3B,iDAA8B;AAC9B,8CAA2B;AAC3B,gDAA6B;AAC7B,+CAA4B;AAC5B,iDAA8B;AAC9B,wDAAqC;AACrC,0DAAuC;AACvC,yDAAsC;AACtC,yDAAsC;AACtC,iDAA8B;AAC9B,oDAAiC;AACjC,kDAA+B;AAC/B,sDAAmC;AACnC,oDAAiC;AACjC,8CAA2B"}