ilib-lint 2.7.2 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -5
- package/package.json +6 -4
- package/src/FileType.js +172 -38
- package/src/LintableFile.js +105 -3
- package/src/ParserManager.js +47 -4
- package/src/PluginManager.js +51 -7
- package/src/Project.js +63 -17
- package/src/SerializerManager.js +155 -0
- package/src/TransformerManager.js +154 -0
- package/src/config/README.md +96 -4
- package/src/index.js +49 -8
- package/src/plugins/BuiltinPlugin.js +13 -1
- package/src/plugins/ErrorFilterTransformer.js +59 -0
- package/src/plugins/LineSerializer.js +6 -4
- package/src/plugins/XliffParser.js +0 -4
- package/src/plugins/XliffSerializer.js +4 -2
- package/src/plugins/string/StringFixCommand.js +2 -2
- package/src/plugins/string/StringParser.js +1 -1
- package/src/plugins/string/StringSerializer.js +7 -4
- package/src/rules/DeclarativeResourceRule.js +2 -2
- package/src/rules/LineRegexpChecker.js +1 -1
- package/src/rules/ResourceCamelCase.js +1 -3
- package/src/rules/ResourceDNTTerms.js +1 -1
- package/src/rules/ResourceEdgeWhitespace.js +1 -1
- package/src/rules/ResourceICUPluralTranslation.js +1 -1
- package/src/rules/ResourceRule.js +4 -4
- package/src/rules/ResourceSnakeCase.js +1 -3
- package/src/rules/ResourceSourceChecker.js +2 -2
- package/src/rules/ResourceTargetChecker.js +2 -2
- package/src/formatters/__tests__/ConfigBasedFormatter.test.js +0 -61
- package/src/rules/__tests__/ResourceCamelCase.test.js +0 -180
- package/src/rules/__tests__/ResourceSnakeCase.test.js +0 -187
package/README.md
CHANGED
|
@@ -20,9 +20,12 @@ This i18n linter differs from other static linters in the following ways:
|
|
|
20
20
|
a rule that checks that the translations in a resource file of a plural resource
|
|
21
21
|
contain the correct set of plural categories for the target language.
|
|
22
22
|
* It can load plugins
|
|
23
|
-
* Parsers -
|
|
24
|
-
* Formatters -
|
|
25
|
-
* Rules -
|
|
23
|
+
* Parsers - add parsers for new programming languages or resource file types
|
|
24
|
+
* Formatters - make the output look exactly the way you want
|
|
25
|
+
* Rules - add new rules declaratively or programmatically
|
|
26
|
+
* Fixers - apply auto-fixes to the file
|
|
27
|
+
* Transformers - transform the file in some way
|
|
28
|
+
* Serializers - serialize the file to a particular format
|
|
26
29
|
|
|
27
30
|
See the [release notes](./docs/ReleaseNotes.md) for details on what is
|
|
28
31
|
new and what has changed.
|
|
@@ -132,6 +135,17 @@ ilib-lint accepts the following command-line parameters:
|
|
|
132
135
|
of 2. There is no default minimum, so the linter will not give an exit code
|
|
133
136
|
unless this parameter is specified or unless one of the other limits is
|
|
134
137
|
exceeded.
|
|
138
|
+
* write - if a file is modified in memory during the linter run, write
|
|
139
|
+
the modified file contents back out to the file system. If the file was not
|
|
140
|
+
modified, it will not be written out. The file name of the file will be calculated
|
|
141
|
+
using the template property of the matching file type in the configuration.
|
|
142
|
+
* autoFix - apply any auto-fixes that go along with the rules that were applied to
|
|
143
|
+
each file. If a file is successfully fixed, it can be written out. The autoFix
|
|
144
|
+
flag implies the write flag.
|
|
145
|
+
* overwrite - If the file is modified by a Fixer or a Transformer and written
|
|
146
|
+
out using a Serializer, it will be written back to the original file, overwriting
|
|
147
|
+
it. The template property of the file type will be ignored. This option implies
|
|
148
|
+
the write flag.
|
|
135
149
|
|
|
136
150
|
If multiple limits are exceeded (maximum number of errors, warnings, or suggestions,
|
|
137
151
|
or minimum I18N score), the exit code will be the most severe amongst them
|
|
@@ -230,12 +244,15 @@ plugins, which allow the plugin to define multiple plugins. For example, many
|
|
|
230
244
|
plugins define multiple related rules at the same time which check for
|
|
231
245
|
different aspects of a string.
|
|
232
246
|
|
|
233
|
-
The linter plugin should override and implement these
|
|
247
|
+
The linter plugin should override and implement these methods:
|
|
234
248
|
|
|
235
249
|
- getParsers - return an array of classes that inherit from the Parser class
|
|
236
250
|
- getRules - return an array of classes that inherit from the Rule class
|
|
237
251
|
- getRuleSets - return an array of named rule sets that define which rules to use
|
|
252
|
+
- getFixers - return an array of classes that inherit from the Fixer class
|
|
238
253
|
- getFormatters - return an array of classes that inherit from the Formatter class
|
|
254
|
+
- getTransformers - return an array of classes that inherit from the Transformer class
|
|
255
|
+
- getSerializers - return an array of classes that inherit from the Serializer class
|
|
239
256
|
|
|
240
257
|
For rules and formatters, each array entry can be either declarative or
|
|
241
258
|
programmatic. See the descriptions below about declarative and programmatic
|
|
@@ -570,7 +587,7 @@ ilib-lint plugins from v1 of ilib-lint to v2.
|
|
|
570
587
|
|
|
571
588
|
## License
|
|
572
589
|
|
|
573
|
-
Copyright © 2022-
|
|
590
|
+
Copyright © 2022-2025, JEDLSoft
|
|
574
591
|
|
|
575
592
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
576
593
|
you may not use this file except in compliance with the License.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ilib-lint",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.8.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./src/index.js",
|
|
6
6
|
"module": "./src/index.js",
|
|
@@ -50,6 +50,7 @@
|
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@tsconfig/node14": "^14.1.2",
|
|
53
|
+
"@types/jest": "^29.5.14",
|
|
53
54
|
"@types/node": "^14.0.0",
|
|
54
55
|
"docdash": "^2.0.2",
|
|
55
56
|
"i18nlint-plugin-test-old": "file:test/i18nlint-plugin-test-old",
|
|
@@ -62,7 +63,6 @@
|
|
|
62
63
|
},
|
|
63
64
|
"dependencies": {
|
|
64
65
|
"@formatjs/intl": "^2.10.4",
|
|
65
|
-
"ilib-locale": "^1.2.2",
|
|
66
66
|
"ilib-localeinfo": "^1.1.0",
|
|
67
67
|
"intl-messageformat": "^10.5",
|
|
68
68
|
"json5": "^2.2.3",
|
|
@@ -70,11 +70,13 @@
|
|
|
70
70
|
"micromatch": "^4.0.7",
|
|
71
71
|
"options-parser": "^0.4.0",
|
|
72
72
|
"xml-js": "^1.6.11",
|
|
73
|
+
"ilib-lint-common": "^3.2.0",
|
|
73
74
|
"ilib-common": "^1.1.6",
|
|
74
|
-
"ilib-
|
|
75
|
-
"ilib-
|
|
75
|
+
"ilib-locale": "^1.2.4",
|
|
76
|
+
"ilib-tools-common": "^1.14.0"
|
|
76
77
|
},
|
|
77
78
|
"scripts": {
|
|
79
|
+
"coverage": "pnpm test -- --coverage",
|
|
78
80
|
"test": "pnpm test:jest",
|
|
79
81
|
"test:jest": "LANG=en_US.UTF8 node --trace-warnings --experimental-vm-modules node_modules/jest/bin/jest.js",
|
|
80
82
|
"test:watch": "pnpm test:jest --watch",
|
package/src/FileType.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* FileType.js - Represents a type of file in an ilib-lint project
|
|
3
3
|
*
|
|
4
|
-
* Copyright © 2023-
|
|
4
|
+
* Copyright © 2023-2025 JEDLSoft
|
|
5
5
|
*
|
|
6
6
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
7
|
* you may not use this file except in compliance with the License.
|
|
@@ -33,33 +33,79 @@ const logger = log4js.getLogger("ilib-lint.FileType");
|
|
|
33
33
|
*/
|
|
34
34
|
class FileType {
|
|
35
35
|
/**
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
|
|
36
|
+
* The lint project that this file is a part of.
|
|
37
|
+
* @type {Project}
|
|
38
|
+
*/
|
|
39
|
+
project;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* The name or glob spec for this file type
|
|
43
|
+
* @type {String|undefined}
|
|
44
|
+
*/
|
|
45
|
+
name;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* The list of locales to use with this file type
|
|
49
|
+
* @type {Array.<String>|undefined}
|
|
50
|
+
*/
|
|
51
|
+
locales;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* The intermediate representation type of this file type.
|
|
55
|
+
* @type {String}
|
|
56
|
+
*/
|
|
57
|
+
type;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* The array of names of classes of parsers to use with this file type.
|
|
61
|
+
* @type {Array.<String>|undefined}
|
|
62
|
+
*/
|
|
63
|
+
parsers = undefined;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* The array of classes of parsers to use with this file type.
|
|
67
|
+
* @type {Array.<Class>|undefined}
|
|
68
|
+
*/
|
|
69
|
+
parserClasses = undefined;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* The array of names of transformers to use with this file type.
|
|
73
|
+
* @type {Array.<String>|undefined}
|
|
74
|
+
*/
|
|
75
|
+
transformers = undefined;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* The array of instances of transformers to use with this file type.
|
|
79
|
+
* @type {Array.<Transformer>|undefined}
|
|
80
|
+
*/
|
|
81
|
+
transformerInstances = undefined;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* The serializer to use with this file type.
|
|
85
|
+
* @type {String|undefined}
|
|
86
|
+
*/
|
|
87
|
+
serializer = undefined;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* The instance of the serializer to use with this file type.
|
|
91
|
+
* @type {Serializer|undefined}
|
|
92
|
+
*/
|
|
93
|
+
serializerInst = undefined;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* The array of rule sets to apply to files of this type.
|
|
97
|
+
* @type {Array<String>|undefined}
|
|
98
|
+
*/
|
|
99
|
+
ruleset = undefined;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* The path template for this file type.
|
|
103
|
+
* @type {String|undefined}
|
|
104
|
+
*/
|
|
105
|
+
template = undefined;
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Contructor a new instance of a file type.
|
|
63
109
|
*
|
|
64
110
|
* The array of parsers will be used to attempt to parse each
|
|
65
111
|
* source file. If a parser throws an exception/error while parsing,
|
|
@@ -70,19 +116,59 @@ class FileType {
|
|
|
70
116
|
*
|
|
71
117
|
* @param {Object} options the options governing the construction
|
|
72
118
|
* of this file type as documented above
|
|
119
|
+
* @param {String} options.name the name or glob spec for this file type
|
|
120
|
+
* @param {Project} options.project the Project that this file type is a part of
|
|
121
|
+
* @param {Array.<String>} [options.locales] list of locales to use with this file type
|
|
122
|
+
* @param {String} [options.template] the path name template for this file type
|
|
123
|
+
* which shows how to extract the locale from the path
|
|
124
|
+
* name if the path includes it. Many file types
|
|
125
|
+
* do not include the locale in the path, and in those cases,
|
|
126
|
+
* the template can be left out. If a serializer is specified, then the template
|
|
127
|
+
* is also used by the serializer to determine how to name the output files.
|
|
128
|
+
* @param {Array.<String>} [options.parsers] an array of names of parsers to
|
|
129
|
+
* apply to this file type. The first parser is the most important one, as its
|
|
130
|
+
* type will be used to determine the type of intermediate representation, the
|
|
131
|
+
* type of the rules, and the type of the transformers and serializer. If no
|
|
132
|
+
* parsers are specified, then the parser manager will be asked to find all
|
|
133
|
+
* parsers that can parse files of this type.
|
|
134
|
+
* @param {Array.<String>} [options.ruleset] a list of rule set names
|
|
135
|
+
* to use with this file type. Only rules in these rule sets that operate
|
|
136
|
+
* on the same type of intermediate representation as the parsers will
|
|
137
|
+
* be applied to the file.
|
|
138
|
+
* @param {Array.<String>} [options.transformers] an array of transformer names
|
|
139
|
+
* to apply to files of this type after the rules have been applied. Every transformer
|
|
140
|
+
* must operate on the same type of intermediate representation as the parser.
|
|
141
|
+
* @param {String|Object} [options.serializer] the name of the serializer to use if
|
|
142
|
+
* the file has been modified by a transformer or a fixer. The serializer must
|
|
143
|
+
* operate on the same type of intermediate representation as the parser.
|
|
73
144
|
* @constructor
|
|
145
|
+
* @throws {Error} if a transformer or serializer is specified that does not
|
|
146
|
+
* operate on the same type of intermediate representation as the parser, or
|
|
147
|
+
* if a parser, transformer, or serializer cannot be found.
|
|
74
148
|
*/
|
|
75
149
|
constructor(options) {
|
|
76
150
|
if (!options || !options.name || !options.project) {
|
|
77
151
|
throw "Missing required options to the FileType constructor";
|
|
78
152
|
}
|
|
79
|
-
["name", "project", "locales", "ruleset", "template", "
|
|
153
|
+
["name", "project", "locales", "ruleset", "template", "parsers", "transformers", "serializer"].forEach(prop => {
|
|
80
154
|
if (typeof(options[prop]) !== 'undefined') {
|
|
81
155
|
this[prop] = options[prop];
|
|
82
156
|
}
|
|
83
157
|
});
|
|
84
158
|
|
|
85
|
-
|
|
159
|
+
if (this.parsers) {
|
|
160
|
+
const parserMgr = this.project.getParserManager();
|
|
161
|
+
this.parserClasses = this.parsers.map(parserName => {
|
|
162
|
+
const parser = parserMgr.getByName(parserName);
|
|
163
|
+
if (!parser) {
|
|
164
|
+
throw `Could not find parser ${parserName} named in the configuration for filetype ${this.name}`;
|
|
165
|
+
}
|
|
166
|
+
if (!this.type) {
|
|
167
|
+
this.type = parserMgr.getType(parserName);
|
|
168
|
+
}
|
|
169
|
+
return parser;
|
|
170
|
+
});
|
|
171
|
+
}
|
|
86
172
|
|
|
87
173
|
if (this.ruleset) {
|
|
88
174
|
if (typeof(this.ruleset) === 'string') {
|
|
@@ -100,16 +186,44 @@ class FileType {
|
|
|
100
186
|
}
|
|
101
187
|
}
|
|
102
188
|
|
|
103
|
-
if (this.
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
189
|
+
if (this.transformers) {
|
|
190
|
+
const names = Array.isArray(this.transformers) ? this.transformers : [ this.transformers ];
|
|
191
|
+
const transformerMgr = this.project.getTransformerManager();
|
|
192
|
+
this.transformerInstances = names.map(transformerName => {
|
|
193
|
+
const transformer = transformerMgr.get(transformerName);
|
|
194
|
+
if (!transformer) {
|
|
195
|
+
throw `Could not find transformer ${transformerName} named in the configuration for filetype ${this.name}`;
|
|
109
196
|
}
|
|
110
|
-
|
|
197
|
+
const transformerType = transformer.getType();
|
|
198
|
+
if (!this.type) {
|
|
199
|
+
this.type = transformerType;
|
|
200
|
+
} else if (transformerType !== this.type) {
|
|
201
|
+
throw new Error(`The transformer ${transformerName} processes representations of type ${transformerType}, but the filetype ${this.name} handles representations of type ${this.type}. The two types must match.`);
|
|
202
|
+
}
|
|
203
|
+
return transformer;
|
|
111
204
|
});
|
|
112
205
|
}
|
|
206
|
+
|
|
207
|
+
if (this.serializer) {
|
|
208
|
+
// if it is a string, then that string is the name of the serializer. If it is an object,
|
|
209
|
+
// then it the name and the settings to pass to the the serializer constructor.
|
|
210
|
+
const name = typeof(this.serializer) === 'string' ? this.serializer : this.serializer.name;
|
|
211
|
+
const serializerMgr = this.project.getSerializerManager();
|
|
212
|
+
this.serializerInst = serializerMgr.get(name, this.serializer);
|
|
213
|
+
if (!this.serializerInst) {
|
|
214
|
+
throw new Error(`Could not find or instantiate serializer ${this.serializer} named in the configuration for filetype ${this.name}`);
|
|
215
|
+
}
|
|
216
|
+
const serializerType = this.serializerInst.getType();
|
|
217
|
+
if (!this.type) {
|
|
218
|
+
this.type = serializerType;
|
|
219
|
+
} else if (serializerType !== this.type) {
|
|
220
|
+
throw new Error(`The serializer ${name} processes representations of type ${serializerType}, but the filetype ${this.name} handles representations of type ${this.type}. The two types must match.`);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (!this.type) {
|
|
225
|
+
this.type = "string";
|
|
226
|
+
}
|
|
113
227
|
}
|
|
114
228
|
|
|
115
229
|
getName() {
|
|
@@ -195,6 +309,26 @@ class FileType {
|
|
|
195
309
|
this.rules = set.getRules();
|
|
196
310
|
return this.rules;
|
|
197
311
|
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Return the list of transformers to use with this file type.
|
|
315
|
+
*
|
|
316
|
+
* @returns {Array.<Transformer>|undefined} an array of transformer instances to use
|
|
317
|
+
* with this file type, or undefined if there are none.
|
|
318
|
+
*/
|
|
319
|
+
getTransformers() {
|
|
320
|
+
return this.transformerInstances;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Return an instance of the serializer class for this file type.
|
|
325
|
+
*
|
|
326
|
+
* @returns {Serializer|undefined} an instance of the serializer class for this
|
|
327
|
+
* file type or undefined if there is no serializer for this file type.
|
|
328
|
+
*/
|
|
329
|
+
getSerializer() {
|
|
330
|
+
return this.serializerInst;
|
|
331
|
+
}
|
|
198
332
|
}
|
|
199
333
|
|
|
200
|
-
export default FileType;
|
|
334
|
+
export default FileType;
|
package/src/LintableFile.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* LintableFile.js - Represent a lintable source file
|
|
3
3
|
*
|
|
4
|
-
* Copyright © 2022-
|
|
4
|
+
* Copyright © 2022-2025 JEDLSoft
|
|
5
5
|
*
|
|
6
6
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
7
|
* you may not use this file except in compliance with the License.
|
|
@@ -31,6 +31,36 @@ const logger = log4js.getLogger("ilib-lint.root.LintableFile");
|
|
|
31
31
|
* @class Represent a source file
|
|
32
32
|
*/
|
|
33
33
|
class LintableFile extends DirItem {
|
|
34
|
+
/**
|
|
35
|
+
* Whether the file has been modified since it was last written or since it was read.
|
|
36
|
+
* @type {boolean}
|
|
37
|
+
*/
|
|
38
|
+
dirty = false;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The list of parsers that can parse this file.
|
|
42
|
+
* @type {Parser[]}
|
|
43
|
+
*/
|
|
44
|
+
parsers = [];
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* The serializer for this file type.
|
|
48
|
+
* @type {Serializer|undefined}
|
|
49
|
+
*/
|
|
50
|
+
serializer;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* The file type of this source file
|
|
54
|
+
* @type {FileType}
|
|
55
|
+
*/
|
|
56
|
+
filetype;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* The intermediate representations of this file
|
|
60
|
+
* @type {IntermediateRepresentation[]}
|
|
61
|
+
*/
|
|
62
|
+
irs = [];
|
|
63
|
+
|
|
34
64
|
/**
|
|
35
65
|
* Construct a source file instance
|
|
36
66
|
* The options parameter can contain any of the following properties:
|
|
@@ -66,6 +96,8 @@ class LintableFile extends DirItem {
|
|
|
66
96
|
extension = extension.substring(1);
|
|
67
97
|
this.parsers = this.filetype.getParserClasses(extension);
|
|
68
98
|
}
|
|
99
|
+
this.transformers = this.filetype.getTransformers();
|
|
100
|
+
this.serializer = this.filetype.getSerializer();
|
|
69
101
|
}
|
|
70
102
|
|
|
71
103
|
/**
|
|
@@ -169,7 +201,7 @@ class LintableFile extends DirItem {
|
|
|
169
201
|
// and that any fixable results were produced
|
|
170
202
|
fixable.length > 0 &&
|
|
171
203
|
// and that the current parser is able to write
|
|
172
|
-
|
|
204
|
+
this.serializer &&
|
|
173
205
|
// and that the fixer for this type of IR is avaliable
|
|
174
206
|
(fixer = this.project.getFixerManager().get(ir.getType()))
|
|
175
207
|
) {
|
|
@@ -179,9 +211,13 @@ class LintableFile extends DirItem {
|
|
|
179
211
|
|
|
180
212
|
// check if anything had been applied
|
|
181
213
|
if (fixes.some((fix) => fix.applied)) {
|
|
214
|
+
// remember that a fix modified the file and that it needs to be
|
|
215
|
+
// written out to disk again after all fixes have been applied
|
|
216
|
+
this.dirty = true;
|
|
217
|
+
|
|
182
218
|
// fixer should modify the provided IR
|
|
183
219
|
// so tell current parser to write out the modified representation
|
|
184
|
-
|
|
220
|
+
this.sourceFile = this.serializer.serialize(irs);
|
|
185
221
|
|
|
186
222
|
// after writing out the fixed content, we want to reparse to see if any new issues appeared,
|
|
187
223
|
// while preserving the results that have been fixed so far;
|
|
@@ -238,6 +274,37 @@ class LintableFile extends DirItem {
|
|
|
238
274
|
return this.irs;
|
|
239
275
|
}
|
|
240
276
|
|
|
277
|
+
/**
|
|
278
|
+
* Set the intermediate representations of this file.
|
|
279
|
+
* @param {Array.<IntermediateRepresentation>} irs the intermediate representations
|
|
280
|
+
* of this file
|
|
281
|
+
*/
|
|
282
|
+
setIRs(irs) {
|
|
283
|
+
if (irs.every(ir => ir instanceof IntermediateRepresentation)) {
|
|
284
|
+
this.irs = irs;
|
|
285
|
+
} else {
|
|
286
|
+
// should never happen
|
|
287
|
+
throw new Error("Invalid intermediate representations provided to setIRs");
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Return whether or not the file has been modified since it was last written
|
|
293
|
+
* or since it was read.
|
|
294
|
+
* @returns {boolean} true if the file is dirty, false otherwise
|
|
295
|
+
*/
|
|
296
|
+
isDirty() {
|
|
297
|
+
return this.dirty;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Return the source file of this lintable file.
|
|
302
|
+
* @returns {SourceFile} the source file
|
|
303
|
+
*/
|
|
304
|
+
getSourceFile() {
|
|
305
|
+
return this.sourceFile;
|
|
306
|
+
}
|
|
307
|
+
|
|
241
308
|
/**
|
|
242
309
|
* Return the stats for the file after issues were found.
|
|
243
310
|
* @returns {FileStats} the stats for the current file
|
|
@@ -253,6 +320,41 @@ class LintableFile extends DirItem {
|
|
|
253
320
|
}
|
|
254
321
|
return fileStats;
|
|
255
322
|
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Return the file type of this file.
|
|
326
|
+
* @returns {FileType} the file type of this file
|
|
327
|
+
*/
|
|
328
|
+
getFileType() {
|
|
329
|
+
return this.filetype;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Apply the available transformers to the intermediate representations of this file.
|
|
334
|
+
* @param {Array.<Result>} results the results of the rules that were applied earlier
|
|
335
|
+
* in the pipeline, or undefined if there are no results or if the rules have not been
|
|
336
|
+
* applied yet
|
|
337
|
+
*/
|
|
338
|
+
applyTransformers(results) {
|
|
339
|
+
const transformers = this.filetype.getTransformers();
|
|
340
|
+
if (this.irs && this.irs.length > 0 && transformers && transformers.length > 0) {
|
|
341
|
+
// For each intermediate representation, attempt to apply every transformer.
|
|
342
|
+
// However, only those transformers that have the same type as the intermediate
|
|
343
|
+
// representation can be applied.
|
|
344
|
+
for (let i = 0; i < this.irs.length; i++) {
|
|
345
|
+
if (!this.irs[i]) continue;
|
|
346
|
+
transformers.forEach(transformer => {
|
|
347
|
+
if (this.irs[i].getType() === transformer.getType()) {
|
|
348
|
+
const newIR = transformer.transform(this.irs[i], results);
|
|
349
|
+
if (newIR) {
|
|
350
|
+
this.irs[i] = newIR;
|
|
351
|
+
this.dirty = true;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
256
358
|
}
|
|
257
359
|
|
|
258
360
|
export default LintableFile;
|
package/src/ParserManager.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* ParserManager.js - Factory to create and return the right parser for the file
|
|
3
3
|
*
|
|
4
|
-
* Copyright © 2022-
|
|
4
|
+
* Copyright © 2022-2025 JEDLSoft
|
|
5
5
|
*
|
|
6
6
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
7
|
* you may not use this file except in compliance with the License.
|
|
@@ -32,6 +32,21 @@ function getSuperClassName(obj) {
|
|
|
32
32
|
* knows about.
|
|
33
33
|
*/
|
|
34
34
|
class ParserManager {
|
|
35
|
+
/**
|
|
36
|
+
* Information about the parsers that this instance of ilib-lint knows about.
|
|
37
|
+
* Each entry in the object is a parser name and the value is an object
|
|
38
|
+
* with the properties:
|
|
39
|
+
* <ul>
|
|
40
|
+
* <li>description - a description of the parser</li>
|
|
41
|
+
* <li>type - the type of parser</li>
|
|
42
|
+
* <li>extensions - an array of file name extensions that this parser can handle</li>
|
|
43
|
+
* </ul>
|
|
44
|
+
*
|
|
45
|
+
* @type {Object}
|
|
46
|
+
* @private
|
|
47
|
+
*/
|
|
48
|
+
parserInfo = {};
|
|
49
|
+
|
|
35
50
|
/**
|
|
36
51
|
* Create a new parser manager instance.
|
|
37
52
|
* @params {Object} options options controlling the construction of this object
|
|
@@ -79,13 +94,22 @@ class ParserManager {
|
|
|
79
94
|
const p = new parser({
|
|
80
95
|
getLogger: log4js.getLogger.bind(log4js)
|
|
81
96
|
});
|
|
97
|
+
const name = p.getName();
|
|
98
|
+
if (this.parserInfo[name]) {
|
|
99
|
+
logger.debug(`Parser ${name} already exists. Cannot add twice. Ignoring.`);
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
this.parserInfo[name] = {
|
|
103
|
+
description: p.getDescription(),
|
|
104
|
+
type: p.getType(),
|
|
105
|
+
extensions: p.getExtensions()
|
|
106
|
+
};
|
|
82
107
|
for (const extension of p.getExtensions()) {
|
|
83
108
|
if (!this.parserCache[extension]) {
|
|
84
109
|
this.parserCache[extension] = [];
|
|
85
110
|
}
|
|
86
111
|
this.parserCache[extension].push(p);
|
|
87
112
|
}
|
|
88
|
-
this.descriptions[p.getName()] = p.getDescription();
|
|
89
113
|
this.parserByName[p.getName()] = p;
|
|
90
114
|
|
|
91
115
|
logger.trace(`Added parser to the parser manager.`);
|
|
@@ -102,10 +126,29 @@ class ParserManager {
|
|
|
102
126
|
* @returns {Object} the parser names and descriptions
|
|
103
127
|
*/
|
|
104
128
|
getDescriptions() {
|
|
105
|
-
|
|
129
|
+
let json = {};
|
|
130
|
+
Object.keys(this.parserInfo).forEach((name) => {
|
|
131
|
+
json[name] = this.parserInfo[name].description;
|
|
132
|
+
});
|
|
133
|
+
return json;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Return the type of the parser with the given name. The type is
|
|
138
|
+
* the type of intermediate represetnation that the parser produces.
|
|
139
|
+
*
|
|
140
|
+
* @param {String} name the name of the parser to get the type for
|
|
141
|
+
* @returns {String} the type of parser with the given name
|
|
142
|
+
*/
|
|
143
|
+
getType(name) {
|
|
144
|
+
return this.parserInfo[name].type;
|
|
106
145
|
}
|
|
107
146
|
|
|
108
|
-
|
|
147
|
+
/**
|
|
148
|
+
* Clear the parsers from the factory. This is only intended
|
|
149
|
+
* for use with the unit tests
|
|
150
|
+
* @private
|
|
151
|
+
*/
|
|
109
152
|
clear() {
|
|
110
153
|
this.parserCache = {};
|
|
111
154
|
}
|