@sasjs/lint 3.0.0 → 4.0.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
@@ -17,16 +17,17 @@ Our goal is to help SAS developers everywhere spend less time on code reviews, b
17
17
  - [@sasjs/vscode-extension](https://github.com/sasjs/vscode-extension) - just download SASjs in the VSCode marketplace, and select view/problems in the menu bar.
18
18
  - [@sasjs/cli](https://cli.sasjs.io/lint) - run `sasjs lint` to get a list of all files with their problems, along with line and column indexes.
19
19
 
20
- Configuration is via a `.sasjslint` file with the following structure (these are also the defaults if no .sasjslint file is found):
20
+ Configuration is via a `.sasjslint` file with the following structure (these are also the defaults - a setting that is absent, and a project with no `.sasjslint` file at all, uses the value below):
21
21
 
22
22
  ```json
23
23
  {
24
+ "allowedGremlins": [],
25
+ "defaultHeader": "/**{lineEnding} @file{lineEnding} @brief <Your brief here>{lineEnding}{lineEnding} <h4> SAS Macros </h4>{lineEnding}{lineEnding}**/",
24
26
  "hasDoxygenHeader": true,
25
27
  "hasMacroNameInMend": true,
26
28
  "hasMacroParentheses": true,
27
29
  "hasRequiredMacroOptions": false,
28
- "requiredMacroOptions": ["SECURE", "SRC"],
29
- "ignoreList": ["sasjsbuild/", "sasjsresults/"],
30
+ "ignoreList": [],
30
31
  "indentationMultiple": 2,
31
32
  "lineEndings": "off",
32
33
  "lowerCaseFileNames": true,
@@ -34,15 +35,17 @@ Configuration is via a `.sasjslint` file with the following structure (these are
34
35
  "maxHeaderLineLength": 80,
35
36
  "maxLineLength": 80,
36
37
  "noEncodedPasswords": true,
38
+ "noGremlins": true,
37
39
  "noNestedMacros": true,
38
40
  "noSingleAsteriskComments": false,
39
- "noGremlins": true,
40
41
  "noSpacesInFileNames": true,
41
42
  "noTabs": true,
42
43
  "noTrailingSpaces": true,
43
44
  "noUndeclaredMacros": true,
44
45
  "noUnusedMacros": true,
45
- "defaultHeader": "/**{lineEnding} @file{lineEnding} @brief <Your brief here>{lineEnding}{lineEnding} <h4> SAS Macros </h4>{lineEnding}{lineEnding}**/"
46
+ "requiredMacroOptions": [],
47
+ "severityLevel": {},
48
+ "strictMacroDefinition": true
46
49
  }
47
50
  ```
48
51
 
@@ -58,6 +61,29 @@ For more details, and the default state, see the description of each rule below.
58
61
 
59
62
  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).
60
63
 
64
+ ## Per-file overrides
65
+
66
+ A file can adjust the configuration for itself, with a `@sasjslint` block in its Doxygen header:
67
+
68
+ ```sas
69
+ /**
70
+ @file
71
+ @brief Calls the settlement API
72
+
73
+ @sasjslint {"maxHeaderLineLength": 200, "noUndeclaredMacros": false}
74
+ **/
75
+ ```
76
+
77
+ The block holds a JSON object that is merged over the resolved `.sasjslint`:
78
+
79
+ - scalars replace, so a file can switch a rule off, switch one on, or raise a limit for itself;
80
+ - arrays are additive, so `allowedGremlins` and `requiredMacroOptions` gain entries rather than replacing the project's;
81
+ - objects merge key by key, so a file can set one `severityLevel` without dropping the others.
82
+
83
+ The override applies to the whole file, and to the formatter, so `sasjs lint fix` and format-on-save honour it - a file that switches `noUnusedMacros` off keeps the entries it would otherwise lose. Only the header is read, so an override cannot be hidden in the body of a file, and a block that is malformed is ignored rather than raised. Place it outside the `<h4> SAS Macros </h4>` section, which the formatter rewrites.
84
+
85
+ One exception: `ignoreList` is evaluated before a file is read, so an entry a header adds cannot exclude the file it sits in.
86
+
61
87
  ### allowedGremlins
62
88
 
63
89
  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).
@@ -12,6 +12,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.formatFile = void 0;
13
13
  const file_1 = require("@sasjs/utils/file");
14
14
  const lint_1 = require("../lint");
15
+ const parseLintOverride_1 = require("../utils/parseLintOverride");
15
16
  const getLintConfig_1 = require("../utils/getLintConfig");
16
17
  const shared_1 = require("./shared");
