@sasjs/lint 3.0.0 → 4.1.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 +107 -6
- package/format/formatFile.js +2 -1
- package/format/formatFile.js.map +1 -1
- package/format/formatText.js +1 -1
- package/format/formatText.js.map +1 -1
- package/lint/lintFile.js +3 -2
- package/lint/lintFile.js.map +1 -1
- package/lint/lintText.js +1 -1
- package/lint/lintText.js.map +1 -1
- package/package.json +1 -1
- package/rules/file/index.d.ts +1 -0
- package/rules/file/index.js +3 -1
- package/rules/file/index.js.map +1 -1
- package/rules/file/noUnusedLibnames.d.ts +15 -0
- package/rules/file/noUnusedLibnames.js +56 -0
- package/rules/file/noUnusedLibnames.js.map +1 -0
- package/sasjslint-schema.json +41 -14
- package/types/LintConfig.d.ts +14 -0
- package/types/LintConfig.js +49 -15
- package/types/LintConfig.js.map +1 -1
- package/utils/getLintConfig.d.ts +28 -13
- package/utils/getLintConfig.js +29 -14
- package/utils/getLintConfig.js.map +1 -1
- package/utils/index.d.ts +3 -0
- package/utils/index.js +3 -0
- package/utils/index.js.map +1 -1
- package/utils/mergeLintConfig.d.ts +10 -0
- package/utils/mergeLintConfig.js +67 -0
- package/utils/mergeLintConfig.js.map +1 -0
- package/utils/parseLibnames.d.ts +33 -0
- package/utils/parseLibnames.js +237 -0
- package/utils/parseLibnames.js.map +1 -0
- package/utils/parseLintOverride.d.ts +36 -0
- package/utils/parseLintOverride.js +109 -0
- package/utils/parseLintOverride.js.map +1 -0
package/types/LintConfig.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LintConfig.js","sourceRoot":"","sources":["../../src/types/LintConfig.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"LintConfig.js","sourceRoot":"","sources":["../../src/types/LintConfig.ts"],"names":[],"mappings":"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"}
|
package/utils/getLintConfig.d.ts
CHANGED
|
@@ -2,26 +2,41 @@ 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
|
-
|
|
9
|
-
|
|
10
|
-
noEncodedPasswords: boolean;
|
|
13
|
+
allowedGremlins: never[];
|
|
14
|
+
defaultHeader: string;
|
|
11
15
|
hasDoxygenHeader: boolean;
|
|
12
|
-
|
|
16
|
+
hasMacroNameInMend: boolean;
|
|
17
|
+
hasMacroParentheses: boolean;
|
|
18
|
+
hasRequiredMacroOptions: boolean;
|
|
19
|
+
ignoreList: never[];
|
|
20
|
+
ignoredLibnames: never[];
|
|
21
|
+
indentationMultiple: number;
|
|
22
|
+
lineEndings: LineEndings;
|
|
13
23
|
lowerCaseFileNames: boolean;
|
|
14
|
-
maxLineLength: number;
|
|
15
|
-
maxHeaderLineLength: number;
|
|
16
24
|
maxDataLineLength: number;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
25
|
+
maxHeaderLineLength: number;
|
|
26
|
+
maxLineLength: number;
|
|
27
|
+
noEncodedPasswords: boolean;
|
|
28
|
+
noGremlins: boolean;
|
|
20
29
|
noNestedMacros: boolean;
|
|
21
|
-
|
|
30
|
+
noSingleAsteriskComments: boolean;
|
|
31
|
+
noSpacesInFileNames: boolean;
|
|
32
|
+
noTabs: boolean;
|
|
33
|
+
noTrailingSpaces: boolean;
|
|
34
|
+
noUndeclaredMacros: boolean;
|
|
35
|
+
noUnusedLibnames: boolean;
|
|
36
|
+
noUnusedMacros: boolean;
|
|
37
|
+
requiredMacroOptions: never[];
|
|
38
|
+
severityLevel: {};
|
|
22
39
|
strictMacroDefinition: boolean;
|
|
23
|
-
noGremlins: boolean;
|
|
24
|
-
defaultHeader: string;
|
|
25
40
|
};
|
|
26
41
|
/**
|
|
27
42
|
* Fetches the config from the .sasjslint file (at project root or home directory) and creates a LintConfig object.
|
package/utils/getLintConfig.js
CHANGED
|
@@ -23,26 +23,41 @@ 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
|
-
|
|
30
|
-
|
|
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
|
-
|
|
39
|
+
hasRequiredMacroOptions: false,
|
|
40
|
+
ignoreList: [],
|
|
41
|
+
ignoredLibnames: [],
|
|
42
|
+
indentationMultiple: 2,
|
|
43
|
+
lineEndings: LineEndings_1.LineEndings.OFF,
|
|
44
|
+
lowerCaseFileNames: true,
|
|
45
|
+
maxDataLineLength: 80,
|
|
46
|
+
maxHeaderLineLength: 80,
|
|
47
|
+
maxLineLength: 80,
|
|
48
|
+
noEncodedPasswords: true,
|
|
44
49
|
noGremlins: true,
|
|
45
|
-
|
|
50
|
+
noNestedMacros: true,
|
|
51
|
+
noSingleAsteriskComments: false,
|
|
52
|
+
noSpacesInFileNames: true,
|
|
53
|
+
noTabs: true,
|
|
54
|
+
noTrailingSpaces: true,
|
|
55
|
+
noUndeclaredMacros: true,
|
|
56
|
+
noUnusedLibnames: false,
|
|
57
|
+
noUnusedMacros: true,
|
|
58
|
+
requiredMacroOptions: [],
|
|
59
|
+
severityLevel: {},
|
|
60
|
+
strictMacroDefinition: true
|
|
46
61
|
};
|
|
47
62
|
/**
|
|
48
63
|
* 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":";;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"getLintConfig.js","sourceRoot":"","sources":["../../src/utils/getLintConfig.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAqDA,sCASC;AA9DD,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,eAAe,EAAE,EAAE;IACnB,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"}
|
package/utils/index.d.ts
CHANGED
|
@@ -9,5 +9,8 @@ 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 './parseLibnames';
|
|
14
|
+
export * from './parseLintOverride';
|
|
12
15
|
export * from './parseMacroCalls';
|
|
13
16
|
export * from './sasMacros';
|
package/utils/index.js
CHANGED
|
@@ -25,6 +25,9 @@ __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("./parseLibnames"), exports);
|
|
30
|
+
__exportStar(require("./parseLintOverride"), exports);
|
|
28
31
|
__exportStar(require("./parseMacroCalls"), exports);
|
|
29
32
|
__exportStar(require("./sasMacros"), exports);
|
|
30
33
|
//# sourceMappingURL=index.js.map
|
package/utils/index.js.map
CHANGED
|
@@ -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,kDAA+B;AAC/B,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,33 @@
|
|
|
1
|
+
import { LintConfig } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* A LIBNAME assignment found in a file, with the position of its libref.
|
|
4
|
+
*/
|
|
5
|
+
export interface LibnameAssignment {
|
|
6
|
+
libref: string;
|
|
7
|
+
lineNumber: number;
|
|
8
|
+
startColumnNumber: number;
|
|
9
|
+
endColumnNumber: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Finds the LIBNAME statements in a file that assign a libref.
|
|
13
|
+
*
|
|
14
|
+
* @param {string} text - the text content of the file.
|
|
15
|
+
* @param {LintConfig} config - the lint configuration. It is accepted for
|
|
16
|
+
* symmetry with the other utilities and is not used by the scan.
|
|
17
|
+
* @returns {LibnameAssignment[]} the assignments, in the order they appear.
|
|
18
|
+
*/
|
|
19
|
+
export declare const parseLibnames: (text: string, config?: LintConfig) => LibnameAssignment[];
|
|
20
|
+
/**
|
|
21
|
+
* Finds the librefs a file assigns and never mentions again.
|
|
22
|
+
*
|
|
23
|
+
* A mention is any occurrence of the libref outside a LIBNAME statement, which
|
|
24
|
+
* includes the indirect forms SAS accepts: `pathname(TESTWORK)`,
|
|
25
|
+
* `pathname("outData", "L")`, `library=path2`, `fmtsearch=(path1 path2)` and
|
|
26
|
+
* `%mfv_getcaslib(castest)`. The test is deliberately generous, because a use
|
|
27
|
+
* that is missed becomes a false positive.
|
|
28
|
+
*
|
|
29
|
+
* @param {string} text - the text content of the file.
|
|
30
|
+
* @param {LintConfig} config - the lint configuration.
|
|
31
|
+
* @returns {LibnameAssignment[]} the assignments that look unused.
|
|
32
|
+
*/
|
|
33
|
+
export declare const getUnusedLibnames: (text: string, config?: LintConfig) => LibnameAssignment[];
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getUnusedLibnames = exports.parseLibnames = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Matches a LIBNAME statement, capturing the libref and the rest of the
|
|
6
|
+
* statement. A statement starts at the start of the file or after a `;`.
|
|
7
|
+
*/
|
|
8
|
+
const libnameStatement = /(?:^|;)\s*libname\s+([a-z_][a-z0-9_]*)([^;]*)/gi;
|
|
9
|
+
/** Matches the options that report or deassign a libref, rather than assign it. */
|
|
10
|
+
const nonAssigningOption = /^\s*(clear|list)\b/i;
|
|
11
|
+
/** Matches the reporting form, which names no libref. */
|
|
12
|
+
const allLibrefs = /^_all_$/i;
|
|
13
|
+
/**
|
|
14
|
+
* Replaces the regions that cannot hold a libref with spaces, keeping every
|
|
15
|
+
* other offset in place.
|
|
16
|
+
*
|
|
17
|
+
* Block comments, macro comments, comment statements and single-quoted strings
|
|
18
|
+
* are opaque. The content of a double-quoted string is kept, because SAS takes a
|
|
19
|
+
* libref as a string as often as a two-level name - `pathname("outData", "L")`
|
|
20
|
+
* uses the libref just as much as `outData.member` does.
|
|
21
|
+
*/
|
|
22
|
+
const blankNonCode = (text) => {
|
|
23
|
+
const chars = text.split('');
|
|
24
|
+
const length = text.length;
|
|
25
|
+
let index = 0;
|
|
26
|
+
let atStatementStart = true;
|
|
27
|
+
const blank = (from, to) => {
|
|
28
|
+
for (let at = from; at < to && at < length; at++) {
|
|
29
|
+
if (chars[at] !== '\n')
|
|
30
|
+
chars[at] = ' ';
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
while (index < length) {
|
|
34
|
+
const char = text[index];
|
|
35
|
+
if (char === '\n') {
|
|
36
|
+
index++;
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
// Single-quoted string - opaque. `''` is an escaped quote character.
|
|
40
|
+
if (char === "'") {
|
|
41
|
+
let end = index + 1;
|
|
42
|
+
while (end < length) {
|
|
43
|
+
if (text[end] === "'") {
|
|
44
|
+
if (text[end + 1] === "'") {
|
|
45
|
+
end += 2;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
end++;
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
if (text[end] === '\n')
|
|
52
|
+
break;
|
|
53
|
+
end++;
|
|
54
|
+
}
|
|
55
|
+
blank(index, end);
|
|
56
|
+
index = end;
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
// Double-quoted string - its content is kept, so a libref inside it counts
|
|
60
|
+
// as a mention, but any `;` is masked. A semicolon inside a string is not a
|
|
61
|
+
// statement boundary, and leaving it in place would invent one, so a
|
|
62
|
+
// `libname` inside generated-code text would read as a real assignment.
|
|
63
|
+
// `""` is an escaped quote character.
|
|
64
|
+
if (char === '"') {
|
|
65
|
+
let end = index + 1;
|
|
66
|
+
while (end < length) {
|
|
67
|
+
if (text[end] === '"') {
|
|
68
|
+
if (text[end + 1] === '"') {
|
|
69
|
+
end += 2;
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
end++;
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
if (text[end] === '\n')
|
|
76
|
+
break;
|
|
77
|
+
end++;
|
|
78
|
+
}
|
|
79
|
+
for (let at = index; at < end; at++) {
|
|
80
|
+
if (chars[at] === ';')
|
|
81
|
+
chars[at] = ' ';
|
|
82
|
+
}
|
|
83
|
+
index = end;
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
if (char === '/' && text[index + 1] === '*') {
|
|
87
|
+
const close = text.indexOf('*/', index + 2);
|
|
88
|
+
const end = close === -1 ? length : close + 2;
|
|
89
|
+
blank(index, end);
|
|
90
|
+
index = end;
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
if (char === '%' && text[index + 1] === '*') {
|
|
94
|
+
const close = text.indexOf(';', index + 2);
|
|
95
|
+
const end = close === -1 ? length : close + 1;
|
|
96
|
+
blank(index, end);
|
|
97
|
+
index = end;
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
if (char === ';') {
|
|
101
|
+
atStatementStart = true;
|
|
102
|
+
index++;
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
if (/\s/.test(char)) {
|
|
106
|
+
index++;
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
// Comment statement - its body is opaque up to the terminating `;`.
|
|
110
|
+
if (atStatementStart && char === '*') {
|
|
111
|
+
const close = text.indexOf(';', index + 1);
|
|
112
|
+
const end = close === -1 ? length : close + 1;
|
|
113
|
+
blank(index, end);
|
|
114
|
+
index = end;
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
atStatementStart = false;
|
|
118
|
+
index++;
|
|
119
|
+
}
|
|
120
|
+
return chars.join('');
|
|
121
|
+
};
|
|
122
|
+
/** Replaces each span with spaces, keeping every other offset in place. */
|
|
123
|
+
const blankSpans = (code, spans) => {
|
|
124
|
+
const chars = code.split('');
|
|
125
|
+
spans.forEach(({ start, end }) => {
|
|
126
|
+
for (let at = start; at < end && at < chars.length; at++) {
|
|
127
|
+
if (chars[at] !== '\n')
|
|
128
|
+
chars[at] = ' ';
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
return chars.join('');
|
|
132
|
+
};
|
|
133
|
+
/** The offset of the first character of each line. */
|
|
134
|
+
const lineStarts = (text) => {
|
|
135
|
+
const starts = [0];
|
|
136
|
+
for (let index = 0; index < text.length; index++) {
|
|
137
|
+
if (text[index] === '\n')
|
|
138
|
+
starts.push(index + 1);
|
|
139
|
+
}
|
|
140
|
+
return starts;
|
|
141
|
+
};
|
|
142
|
+
/** Converts an offset into a one-based line and column. */
|
|
143
|
+
const positionOf = (starts, offset) => {
|
|
144
|
+
let line = 0;
|
|
145
|
+
while (line + 1 < starts.length && starts[line + 1] <= offset)
|
|
146
|
+
line++;
|
|
147
|
+
return { lineNumber: line + 1, columnNumber: offset - starts[line] + 1 };
|
|
148
|
+
};
|
|
149
|
+
/** True when the libref appears in the code outside a LIBNAME statement. */
|
|
150
|
+
const isMentioned = (code, libref) => new RegExp(`(^|[^a-z0-9_])${libref}([^a-z0-9_]|$)`, 'i').test(code);
|
|
151
|
+
/**
|
|
152
|
+
* Finds the statements in `code` that assign a libref, with the offset of each
|
|
153
|
+
* statement.
|
|
154
|
+
*
|
|
155
|
+
* A statement assigns when it names a libref and carries options -
|
|
156
|
+
* `libname outData "&dirOut.";` assigns, while `libname outData;` deassigns,
|
|
157
|
+
* `libname outData clear;` deassigns and `libname outData list;` reports. The
|
|
158
|
+
* reporting form `libname _all_ list;` names no libref. A libref built at
|
|
159
|
+
* runtime (`libname &lib;`) is not a literal, so there is nothing to check.
|
|
160
|
+
*
|
|
161
|
+
* A libref assigned more than once is reported once, at its first assignment.
|
|
162
|
+
*/
|
|
163
|
+
const findAssignments = (text, code) => {
|
|
164
|
+
const assignments = [];
|
|
165
|
+
const spans = [];
|
|
166
|
+
const starts = lineStarts(text);
|
|
167
|
+
const reported = new Set();
|
|
168
|
+
let match;
|
|
169
|
+
libnameStatement.lastIndex = 0;
|
|
170
|
+
while ((match = libnameStatement.exec(code)) !== null) {
|
|
171
|
+
const libref = match[1];
|
|
172
|
+
const options = match[2];
|
|
173
|
+
if (allLibrefs.test(libref))
|
|
174
|
+
continue;
|
|
175
|
+
if (!options.trim() || nonAssigningOption.test(options))
|
|
176
|
+
continue;
|
|
177
|
+
// The statement runs to the `;` that closed it, or to the end of the file.
|
|
178
|
+
const close = code.indexOf(';', match.index + match[0].length);
|
|
179
|
+
const end = close === -1 ? code.length : close + 1;
|
|
180
|
+
spans.push({ start: match.index, end });
|
|
181
|
+
const key = libref.toLowerCase();
|
|
182
|
+
if (reported.has(key))
|
|
183
|
+
continue;
|
|
184
|
+
reported.add(key);
|
|
185
|
+
const offset = match.index + match[0].length - options.length - libref.length;
|
|
186
|
+
const { lineNumber, columnNumber } = positionOf(starts, offset);
|
|
187
|
+
assignments.push({
|
|
188
|
+
libref,
|
|
189
|
+
lineNumber,
|
|
190
|
+
startColumnNumber: columnNumber,
|
|
191
|
+
endColumnNumber: columnNumber + libref.length
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
return { assignments, spans };
|
|
195
|
+
};
|
|
196
|
+
/**
|
|
197
|
+
* Finds the LIBNAME statements in a file that assign a libref.
|
|
198
|
+
*
|
|
199
|
+
* @param {string} text - the text content of the file.
|
|
200
|
+
* @param {LintConfig} config - the lint configuration. It is accepted for
|
|
201
|
+
* symmetry with the other utilities and is not used by the scan.
|
|
202
|
+
* @returns {LibnameAssignment[]} the assignments, in the order they appear.
|
|
203
|
+
*/
|
|
204
|
+
const parseLibnames = (text, config) => {
|
|
205
|
+
if (!text)
|
|
206
|
+
return [];
|
|
207
|
+
return findAssignments(text, blankNonCode(text)).assignments;
|
|
208
|
+
};
|
|
209
|
+
exports.parseLibnames = parseLibnames;
|
|
210
|
+
/**
|
|
211
|
+
* Finds the librefs a file assigns and never mentions again.
|
|
212
|
+
*
|
|
213
|
+
* A mention is any occurrence of the libref outside a LIBNAME statement, which
|
|
214
|
+
* includes the indirect forms SAS accepts: `pathname(TESTWORK)`,
|
|
215
|
+
* `pathname("outData", "L")`, `library=path2`, `fmtsearch=(path1 path2)` and
|
|
216
|
+
* `%mfv_getcaslib(castest)`. The test is deliberately generous, because a use
|
|
217
|
+
* that is missed becomes a false positive.
|
|
218
|
+
*
|
|
219
|
+
* @param {string} text - the text content of the file.
|
|
220
|
+
* @param {LintConfig} config - the lint configuration.
|
|
221
|
+
* @returns {LibnameAssignment[]} the assignments that look unused.
|
|
222
|
+
*/
|
|
223
|
+
const getUnusedLibnames = (text, config) => {
|
|
224
|
+
if (!text)
|
|
225
|
+
return [];
|
|
226
|
+
const code = blankNonCode(text);
|
|
227
|
+
const { assignments, spans } = findAssignments(text, code);
|
|
228
|
+
if (!assignments.length)
|
|
229
|
+
return [];
|
|
230
|
+
// The assigning statements are blanked, so a libref does not count as a
|
|
231
|
+
// mention of itself. A statement that deassigns or reports a libref is left
|
|
232
|
+
// in place - it refers to a libref assigned somewhere else, so it is a mention.
|
|
233
|
+
const withoutAssignments = blankSpans(code, spans);
|
|
234
|
+
return assignments.filter(({ libref }) => !isMentioned(withoutAssignments, libref));
|
|
235
|
+
};
|
|
236
|
+
exports.getUnusedLibnames = getUnusedLibnames;
|
|
237
|
+
//# sourceMappingURL=parseLibnames.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parseLibnames.js","sourceRoot":"","sources":["../../src/utils/parseLibnames.ts"],"names":[],"mappings":"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"}
|
|
@@ -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;
|