17
18
  /**
@@ -25,7 +26,7 @@ const formatFile = (filePath, configuration) => __awaiter(void 0, void 0, void 0
25
26
  const diagnosticsBeforeFormat = yield (0, lint_1.lintFile)(filePath, config);
26
27
  const diagnosticsCountBeforeFormat = diagnosticsBeforeFormat.length;
27
28
  const text = yield (0, file_1.readFile)(filePath);
28
- const formattedText = (0, shared_1.processText)(text, config);
29
+ const formattedText = (0, shared_1.processText)(text, (0, parseLintOverride_1.applyLintOverride)(text, config));
29
30
  yield (0, file_1.createFile)(filePath, formattedText);
30
31
  const diagnosticsAfterFormat = yield (0, lint_1.lintFile)(filePath, config);
31
32
  const diagnosticsCountAfterFormat = diagnosticsAfterFormat.length;
@@ -1 +1 @@
1
- {"version":3,"file":"formatFile.js","sourceRoot":"","sources":["../../src/format/formatFile.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,4CAAwD;AACxD,kCAAkC;AAGlC,0DAAsD;AACtD,qCAAsC;AAEtC;;;;;GAKG;AACI,MAAM,UAAU,GAAG,CACxB,QAAgB,EAChB,aAA0B,EACH,EAAE;IACzB,MAAM,MAAM,GAAG,aAAa,IAAI,CAAC,MAAM,IAAA,6BAAa,GAAE,CAAC,CAAA;IACvD,MAAM,uBAAuB,GAAG,MAAM,IAAA,eAAQ,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;IAChE,MAAM,4BAA4B,GAAG,uBAAuB,CAAC,MAAM,CAAA;IAEnE,MAAM,IAAI,GAAG,MAAM,IAAA,eAAQ,EAAC,QAAQ,CAAC,CAAA;IAErC,MAAM,aAAa,GAAG,IAAA,oBAAW,EAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IAE/C,MAAM,IAAA,iBAAU,EAAC,QAAQ,EAAE,aAAa,CAAC,CAAA;IAEzC,MAAM,sBAAsB,GAAG,MAAM,IAAA,eAAQ,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;IAC/D,MAAM,2BAA2B,GAAG,sBAAsB,CAAC,MAAM,CAAA;IAEjE,MAAM,qBAAqB,GACzB,4BAA4B,GAAG,2BAA2B,CAAA;IAE5D,MAAM,gBAAgB,GAAa,EAAE,CAAA;IAErC,IAAI,qBAAqB,EAAE,CAAC;QAC1B,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IACjC,CAAC;IAED,OAAO;QACL,gBAAgB;QAChB,qBAAqB;QACrB,kBAAkB,EAAE,sBAAsB;KAC3C,CAAA;AACH,CAAC,CAAA,CAAA;AA/BY,QAAA,UAAU,cA+BtB"}
1
+ {"version":3,"file":"formatFile.js","sourceRoot":"","sources":["../../src/format/formatFile.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,4CAAwD;AACxD,kCAAkC;AAGlC,kEAA8D;AAC9D,0DAAsD;AACtD,qCAAsC;AAEtC;;;;;GAKG;AACI,MAAM,UAAU,GAAG,CACxB,QAAgB,EAChB,aAA0B,EACH,EAAE;IACzB,MAAM,MAAM,GAAG,aAAa,IAAI,CAAC,MAAM,IAAA,6BAAa,GAAE,CAAC,CAAA;IACvD,MAAM,uBAAuB,GAAG,MAAM,IAAA,eAAQ,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;IAChE,MAAM,4BAA4B,GAAG,uBAAuB,CAAC,MAAM,CAAA;IAEnE,MAAM,IAAI,GAAG,MAAM,IAAA,eAAQ,EAAC,QAAQ,CAAC,CAAA;IAErC,MAAM,aAAa,GAAG,IAAA,oBAAW,EAAC,IAAI,EAAE,IAAA,qCAAiB,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAA;IAExE,MAAM,IAAA,iBAAU,EAAC,QAAQ,EAAE,aAAa,CAAC,CAAA;IAEzC,MAAM,sBAAsB,GAAG,MAAM,IAAA,eAAQ,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;IAC/D,MAAM,2BAA2B,GAAG,sBAAsB,CAAC,MAAM,CAAA;IAEjE,MAAM,qBAAqB,GACzB,4BAA4B,GAAG,2BAA2B,CAAA;IAE5D,MAAM,gBAAgB,GAAa,EAAE,CAAA;IAErC,IAAI,qBAAqB,EAAE,CAAC;QAC1B,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IACjC,CAAC;IAED,OAAO;QACL,gBAAgB;QAChB,qBAAqB;QACrB,kBAAkB,EAAE,sBAAsB;KAC3C,CAAA;AACH,CAAC,CAAA,CAAA;AA/BY,QAAA,UAAU,cA+BtB"}
@@ -14,7 +14,7 @@ const utils_1 = require("../utils");
14
14
  const shared_1 = require("./shared");
15
15
  const formatText = (text, configuration) => __awaiter(void 0, void 0, void 0, function* () {
16
16
  const config = configuration || (yield (0, utils_1.getLintConfig)());
17
- return (0, shared_1.processText)(text, config);
17
+ return (0, shared_1.processText)(text, (0, utils_1.applyLintOverride)(text, config));
18
18
  });
19
19
  exports.formatText = formatText;
20
20
  //# sourceMappingURL=formatText.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"formatText.js","sourceRoot":"","sources":["../../src/format/formatText.ts"],"names":[],"mappings":";;;;;;;;;;;;AACA,oCAAwC;AACxC,qCAAsC;AAE/B,MAAM,UAAU,GAAG,CAAO,IAAY,EAAE,aAA0B,EAAE,EAAE;IAC3E,MAAM,MAAM,GAAG,aAAa,IAAI,CAAC,MAAM,IAAA,qBAAa,GAAE,CAAC,CAAA;IACvD,OAAO,IAAA,oBAAW,EAAC,IAAI,EAAE,MAAM,CAAC,CAAA;AAClC,CAAC,CAAA,CAAA;AAHY,QAAA,UAAU,cAGtB"}
1
+ {"version":3,"file":"formatText.js","sourceRoot":"","sources":["../../src/format/formatText.ts"],"names":[],"mappings":";;;;;;;;;;;;AACA,oCAA2D;AAC3D,qCAAsC;AAE/B,MAAM,UAAU,GAAG,CAAO,IAAY,EAAE,aAA0B,EAAE,EAAE;IAC3E,MAAM,MAAM,GAAG,aAAa,IAAI,CAAC,MAAM,IAAA,qBAAa,GAAE,CAAC,CAAA;IACvD,OAAO,IAAA,oBAAW,EAAC,IAAI,EAAE,IAAA,yBAAiB,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAA;AAC3D,CAAC,CAAA,CAAA;AAHY,QAAA,UAAU,cAGtB"}
package/lint/lintFile.js CHANGED
@@ -24,8 +24,9 @@ const lintFile = (filePath, configuration) => __awaiter(void 0, void 0, void 0,
24
24
  return [];
25
25
  const config = configuration || (yield (0, utils_1.getLintConfig)());
26
26
  const text = yield (0, file_1.readFile)(filePath);
27
- const fileDiagnostics = (0, shared_1.processFile)(filePath, config);
28
- const textDiagnostics = (0, shared_1.processText)(text, config);
27
+ const effectiveConfig = (0, utils_1.applyLintOverride)(text, config);
28
+ const fileDiagnostics = (0, shared_1.processFile)(filePath, effectiveConfig);
29
+ const textDiagnostics = (0, shared_1.processText)(text, effectiveConfig);
29
30
  return [...fileDiagnostics, ...textDiagnostics];
30
31
  });
31
32
  exports.lintFile = lintFile;
@@ -1 +1 @@
1
- {"version":3,"file":"lintFile.js","sourceRoot":"","sources":["../../src/lint/lintFile.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,4CAA4C;AAE5C,oCAAmD;AACnD,qCAAmD;AAEnD;;;;;GAKG;AACI,MAAM,QAAQ,GAAG,CACtB,QAAgB,EAChB,aAA0B,EACH,EAAE;IACzB,IAAI,MAAM,IAAA,iBAAS,EAAC,QAAQ,EAAE,aAAa,CAAC;QAAE,OAAO,EAAE,CAAA;IAEvD,MAAM,MAAM,GAAG,aAAa,IAAI,CAAC,MAAM,IAAA,qBAAa,GAAE,CAAC,CAAA;IACvD,MAAM,IAAI,GAAG,MAAM,IAAA,eAAQ,EAAC,QAAQ,CAAC,CAAA;IAErC,MAAM,eAAe,GAAG,IAAA,oBAAW,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;IACrD,MAAM,eAAe,GAAG,IAAA,oBAAW,EAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IAEjD,OAAO,CAAC,GAAG,eAAe,EAAE,GAAG,eAAe,CAAC,CAAA;AACjD,CAAC,CAAA,CAAA;AAbY,QAAA,QAAQ,YAapB"}
1
+ {"version":3,"file":"lintFile.js","sourceRoot":"","sources":["../../src/lint/lintFile.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,4CAA4C;AAE5C,oCAAsE;AACtE,qCAAmD;AAEnD;;;;;GAKG;AACI,MAAM,QAAQ,GAAG,CACtB,QAAgB,EAChB,aAA0B,EACH,EAAE;IACzB,IAAI,MAAM,IAAA,iBAAS,EAAC,QAAQ,EAAE,aAAa,CAAC;QAAE,OAAO,EAAE,CAAA;IAEvD,MAAM,MAAM,GAAG,aAAa,IAAI,CAAC,MAAM,IAAA,qBAAa,GAAE,CAAC,CAAA;IACvD,MAAM,IAAI,GAAG,MAAM,IAAA,eAAQ,EAAC,QAAQ,CAAC,CAAA;IACrC,MAAM,eAAe,GAAG,IAAA,yBAAiB,EAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IAEvD,MAAM,eAAe,GAAG,IAAA,oBAAW,EAAC,QAAQ,EAAE,eAAe,CAAC,CAAA;IAC9D,MAAM,eAAe,GAAG,IAAA,oBAAW,EAAC,IAAI,EAAE,eAAe,CAAC,CAAA;IAE1D,OAAO,CAAC,GAAG,eAAe,EAAE,GAAG,eAAe,CAAC,CAAA;AACjD,CAAC,CAAA,CAAA;AAdY,QAAA,QAAQ,YAcpB"}
package/lint/lintText.js CHANGED
@@ -22,7 +22,7 @@ const shared_1 = require("./shared");
22
22
  */
23
23
  const lintText = (text, configuration) => __awaiter(void 0, void 0, void 0, function* () {
24
24
  const config = configuration || (yield (0, utils_1.getLintConfig)());
25
- return (0, shared_1.processText)(text, config);
25
+ return (0, shared_1.processText)(text, (0, utils_1.applyLintOverride)(text, config));
26
26
  });
27
27
  exports.lintText = lintText;
28
28
  //# sourceMappingURL=lintText.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"lintText.js","sourceRoot":"","sources":["../../src/lint/lintText.ts"],"names":[],"mappings":";;;;;;;;;;;;AACA,oCAAwC;AACxC,qCAAsC;AAEtC;;;;;;;GAOG;AACI,MAAM,QAAQ,GAAG,CACtB,IAAY,EACZ,aAA0B,EACH,EAAE;IACzB,MAAM,MAAM,GAAG,aAAa,IAAI,CAAC,MAAM,IAAA,qBAAa,GAAE,CAAC,CAAA;IACvD,OAAO,IAAA,oBAAW,EAAC,IAAI,EAAE,MAAM,CAAC,CAAA;AAClC,CAAC,CAAA,CAAA;AANY,QAAA,QAAQ,YAMpB"}
1
+ {"version":3,"file":"lintText.js","sourceRoot":"","sources":["../../src/lint/lintText.ts"],"names":[],"mappings":";;;;;;;;;;;;AACA,oCAA2D;AAC3D,qCAAsC;AAEtC;;;;;;;GAOG;AACI,MAAM,QAAQ,GAAG,CACtB,IAAY,EACZ,aAA0B,EACH,EAAE;IACzB,MAAM,MAAM,GAAG,aAAa,IAAI,CAAC,MAAM,IAAA,qBAAa,GAAE,CAAC,CAAA;IACvD,OAAO,IAAA,oBAAW,EAAC,IAAI,EAAE,IAAA,yBAAiB,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAA;AAC3D,CAAC,CAAA,CAAA;AANY,QAAA,QAAQ,YAMpB"}
package/package.json CHANGED
@@ -72,5 +72,5 @@
72
72
  "@sasjs/utils": "3.6.2",
73
73
  "ignore": "7.0.11"
74
74
  },
75
- "version": "3.0.0"
75
+ "version": "4.0.0"
76
76
  }
@@ -3,18 +3,22 @@
3
3
  "$id": "https://github.com/sasjs/lint/blob/main/sasjslint-schema.json",
4
4
  "type": "object",
5
5
  "title": "SASjs Lint Config File",
6
- "description": "The SASjs Lint Config file provides the settings for customising SAS code style in your project.",
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
- "noEncodedPasswords": true,
9
- "hasDoxygenHeader": true,
8
+ "allowedGremlins": [],
10
9
  "defaultHeader": "/**{lineEnding} @file{lineEnding} @brief <Your brief here>{lineEnding}{lineEnding} <h4> SAS Macros </h4>{lineEnding}{lineEnding}**/",
11
- "hasMacroNameInMend": false,
10
+ "hasDoxygenHeader": true,
11
+ "hasMacroNameInMend": true,
12
12
  "hasMacroParentheses": true,
13
+ "hasRequiredMacroOptions": false,
14
+ "ignoreList": [],
13
15
  "indentationMultiple": 2,
16
+ "lineEndings": "off",
14
17
  "lowerCaseFileNames": true,
15
- "maxLineLength": 80,
16
- "maxHeaderLineLength": 80,
17
18
  "maxDataLineLength": 80,
19
+ "maxHeaderLineLength": 80,
20
+ "maxLineLength": 80,
21
+ "noEncodedPasswords": true,
18
22
  "noGremlins": true,
19
23
  "noNestedMacros": true,
20
24
  "noSingleAsteriskComments": false,
@@ -23,11 +27,9 @@
23
27
  "noTrailingSpaces": true,
24
28
  "noUndeclaredMacros": true,
25
29
  "noUnusedMacros": true,
26
- "lineEndings": "off",
27
- "strictMacroDefinition": true,
28
- "ignoreList": ["sajsbuild", "sasjsresults"],
29
- "hasRequiredMacroOptions": false,
30
- "requiredMacroOptions": []
30
+ "requiredMacroOptions": [],
31
+ "severityLevel": {},
32
+ "strictMacroDefinition": true
31
33
  },
32
34
  "examples": [
33
35
  {
@@ -106,7 +108,7 @@
106
108
  "type": "boolean",
107
109
  "title": "hasMacroNameInMend",
108
110
  "description": "Enforces the presence of macro names in %mend statements. Shows a warning for %mend statements with missing or mismatched macro names.",
109
- "default": false,
111
+ "default": true,
110
112
  "examples": [true, false]
111
113
  },
112
114
  "hasMacroParentheses": {
@@ -235,8 +237,8 @@
235
237
  "type": "array",
236
238
  "title": "ignoreList",
237
239
  "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.",
238
- "default": ["sasjsbuild/", "sasjsresults/"],
239
- "examples": ["sasjs/tests", "tmp/scratch.sas"]
240
+ "default": [],
241
+ "examples": [["sasjsbuild/", "sasjsresults/"], ["sasjs/tests", "tmp/scratch.sas"]]
240
242
  },
241
243
  "hasRequiredMacroOptions": {
242
244
  "$id": "#/properties/hasRequiredMacroOptions",
@@ -9,6 +9,8 @@ import { Severity } from './Severity';
9
9
  * More types of rules, when available, will be added here.
10
10
  */
11
11
  export declare class LintConfig {
12
+ /** The JSON this configuration was built from, so it can be overridden. */
13
+ readonly source: any;
12
14
  readonly ignoreList: string[];
13
15
  readonly allowedGremlins: string[];
14
16
  readonly lineLintRules: LineLintRule[];
@@ -25,4 +27,15 @@ export declare class LintConfig {
25
27
  };
26
28
  readonly requiredMacroOptions: string[];
27
29
  constructor(json?: any);
30
+ /**
31
+ * Returns a new configuration with an override merged over this one, so a
32
+ * file can adjust the rules that apply to it.
33
+ *
34
+ * Scalars replace, arrays are additive and objects merge key by key - see
35
+ * `mergeLintConfig`.
36
+ *
37
+ * @param {object} json - the override, as read from a `@sasjslint` block.
38
+ * @returns {LintConfig} a new configuration; this one is unchanged.
39
+ */
40
+ override(json: any): LintConfig;
28
41
  }
@@ -6,6 +6,7 @@ const line_1 = require("../rules/line");
6
6
  const path_1 = require("../rules/path");
7
7
  const LineEndings_1 = require("./LineEndings");
8
8
  const utils_1 = require("../utils");
9
+ const mergeLintConfig_1 = require("../utils/mergeLintConfig");
9
10
  const Severity_1 = require("./Severity");
10
11
  /**
11
12
  * LintConfig is the logical representation of the .sasjslint file.
@@ -29,6 +30,7 @@ class LintConfig {
29
30
  this.defaultHeader = (0, utils_1.getDefaultHeader)();
30
31
  this.severityLevel = {};
31
32
  this.requiredMacroOptions = [];
33
+ this.source = json !== null && json !== void 0 ? json : {};
32
34
  if (json === null || json === void 0 ? void 0 : json.ignoreList) {
33
35
  if (Array.isArray(json.ignoreList)) {
34
36
  json.ignoreList.forEach((item) => {
@@ -52,9 +54,13 @@ class LintConfig {
52
54
  if ((json === null || json === void 0 ? void 0 : json.noTabs) === false || (json === null || json === void 0 ? void 0 : json.noTabIndentation) === false) {
53
55
  this.lineLintRules.pop();
54
56
  }
55
- if ((json === null || json === void 0 ? void 0 : json.maxLineLength) > 0) {
57
+ // An absent setting falls back to the default, so the rule is on unless the
58
+ // value switches it off (0 or a negative number).
59
+ if ((json === null || json === void 0 ? void 0 : json.maxLineLength) === undefined || (json === null || json === void 0 ? void 0 : json.maxLineLength) > 0) {
56
60
  this.lineLintRules.push(line_1.maxLineLength);
57
- this.maxLineLength = json.maxLineLength;
61
+ if (!isNaN(json === null || json === void 0 ? void 0 : json.maxLineLength)) {
62
+ this.maxLineLength = json.maxLineLength;
63
+ }
58
64
  if (!isNaN(json === null || json === void 0 ? void 0 : json.maxHeaderLineLength)) {
59
65
  this.maxHeaderLineLength = json.maxHeaderLineLength;
60
66
  }
@@ -86,7 +92,7 @@ class LintConfig {
86
92
  if ((json === null || json === void 0 ? void 0 : json.lowerCaseFileNames) !== false) {
87
93
  this.pathLintRules.push(path_1.lowerCaseFileNames);
88
94
  }
89
- if (json === null || json === void 0 ? void 0 : json.hasMacroNameInMend) {
95
+ if ((json === null || json === void 0 ? void 0 : json.hasMacroNameInMend) !== false) {
90
96
  this.fileLintRules.push(file_1.hasMacroNameInMend);
91
97
  }
92
98
  if ((json === null || json === void 0 ? void 0 : json.noNestedMacros) !== false) {
@@ -101,20 +107,17 @@ class LintConfig {
101
107
  if (json === null || json === void 0 ? void 0 : json.hasRequiredMacroOptions) {
102
108
  this.fileLintRules.push(file_1.hasRequiredMacroOptions);
103
109
  if (json === null || json === void 0 ? void 0 : json.requiredMacroOptions) {
104
- if (Array.isArray(json.requiredMacroOptions) &&
105
- json.requiredMacroOptions.length > 0) {
106
- json.requiredMacroOptions.forEach((item) => {
107
- if (typeof item === 'string') {
108
- this.requiredMacroOptions.push(item);
109
- }
110
- else {
111
- throw new Error(`Property "requiredMacroOptions" has invalid type of values. It can only contain strings.`);
112
- }
113
- });
114
- }
115
- else {
110
+ if (!Array.isArray(json.requiredMacroOptions)) {
116
111
  throw new Error(`Property "requiredMacroOptions" can only be an array of strings.`);
117
112
  }
113
+ json.requiredMacroOptions.forEach((item) => {
114
+ if (typeof item === 'string') {
115
+ this.requiredMacroOptions.push(item);
116
+ }
117
+ else {
118
+ throw new Error(`Property "requiredMacroOptions" has invalid type of values. It can only contain strings.`);
119
+ }
120
+ });
118
121
  }
119
122
  }
120
123
  if (json === null || json === void 0 ? void 0 : json.noSingleAsteriskComments) {
@@ -151,6 +154,19 @@ class LintConfig {
151
154
  }
152
155
  }
153
156
  }
157
+ /**
158
+ * Returns a new configuration with an override merged over this one, so a
159
+ * file can adjust the rules that apply to it.
160
+ *
161
+ * Scalars replace, arrays are additive and objects merge key by key - see
162
+ * `mergeLintConfig`.
163
+ *
164
+ * @param {object} json - the override, as read from a `@sasjslint` block.
165
+ * @returns {LintConfig} a new configuration; this one is unchanged.
166
+ */
167
+ override(json) {
168
+ return new LintConfig((0, mergeLintConfig_1.mergeLintConfig)(this.source, json));
169
+ }
154
170
  }
155
171
  exports.LintConfig = LintConfig;
156
172
  //# sourceMappingURL=LintConfig.js.map
@@ -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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"}
@@ -2,26 +2,39 @@ import { LintConfig } from '../types/LintConfig';
2
2
  import { LineEndings } from '../types/LineEndings';
3
3
  export declare const getDefaultHeader: () => string;
4
4
  /**
5
- * Default configuration that is used when a .sasjslint file is not found
5
+ * Default configuration that is used when a .sasjslint file is not found.
6
+ *
7
+ * It lists every setting the linter reads, with its default value, so it
8
+ * doubles as the reference for the `.sasjslint` file. `getLintConfig.spec.ts`
9
+ * enumerates the settings the config reads and fails if this object misses one,
10
+ * and the README mirrors it.
6
11
  */
7
12
  export declare const DefaultLintConfiguration: {
8
- lineEndings: LineEndings;
9
- noTrailingSpaces: boolean;
10
- noEncodedPasswords: boolean;
13
+ allowedGremlins: never[];
14
+ defaultHeader: string;
11
15
  hasDoxygenHeader: boolean;
12
- noSpacesInFileNames: boolean;
16
+ hasMacroNameInMend: boolean;
17
+ hasMacroParentheses: boolean;
18
+ hasRequiredMacroOptions: boolean;
19
+ ignoreList: never[];
20
+ indentationMultiple: number;
21
+ lineEndings: LineEndings;
13
22
  lowerCaseFileNames: boolean;
14
- maxLineLength: number;
15
- maxHeaderLineLength: number;
16
23
  maxDataLineLength: number;
17
- noTabIndentation: boolean;
18
- indentationMultiple: number;
19
- hasMacroNameInMend: boolean;
24
+ maxHeaderLineLength: number;
25
+ maxLineLength: number;
26
+ noEncodedPasswords: boolean;
27
+ noGremlins: boolean;
20
28
  noNestedMacros: boolean;
21
- hasMacroParentheses: boolean;
29
+ noSingleAsteriskComments: boolean;
30
+ noSpacesInFileNames: boolean;
31
+ noTabs: boolean;
32
+ noTrailingSpaces: boolean;
33
+ noUndeclaredMacros: boolean;
34
+ noUnusedMacros: boolean;
35
+ requiredMacroOptions: never[];
36
+ severityLevel: {};
22
37
  strictMacroDefinition: boolean;
23
- noGremlins: boolean;
24
- defaultHeader: string;
25
38
  };
26
39
  /**
27
40
  * Fetches the config from the .sasjslint file (at project root or home directory) and creates a LintConfig object.
@@ -23,26 +23,39 @@ const LineEndings_1 = require("../types/LineEndings");
23
23
  const getDefaultHeader = () => `/**{lineEnding} @file{lineEnding} @brief <Your brief here>{lineEnding}{lineEnding} <h4> SAS Macros </h4>{lineEnding}{lineEnding}**/`;
24
24
  exports.getDefaultHeader = getDefaultHeader;
25
25
  /**
26
- * Default configuration that is used when a .sasjslint file is not found
26
+ * Default configuration that is used when a .sasjslint file is not found.
27
+ *
28
+ * It lists every setting the linter reads, with its default value, so it
29
+ * doubles as the reference for the `.sasjslint` file. `getLintConfig.spec.ts`
30
+ * enumerates the settings the config reads and fails if this object misses one,
31
+ * and the README mirrors it.
27
32
  */
28
33
  exports.DefaultLintConfiguration = {
29
- lineEndings: LineEndings_1.LineEndings.OFF,
30
- noTrailingSpaces: true,
31
- noEncodedPasswords: true,
34
+ allowedGremlins: [],
35
+ defaultHeader: (0, exports.getDefaultHeader)(),
32
36
  hasDoxygenHeader: true,
33
- noSpacesInFileNames: true,
34
- lowerCaseFileNames: true,
35
- maxLineLength: 80,
36
- maxHeaderLineLength: 80,
37
- maxDataLineLength: 80,
38
- noTabIndentation: true,
39
- indentationMultiple: 2,
40
37
  hasMacroNameInMend: true,
41
- noNestedMacros: true,
42
38
  hasMacroParentheses: true,
43
- strictMacroDefinition: true,
39
+ hasRequiredMacroOptions: false,
40
+ ignoreList: [],
41
+ indentationMultiple: 2,
42
+ lineEndings: LineEndings_1.LineEndings.OFF,
43
+ lowerCaseFileNames: true,
44
+ maxDataLineLength: 80,
45
+ maxHeaderLineLength: 80,
46
+ maxLineLength: 80,
47
+ noEncodedPasswords: true,
44
48
  noGremlins: true,
45
- defaultHeader: (0, exports.getDefaultHeader)()
49
+ noNestedMacros: true,
50
+ noSingleAsteriskComments: false,
51
+ noSpacesInFileNames: true,
52
+ noTabs: true,
53
+ noTrailingSpaces: true,
54
+ noUndeclaredMacros: true,
55
+ noUnusedMacros: true,
56
+ requiredMacroOptions: [],
57
+ severityLevel: {},
58
+ strictMacroDefinition: true
46
59
  };
47
60
  /**
48
61
  * Fetches the config from the .sasjslint file (at project root or home directory) and creates a LintConfig object.
@@ -1 +1 @@
1
- {"version":3,"file":"getLintConfig.js","sourceRoot":"","sources":["../../src/utils/getLintConfig.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAsCA,sCASC;AA/CD,gDAAuB;AACvB,4CAAmB;AACnB,oDAAgD;AAChD,4CAA4C;AAC5C,qDAAiD;AACjD,sDAAkD;AAE3C,MAAM,gBAAgB,GAAG,GAAG,EAAE,CACnC,wIAAwI,CAAA;AAD7H,QAAA,gBAAgB,oBAC6G;AAE1I;;GAEG;AACU,QAAA,wBAAwB,GAAG;IACtC,WAAW,EAAE,yBAAW,CAAC,GAAG;IAC5B,gBAAgB,EAAE,IAAI;IACtB,kBAAkB,EAAE,IAAI;IACxB,gBAAgB,EAAE,IAAI;IACtB,mBAAmB,EAAE,IAAI;IACzB,kBAAkB,EAAE,IAAI;IACxB,aAAa,EAAE,EAAE;IACjB,mBAAmB,EAAE,EAAE;IACvB,iBAAiB,EAAE,EAAE;IACrB,gBAAgB,EAAE,IAAI;IACtB,mBAAmB,EAAE,CAAC;IACtB,kBAAkB,EAAE,IAAI;IACxB,cAAc,EAAE,IAAI;IACpB,mBAAmB,EAAE,IAAI;IACzB,qBAAqB,EAAE,IAAI;IAC3B,UAAU,EAAE,IAAI;IAChB,aAAa,EAAE,IAAA,wBAAgB,GAAE;CAClC,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":";;;;;;;;;;;;;;;AAmDA,sCASC;AA5DD,gDAAuB;AACvB,4CAAmB;AACnB,oDAAgD;AAChD,4CAA4C;AAC5C,qDAAiD;AACjD,sDAAkD;AAE3C,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,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,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"}
package/utils/index.d.ts CHANGED
@@ -9,5 +9,7 @@ export * from './getIndicesOf';
9
9
  export * from './getHeaderLinesCount';
10
10
  export * from './getDataSectionsDetail';
11
11
  export * from './headerMacros';
12
+ export * from './mergeLintConfig';
13
+ export * from './parseLintOverride';
12
14
  export * from './parseMacroCalls';
13
15
  export * from './sasMacros';
package/utils/index.js CHANGED
@@ -25,6 +25,8 @@ __exportStar(require("./getIndicesOf"), exports);
25
25
  __exportStar(require("./getHeaderLinesCount"), exports);
26
26
  __exportStar(require("./getDataSectionsDetail"), exports);
27
27
  __exportStar(require("./headerMacros"), exports);
28
+ __exportStar(require("./mergeLintConfig"), exports);
29
+ __exportStar(require("./parseLintOverride"), exports);
28
30
  __exportStar(require("./parseMacroCalls"), exports);
29
31
  __exportStar(require("./sasMacros"), exports);
30
32
  //# sourceMappingURL=index.js.map
@@ -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,iDAA8B;AAC9B,wDAAqC;AACrC,0DAAuC;AACvC,iDAA8B;AAC9B,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,iDAA8B;AAC9B,wDAAqC;AACrC,0DAAuC;AACvC,iDAA8B;AAC9B,oDAAiC;AACjC,sDAAmC;AACnC,oDAAiC;AACjC,8CAA2B"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Merges a per-file configuration override over the project configuration.
3
+ *
4
+ * Scalars replace, arrays are additive, and objects merge key by key. A file
5
+ * therefore adds an allowed gremlin, a required macro option or a severity
6
+ * level without having to restate the rest of the project configuration, and
7
+ * it can still switch a rule off or raise a limit for itself. Deprecated
8
+ * setting names are folded onto their canonical key first.
9
+ */
10
+ export declare const mergeLintConfig: (base: any, override: any) => any;
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.mergeLintConfig = void 0;
4
+ /**
5
+ * Deprecated setting names, mapped to the canonical key. An alias is folded onto
6
+ * the canonical key before the merge, so a project that sets `noTabIndentation`
7
+ * and a file that sets `noTabs` cannot end up carrying both - which would let
8
+ * the alias win in the constructor and defeat the file.
9
+ */
10
+ const aliases = {
11
+ noTabIndentation: 'noTabs'
12
+ };
13
+ const normaliseAliases = (json) => {
14
+ if (!isPlainObject(json))
15
+ return json;
16
+ const normalised = Object.assign({}, json);
17
+ for (const [alias, canonical] of Object.entries(aliases)) {
18
+ if (alias in normalised) {
19
+ if (!(canonical in normalised)) {
20
+ normalised[canonical] = normalised[alias];
21
+ }
22
+ delete normalised[alias];
23
+ }
24
+ }
25
+ return normalised;
26
+ };
27
+ /**
28
+ * Merges a per-file configuration override over the project configuration.
29
+ *
30
+ * Scalars replace, arrays are additive, and objects merge key by key. A file
31
+ * therefore adds an allowed gremlin, a required macro option or a severity
32
+ * level without having to restate the rest of the project configuration, and
33
+ * it can still switch a rule off or raise a limit for itself. Deprecated
34
+ * setting names are folded onto their canonical key first.
35
+ */
36
+ const mergeLintConfig = (base, override) => {
37
+ const normalisedOverride = normaliseAliases(override);
38
+ if (!isPlainObject(base) || !isPlainObject(normalisedOverride)) {
39
+ return normalisedOverride;
40
+ }
41
+ const merged = normaliseAliases(base);
42
+ for (const [key, value] of Object.entries(normalisedOverride)) {
43
+ const current = merged[key];
44
+ if (Array.isArray(current) && Array.isArray(value)) {
45
+ merged[key] = mergeArrays(current, value);
46
+ }
47
+ else if (isPlainObject(current) && isPlainObject(value)) {
48
+ merged[key] = Object.assign(Object.assign({}, current), value);
49
+ }
50
+ else {
51
+ merged[key] = value;
52
+ }
53
+ }
54
+ return merged;
55
+ };
56
+ exports.mergeLintConfig = mergeLintConfig;
57
+ const isPlainObject = (value) => !!value && typeof value === 'object' && !Array.isArray(value);
58
+ const isPrimitiveArray = (value) => value.every((item) => item === null || typeof item !== 'object');
59
+ /**
60
+ * Concatenates two arrays. Arrays of primitives are de-duplicated, so an
61
+ * override that repeats an entry the project already lists does not add it
62
+ * twice.
63
+ */
64
+ const mergeArrays = (base, override) => isPrimitiveArray(base) && isPrimitiveArray(override)
65
+ ? [...new Set([...base, ...override])]
66
+ : [...base, ...override];
67
+ //# sourceMappingURL=mergeLintConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mergeLintConfig.js","sourceRoot":"","sources":["../../src/utils/mergeLintConfig.ts"],"names":[],"mappings":";;;AAAA;;;;;GAKG;AACH,MAAM,OAAO,GAA2B;IACtC,gBAAgB,EAAE,QAAQ;CAC3B,CAAA;AAED,MAAM,gBAAgB,GAAG,CAAC,IAAS,EAAO,EAAE;IAC1C,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAA;IAErC,MAAM,UAAU,qBAAQ,IAAI,CAAE,CAAA;IAE9B,KAAK,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACzD,IAAI,KAAK,IAAI,UAAU,EAAE,CAAC;YACxB,IAAI,CAAC,CAAC,SAAS,IAAI,UAAU,CAAC,EAAE,CAAC;gBAC/B,UAAU,CAAC,SAAS,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,CAAA;YAC3C,CAAC;YAED,OAAO,UAAU,CAAC,KAAK,CAAC,CAAA;QAC1B,CAAC;IACH,CAAC;IAED,OAAO,UAAU,CAAA;AACnB,CAAC,CAAA;AAED;;;;;;;;GAQG;AACI,MAAM,eAAe,GAAG,CAAC,IAAS,EAAE,QAAa,EAAO,EAAE;IAC/D,MAAM,kBAAkB,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAA;IAErD,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,kBAAkB,CAAC,EAAE,CAAC;QAC/D,OAAO,kBAAkB,CAAA;IAC3B,CAAC;IAED,MAAM,MAAM,GAAQ,gBAAgB,CAAC,IAAI,CAAC,CAAA;IAE1C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,kBAAkB,CAAC,EAAE,CAAC;QAC9D,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,CAAA;QAE3B,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACnD,MAAM,CAAC,GAAG,CAAC,GAAG,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;QAC3C,CAAC;aAAM,IAAI,aAAa,CAAC,OAAO,CAAC,IAAI,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1D,MAAM,CAAC,GAAG,CAAC,mCAAS,OAAkB,GAAM,KAAgB,CAAE,CAAA;QAChE,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;QACrB,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC,CAAA;AAtBY,QAAA,eAAe,mBAsB3B;AAED,MAAM,aAAa,GAAG,CAAC,KAAU,EAAW,EAAE,CAC5C,CAAC,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;AAE/D,MAAM,gBAAgB,GAAG,CAAC,KAAY,EAAW,EAAE,CACjD,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAA;AAElE;;;;GAIG;AACH,MAAM,WAAW,GAAG,CAAC,IAAW,EAAE,QAAe,EAAS,EAAE,CAC1D,gBAAgB,CAAC,IAAI,CAAC,IAAI,gBAAgB,CAAC,QAAQ,CAAC;IAClD,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,QAAQ,CAAC,CAAA"}
@@ -0,0 +1,36 @@
1
+ import type { LintConfig } from '../types/LintConfig';
2
+ /**
3
+ * Reads the per-file override from the header of a file.
4
+ *
5
+ * The override is a `@sasjslint` tag followed by a JSON object, anywhere in the
6
+ * Doxygen header:
7
+ *
8
+ * ```
9
+ * /**
10
+ * @file
11
+ * @brief Calls the settlement API
12
+ *
13
+ * @sasjslint {"maxHeaderLineLength": 200, "noUndeclaredMacros": false}
14
+ * **\/
15
+ * ```
16
+ *
17
+ * Only the header is read, so an override cannot be buried in the body of a
18
+ * file. A tag that is missing, unterminated, malformed or not an object is
19
+ * ignored rather than raised: the linter must not fail on bad input.
20
+ *
21
+ * @param {string} text - the text content of the file.
22
+ * @param {LintConfig} config - the resolved configuration, used to find the
23
+ * header and its line endings.
24
+ * @returns {object | null} the override, or null when there is none.
25
+ */
26
+ export declare const getLintOverride: (text: string, config: LintConfig) => any | null;
27
+ /**
28
+ * Returns the configuration to lint a file with: the given configuration, with
29
+ * the file's own `@sasjslint` override merged over it. The header wins, since
30
+ * it is the more specific statement.
31
+ *
32
+ * @param {string} text - the text content of the file.
33
+ * @param {LintConfig} config - the resolved configuration.
34
+ * @returns {LintConfig} the effective configuration.
35
+ */
36
+ export declare const applyLintOverride: (text: string, config: LintConfig) => LintConfig;
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.applyLintOverride = exports.getLintOverride = void 0;
4
+ const getHeaderLinesCount_1 = require("./getHeaderLinesCount");
5
+ const splitText_1 = require("./splitText");
6
+ /**
7
+ * The tag that introduces a per-file override, with the object that must follow
8
+ * it. The tag has to start a header line, and the `{` has to come immediately
9
+ * after it, so a `@brief` that mentions the syntax in prose, a longer tag such
10
+ * as `@sasjslintFoo`, and a tag with something else after it are all left alone
11
+ * rather than read as an override.
12
+ */
13
+ const marker = /^[^\w]*@sasjslint\s*\{/m;
14
+ /**
15
+ * Reads a balanced JSON object from `start`, honouring strings and escapes so
16
+ * a brace inside a value does not end the scan early.
17
+ */
18
+ const readObject = (text, start) => {
19
+ let depth = 0;
20
+ let inString = false;
21
+ let escaped = false;
22
+ for (let index = start; index < text.length; index++) {
23
+ const char = text[index];
24
+ if (inString) {
25
+ if (escaped)
26
+ escaped = false;
27
+ else if (char === '\\')
28
+ escaped = true;
29
+ else if (char === '"')
30
+ inString = false;
31
+ continue;
32
+ }
33
+ if (char === '"') {
34
+ inString = true;
35
+ }
36
+ else if (char === '{') {
37
+ depth++;
38
+ }
39
+ else if (char === '}') {
40
+ depth--;
41
+ if (depth === 0)
42
+ return text.slice(start, index + 1);
43
+ }
44
+ }
45
+ return null;
46
+ };
47
+ /**
48
+ * Reads the per-file override from the header of a file.
49
+ *
50
+ * The override is a `@sasjslint` tag followed by a JSON object, anywhere in the
51
+ * Doxygen header:
52
+ *
53
+ * ```
54
+ * /**
55
+ * @file
56
+ * @brief Calls the settlement API
57
+ *
58
+ * @sasjslint {"maxHeaderLineLength": 200, "noUndeclaredMacros": false}
59
+ * **\/
60
+ * ```
61
+ *
62
+ * Only the header is read, so an override cannot be buried in the body of a
63
+ * file. A tag that is missing, unterminated, malformed or not an object is
64
+ * ignored rather than raised: the linter must not fail on bad input.
65
+ *
66
+ * @param {string} text - the text content of the file.
67
+ * @param {LintConfig} config - the resolved configuration, used to find the
68
+ * header and its line endings.
69
+ * @returns {object | null} the override, or null when there is none.
70
+ */
71
+ const getLintOverride = (text, config) => {
72
+ if (!text)
73
+ return null;
74
+ const headerLinesCount = (0, getHeaderLinesCount_1.getHeaderLinesCount)(text, config);
75
+ if (!headerLinesCount)
76
+ return null;
77
+ const header = (0, splitText_1.splitText)(text, config).slice(0, headerLinesCount).join('\n');
78
+ const match = marker.exec(header);
79
+ if (!match)
80
+ return null;
81
+ // The match ends with the opening brace.
82
+ const brace = match.index + match[0].length - 1;
83
+ const body = readObject(header, brace);
84
+ if (!body)
85
+ return null;
86
+ try {
87
+ // The body always starts with `{`, so a successful parse is an object.
88
+ return JSON.parse(body);
89
+ }
90
+ catch (_a) {
91
+ return null;
92
+ }
93
+ };
94
+ exports.getLintOverride = getLintOverride;
95
+ /**
96
+ * Returns the configuration to lint a file with: the given configuration, with
97
+ * the file's own `@sasjslint` override merged over it. The header wins, since
98
+ * it is the more specific statement.
99
+ *
100
+ * @param {string} text - the text content of the file.
101
+ * @param {LintConfig} config - the resolved configuration.
102
+ * @returns {LintConfig} the effective configuration.
103
+ */
104
+ const applyLintOverride = (text, config) => {
105
+ const override = (0, exports.getLintOverride)(text, config);
106
+ return override ? config.override(override) : config;
107
+ };
108
+ exports.applyLintOverride = applyLintOverride;
109
+ //# sourceMappingURL=parseLintOverride.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseLintOverride.js","sourceRoot":"","sources":["../../src/utils/parseLintOverride.ts"],"names":[],"mappings":";;;AACA,+DAA2D;AAC3D,2CAAuC;AAEvC;;;;;;GAMG;AACH,MAAM,MAAM,GAAG,yBAAyB,CAAA;AAExC;;;GAGG;AACH,MAAM,UAAU,GAAG,CAAC,IAAY,EAAE,KAAa,EAAiB,EAAE;IAChE,IAAI,KAAK,GAAG,CAAC,CAAA;IACb,IAAI,QAAQ,GAAG,KAAK,CAAA;IACpB,IAAI,OAAO,GAAG,KAAK,CAAA;IAEnB,KAAK,IAAI,KAAK,GAAG,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;QACrD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAA;QAExB,IAAI,QAAQ,EAAE,CAAC;YACb,IAAI,OAAO;gBAAE,OAAO,GAAG,KAAK,CAAA;iBACvB,IAAI,IAAI,KAAK,IAAI;gBAAE,OAAO,GAAG,IAAI,CAAA;iBACjC,IAAI,IAAI,KAAK,GAAG;gBAAE,QAAQ,GAAG,KAAK,CAAA;YACvC,SAAQ;QACV,CAAC;QAED,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACjB,QAAQ,GAAG,IAAI,CAAA;QACjB,CAAC;aAAM,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACxB,KAAK,EAAE,CAAA;QACT,CAAC;aAAM,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACxB,KAAK,EAAE,CAAA;YACP,IAAI,KAAK,KAAK,CAAC;gBAAE,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,CAAC,CAAC,CAAA;QACtD,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAA;AACb,CAAC,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACI,MAAM,eAAe,GAAG,CAC7B,IAAY,EACZ,MAAkB,EACN,EAAE;IACd,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAA;IAEtB,MAAM,gBAAgB,GAAG,IAAA,yCAAmB,EAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IAC1D,IAAI,CAAC,gBAAgB;QAAE,OAAO,IAAI,CAAA;IAElC,MAAM,MAAM,GAAG,IAAA,qBAAS,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAE5E,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IACjC,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAA;IAEvB,yCAAyC;IACzC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAA;IAE/C,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;IACtC,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAA;IAEtB,IAAI,CAAC;QACH,uEAAuE;QACvE,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IACzB,CAAC;IAAC,WAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC,CAAA;AA1BY,QAAA,eAAe,mBA0B3B;AAED;;;;;;;;GAQG;AACI,MAAM,iBAAiB,GAAG,CAC/B,IAAY,EACZ,MAAkB,EACN,EAAE;IACd,MAAM,QAAQ,GAAG,IAAA,uBAAe,EAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IAC9C,OAAO,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAA;AACtD,CAAC,CAAA;AANY,QAAA,iBAAiB,qBAM7B"}