@komaci/static-analyzer 242.1.0 → 242.1.3

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.
Files changed (3) hide show
  1. package/README.md +9 -0
  2. package/RULES.md +1253 -0
  3. package/package.json +6 -4
package/README.md ADDED
@@ -0,0 +1,9 @@
1
+ # Static Analyzer
2
+
3
+ This library is used to analyze LWC modules for compatibility with Komaci. This is used internally by `@komaci/esm-generator` to determine if code is valid to encapsulate within a Resolvable Module, and externally by ESLint to aid LWC developers in ensuring their components are written in a way that ensures that Komaci is able to prefetch data for offline-ability and performance.
4
+
5
+ ## Rules
6
+
7
+ There are a number of diagnostic rules that are produced when analyzing an LWC bundle with `@komaci/static-analyzer`. Diagnostics will be produced for each violation detected within a module bundle.
8
+
9
+ A detailed breakdown for the rules and how each can be addressed can be found in [RULES.md](./RULES.md).
package/RULES.md ADDED
@@ -0,0 +1,1253 @@
1
+ # Komaci Static Analyzer Rules
2
+
3
+ - [`komaci1001`: no-unresolved-parent-class-reference](#komaci1001-no-unresolved-parent-class-reference)
4
+ - [`komaci1002`: no-multiple-template-files](#komaci1002-no-multiple-template-files)
5
+ - [`komaci1003`: no-private-wire-config-property](#komaci1003-no-private-wire-config-property)
6
+ - [`komaci1004`: no-undefined-wire-config-property](#komaci1004-no-undefined-wire-config-property)
7
+ - [`komaci1006`: no-wire-configuration-property-using-output-of-non-primeable-wire](#komaci1006-no-wire-configuration-property-using-output-of-non-primeable-wire)
8
+ - [`komaci1007`: no-wire-adapter-of-resource-cannot-be-primed](#komaci1007-no-wire-adapter-of-resource-cannot-be-primed)
9
+ - [`komaci1008`: no-missing-resource-cannot-prime-wire-adapter](#komaci1008-no-missing-resource-cannot-prime-wire-adapter)
10
+ - [`komaci1009`: no-wire-config-property-uses-getter-function-returning-non-literal](#komaci1009-no-wire-config-property-uses-getter-function-returning-non-literal)
11
+ - [`komaci1010`: no-wire-config-property-uses-getter-function-returning-inaccessible-import](#komaci1010-no-wire-config-property-uses-getter-function-returning-inaccessible-import)
12
+ - [`komaci1011`: no-class-refers-to-parent-class-from-unsupported-namespace](#komaci1011-no-class-refers-to-parent-class-from-unsupported-namespace)
13
+ - [`komaci1012`: no-wire-config-property-uses-imported-artifact-from-unsupported-namespace](#komaci1012-no-wire-config-property-uses-imported-artifact-from-unsupported-namespace)
14
+ - [`komaci1013`: no-wire-config-references-non-local-property-reactive-value](#komaci1013-no-wire-config-references-non-local-property-reactive-value)
15
+ - [`komaci1014`: no-composition-on-unanalyzable-property-from-unresolvable-wire](#komaci1014-no-composition-on-unanalyzable-property-from-unresolvable-wire)
16
+ - [`komaci1015`: no-composition-on-unanalyzable-property-non-public](#komaci1015-no-composition-on-unanalyzable-property-non-public)
17
+ - [`komaci1016`: no-composition-on-unanalyzable-getter-property](#komaci1016-no-composition-on-unanalyzable-getter-property)
18
+ - [`komaci1017`: no-composition-on-unanalyzable-property-missing](#komaci1017-no-composition-on-unanalyzable-property-missing)
19
+ - [`komaci1018`: no-wire-config-property-circular-wire-dependency](#komaci1018-no-wire-config-property-circular-wire-dependency)
20
+ - [`komaci1022`: no-assignment-expression-assigns-value-to-member-variable](#komaci1022-no-assignment-expression-assigns-value-to-member-variable)
21
+ - [`komaci1023`: no-assignment-expression-for-external-components](#komaci1023-no-assignment-expression-for-external-components)
22
+ - [`komaci1024`: no-tagged-template-expression-contains-unsupported-namespace](#komaci1024-no-tagged-template-expression-contains-unsupported-namespace)
23
+ - [`komaci1025`: no-getter-contains-more-than-return-statement](#komaci1025-no-getter-contains-more-than-return-statement)
24
+ - [`komaci1026`: no-expression-contains-module-level-variable-ref](#komaci1026-no-expression-contains-module-level-variable-ref)
25
+ - [`komaci1027`: no-call-expression-references-unsupported-namespace](#komaci1027-no-call-expression-references-unsupported-namespace)
26
+ - [`komaci1028`: no-eval-usage](#komaci1028-no-eval-usage)
27
+ - [`komaci1029`: no-reference-to-class-functions](#komaci1029-no-reference-to-class-functions)
28
+ - [`komaci1030`: no-reference-to-module-functions](#komaci1030-no-reference-to-module-functions)
29
+ - [`komaci1031`: no-functions-declared-within-getter-method](#komaci1031-no-functions-declared-within-getter-method)
30
+ - [`komaci1032`: no-unsupported-member-variable-in-member-expression](#komaci1032-no-unsupported-member-variable-in-member-expression)
31
+ - [`komaci1033`: no-member-expression-reference-to-non-existent-member-variable](#komaci1033-no-member-expression-reference-to-non-existent-member-variable)
32
+ - [`komaci1034`: no-member-expression-reference-to-unsupported-namespace-reference](#komaci1034-no-member-expression-reference-to-unsupported-namespace-reference)
33
+ - [`komaci1035`: no-member-expression-contains-non-portable-identifier](#komaci1035-no-member-expression-contains-non-portable-identifier)
34
+ - [`komaci1036`: no-member-expression-reference-to-super-class](#komaci1036-no-member-expression-reference-to-super-class)
35
+ - [`komaci1037`: no-member-expression-reference-to-unsupported-global](#komaci1037-no-member-expression-reference-to-unsupported-global)
36
+ - [`komaci1038`: no-reference-to-unsupported-namespace-reference](#komaci1038-no-reference-to-unsupported-namespace-reference)
37
+
38
+ ## `komaci1001`: no-unresolved-parent-class-reference
39
+
40
+ | Code | Description | Message | Severity |
41
+ | ------------ | --------------------------------------------------------- | ----------------------------------------------- | -------- |
42
+ | `komaci1001` | Flags when a component extends from an unresolable class. | This class refers to an unresolved parent class | error |
43
+
44
+ ### ❌ Incorrect
45
+
46
+ ```js
47
+ const Foo = {}; // Not a class!
48
+ export default class Example extends Foo {} // flags
49
+ ```
50
+
51
+ ```js
52
+ // Foo is not defined
53
+ export default class Example extends Foo {} // flags
54
+ ```
55
+
56
+ ### ✅ Correct
57
+
58
+ ```js
59
+ import Foo from 'x/foo';
60
+
61
+ export default class Example extends Foo {}
62
+ ```
63
+
64
+ ### 😟 Limitations
65
+
66
+ Using mixins with a parent class are currently not supported.
67
+
68
+ ```js
69
+ import Foo from 'x/foo';
70
+ import Mixin from 'x/mixin';
71
+
72
+ export default class Example extends Mixin(Foo) {}
73
+ ```
74
+
75
+ ## `komaci1002`: no-multiple-template-files
76
+
77
+ | Code | Description | Message | Severity |
78
+ | ------------ | -------------------------------------------------------- | ------------------------------------------------------------------------ | -------- |
79
+ | `komaci1002` | Flags when a component is using multiple template files. | This analyzer does not support LWCs which render multiple template files | warning |
80
+
81
+ ### ❌ Incorrect
82
+
83
+ ```js
84
+ // example.js
85
+ import { LightningElement } from 'lwc';
86
+ import tmpl1 from './example.html';
87
+ import tmpl2 from './example.2.html';
88
+ export default class Example extends LightningElement {
89
+ @api someInput;
90
+ render() {
91
+ return this.someInput ? tmpl1 : tmpl2;
92
+ }
93
+ }
94
+ ```
95
+
96
+ ```html
97
+ <!-- example.html -->
98
+ <template></template>
99
+ ```
100
+
101
+ ```html
102
+ <!-- example.2.html -->
103
+ <template></template>
104
+ <!-- flags -->
105
+ ```
106
+
107
+ ### ✅ Correct
108
+
109
+ The only way to fix this is to not use multiple templates, or simply ignore the error.
110
+
111
+ ## `komaci1003`: no-private-wire-config-property
112
+
113
+ | Code | Description | Message | Severity |
114
+ | ------------ | ------------------------------------------------------------------------ | ------------------------------------------------------------- | -------- |
115
+ | `komaci1003` | Flags when a component is using a private property within a wire config. | This wire configuration uses a property '{0}' that is private | error |
116
+
117
+ ### ❌ Incorrect
118
+
119
+ Private properties used in wire configs are not resolvable.
120
+
121
+ ```js
122
+ import { LightningElement, wire } from 'lwc';
123
+ import { getRecord } from 'lightning/uiRecordApi';
124
+
125
+ export default class Example extends LightningElement {
126
+ recordId;
127
+
128
+ @wire(getRecord, { recordId: '$recordId' })
129
+ record;
130
+ }
131
+ ```
132
+
133
+ ### ✅ Correct
134
+
135
+ Make the property public.
136
+
137
+ ```js
138
+ import { LightningElement, wire, api } from 'lwc';
139
+ import { getRecord } from 'lightning/uiRecordApi';
140
+
141
+ export default class Example extends LightningElement {
142
+ @api recordId;
143
+
144
+ @wire(getRecord, { recordId: '$recordId' })
145
+ record;
146
+ }
147
+ ```
148
+
149
+ ### 😟 Limitations
150
+
151
+ Public properties decorated with `@api` cannot be reassigned.
152
+
153
+ ```js
154
+ import { LightningElement, wire, api } from 'lwc';
155
+ import { getRecord } from 'lightning/uiRecordApi';
156
+
157
+ export default class Example extends LightningElement {
158
+ recordId;
159
+
160
+ connectedCallback() {
161
+ this.recordId = '1234'; // Prevents recordId from being made public
162
+ }
163
+
164
+ @wire(getRecord, { recordId: '$recordId' })
165
+ record;
166
+ }
167
+ ```
168
+
169
+ ## `komaci1004`: no-undefined-wire-config-property
170
+
171
+ | Code | Description | Message | Severity |
172
+ | ------------ | ------------------------------------------- | ---------------------------------------------------------------- | -------- |
173
+ | `komaci1004` | **⛔️ This diagnostic is no longer valid.** | This wire configuration uses a property '{0}' which is undefined | warning |
174
+
175
+ ## `komaci1006`: no-wire-configuration-property-using-output-of-non-primeable-wire
176
+
177
+ | Code | Description | Message | Severity |
178
+ | ------------ | -------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | -------- |
179
+ | `komaci1006` | Flags when a wire's config is referencing the output of a wire that is not resolvable. | The wire configuration uses a property '{0}' that is the output of a non-primeable wire, making this wire non-primeable | error |
180
+
181
+ ### ❌ Incorrect
182
+
183
+ ```js
184
+ import { LightningElement, wire, api } from 'lwc';
185
+ import { invalid } from 'x/invalid';
186
+ im `komaci1007`:port { getObjectInfo } from 'lightning/uiObjectInfoApi';
187
+
188
+ export default class Example extends LightningElement {
189
+ // "invalid" is not a known wire, and thus is not primable
190
+ @wire(invalid, {}) // komaci1007: "The wire adapter 'invalid' of resource 'x/invalid' cannot be primed"
191
+ wiredOutput1;
192
+
193
+ // Since "invalid" is not primable, its output "wiredOutput1.data" cannot be used as input in another wire
194
+ @wire(getObjectInfo, { input: '$wiredOutput1.data' })
195
+ wiredOutput2;
196
+ }
197
+ ```
198
+
199
+ ### ✅ Correct
200
+
201
+ ```js
202
+ import { LightningElement, wire, api } from 'lwc';
203
+ import { getRecord } from 'lightning/uiRecordApi';
204
+ import { getObjectInfo } from 'lightning/uiObjectInfoApi';
205
+
206
+ export default class Example extends LightningElement {
207
+ // "getRecord" from "lightning/uiRecordApi" is a known wire, and thus primeable
208
+ @wire(getRecord, {})
209
+ wiredOutput1;
210
+
211
+ // valid
212
+ @wire(getObjectInfo, { input: '$wiredOutput1.data' })
213
+ wiredOutput2;
214
+ }
215
+ ```
216
+
217
+ ### Alternatives
218
+
219
+ This rule will flag if any wire is using input from another wire that's not primeable. Reference the diagnostic on the non-primeable wire's in order to address this issue.
220
+
221
+ ## `komaci1007`: no-wire-adapter-of-resource-cannot-be-primed
222
+
223
+ | Code | Description | Message | Severity |
224
+ | ------------ | ----------------------------------------- | --------------------------------------------------------- | -------- |
225
+ | `komaci1007` | Flags when an invalid wire is being used. | The wire adapter '{0}' of resource '{1}' cannot be primed | error |
226
+
227
+ ### ❌ Incorrect
228
+
229
+ Only wires from valid resources, such as [LDS wires](https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.reference_ui_api) in the `lightning` namespace, are allowed.
230
+
231
+ ```js
232
+ import { LightningElement, wire } from 'lwc';
233
+ import { invalid } from 'x/invalid';
234
+ import { alsoInvalid } from './invalid'; //
235
+
236
+ export default class Example extends LightningElement {
237
+ @wire(invalid, {})
238
+ wireOutput1;
239
+
240
+ @wire(alsoInvalid, {})
241
+ wireOutput2;
242
+ }
243
+ ```
244
+
245
+ ### ✅ Correct
246
+
247
+ ```js
248
+ import { LightningElement, wire } from 'lwc';
249
+ import { getRecord } from 'lightning/uiRecordApi';
250
+ import { getObjectInfo } from 'lightning/uiObjectInfoApi';
251
+
252
+ export default class Example extends LightningElement {
253
+ @wire(getRecord, {})
254
+ wireOutput1;
255
+
256
+ @wire(getObjectInfo, {})
257
+ wireOutput2;
258
+ }
259
+ ```
260
+
261
+ ### When To Ignore
262
+
263
+ If the wire you're using does not need to be primed for offline use.
264
+
265
+ ## `komaci1008`: no-missing-resource-cannot-prime-wire-adapter
266
+
267
+ | Code | Description | Message | Severity |
268
+ | ------------ | ------------------------------- | ------------------------------------------------------------------------- | -------- |
269
+ | `komaci1008` | Flags when wire is not defined. | The wire adapter cannot be primed because it refers to a missing resource | error |
270
+
271
+ ### ❌ Incorrect
272
+
273
+ ```js
274
+ import { LightningElement, wire } from 'lwc';
275
+
276
+ export default class ScriptTestClass extends LightningElement {
277
+ // getRecord has not been imported
278
+ @wire(getRecord, {})
279
+ record;
280
+ }
281
+ ```
282
+
283
+ ### ✅ Correct
284
+
285
+ ```js
286
+ import { LightningElement, wire } from 'lwc';
287
+ import { getRecord } from 'lightning/uiRecordApi';
288
+
289
+ export default class ScriptTestClass extends LightningElement {
290
+ @wire(getRecord, {})
291
+ record;
292
+ }
293
+ ```
294
+
295
+ ## `komaci1009`: no-wire-config-property-uses-getter-function-returning-non-literal
296
+
297
+ | Code | Description | Message | Severity |
298
+ | ------------ | --------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------- |
299
+ | `komaci1009` | Flags when a wire uses a getter that returns an unsupported value that's not a literal. | This wire configuration uses a property from a getter function named '{0}' that returns a non-literal | error |
300
+
301
+ ### ❌ Incorrect
302
+
303
+ ```js
304
+ import { LightningElement, wire } from 'lwc';
305
+ import { getRecord } from 'lightning/uiRecordApi';
306
+ export default class Example extends LightningElement {
307
+ prop; // unsupported
308
+ get value() {
309
+ return this.prop;
310
+ }
311
+
312
+ @wire(getRecord, { input: '$value' }) // flags
313
+ record;
314
+ }
315
+ ```
316
+
317
+ ### ✅ Correct
318
+
319
+ ```js
320
+ import { LightningElement, wire } from 'lwc';
321
+ import { getRecord } from 'lightning/uiRecordApi';
322
+ export default class Example extends LightningElement {
323
+ prop; // unsupported
324
+ get value() {
325
+ return this.prop;
326
+ }
327
+
328
+ @wire(getRecord, { input: '$value' }) // flags
329
+ record;
330
+ }
331
+ ```
332
+
333
+ ## `komaci1010`: no-wire-config-property-uses-getter-function-returning-inaccessible-import
334
+
335
+ | Code | Description | Message | Severity |
336
+ | ------------ | ---------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | -------- |
337
+ | `komaci1010` | Flags when an unknown resource is imported and used in a getter referenced by a wire's config. | This wire configuration uses a property from a getter function named '{0}' that returns an inaccessible import | error |
338
+
339
+ ### ❌ Incorrect
340
+
341
+ ```js
342
+ import { LightningElement, wire } from 'lwc';
343
+ import { getRecord } from 'lightning/uiRecordApi';
344
+ import { invalid } from 'x/invalid';
345
+
346
+ export default class ScriptTestClass extends LightningElement {
347
+ get label() {
348
+ return invalid;
349
+ }
350
+
351
+ @wire(getRecord, { label: '$label' })
352
+ record1;
353
+ }
354
+ ```
355
+
356
+ ### ✅ Correct
357
+
358
+ Only known resources, such as those imported from `@salesforce/*`, can be used in wires.
359
+
360
+ ```js
361
+ import { LightningElement, wire } from 'lwc';
362
+ import { getRecord } from 'lightning/uiRecordApi';
363
+ import myLabel from '@salesforce/label/My.Label';
364
+
365
+ export default class ScriptTestClass extends LightningElement {
366
+ get label() {
367
+ return myLabel;
368
+ }
369
+
370
+ @wire(getRecord, { label: '$label' })
371
+ record1;
372
+ }
373
+ ```
374
+
375
+ ## `komaci1011`: no-class-refers-to-parent-class-from-unsupported-namespace
376
+
377
+ | Code | Description | Message | Severity |
378
+ | ------------ | -------------------------------------------------------------- | ----------------------------------------------------------------- | -------- |
379
+ | `komaci1011` | Flags when the component extends from an invalid parent class. | This class refers to a parent class from an unsupported namespace | error |
380
+
381
+ ### ❌ Incorrect
382
+
383
+ ```js
384
+ import Foo from './foo';
385
+ export default class Example extends Foo {}
386
+ ```
387
+
388
+ ### ✅ Correct
389
+
390
+ ```js
391
+ import Foo from 'lightning/recordForm';
392
+
393
+ export default class Example extends Foo {}
394
+ ```
395
+
396
+ ## `komaci1012`: no-wire-config-property-uses-imported-artifact-from-unsupported-namespace
397
+
398
+ | Code | Description | Message | Severity |
399
+ | ------------ | ------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------- | -------- |
400
+ | `komaci1012` | Flags when a wire references an imported artifacted that is not from a supported resource. | This wire configuration uses an imported artifact '{0}' from unsupported namespace '{1}' | error |
401
+
402
+ ### ❌ Incorrect
403
+
404
+ ```js
405
+ import { LightningElement, wire, api } from 'lwc';
406
+ import { getRecord } from 'lightning/uiRecordApi';
407
+ import invalid from 'x/invalid';
408
+
409
+ export default class Example extends LightningElement {
410
+ @wire(getRecord, { label: invalid })
411
+ records;
412
+ }
413
+ ```
414
+
415
+ ### ✅ Correct
416
+
417
+ Only reference imported artifacts from `@salesforce/*`.
418
+
419
+ ```js
420
+ import { LightningElement, wire, api } from 'lwc';
421
+ import { getRecord } from 'lightning/uiRecordApi';
422
+ import label from '@salesforce/label/My.Label';
423
+
424
+ export default class Example extends LightningElement {
425
+ @wire(getRecord, { recordId: label })
426
+ records;
427
+ }
428
+ ```
429
+
430
+ ## `komaci1013`: no-wire-config-references-non-local-property-reactive-value
431
+
432
+ | Code | Description | Message | Severity |
433
+ | ------------ | ----------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | -------- |
434
+ | `komaci1013` | Flags when a wire config references a non-local property via dollar-sign syntax, e.g., '$prop'. | This wire configuration references a reactive value '{0}' that is not a local property | warning |
435
+
436
+ Wire configs that use the dollar-sign syntax must only reference component properties. It cannot reference imported values, or other values defined outside the component's class.
437
+
438
+ ### ❌ Incorrect
439
+
440
+ ```js
441
+ import { LightningElement, wire, api } from 'lwc';
442
+ import { getRecord } from 'lightning/uiRecordApi';
443
+ import label from '@salesforce/label/My.Label';
444
+
445
+ export default class Example extends LightningElement {
446
+ @wire(getRecord, { recordId: '$label' })
447
+ records;
448
+ }
449
+ ```
450
+
451
+ ### ✅ Correct
452
+
453
+ Try referencing the value directly.
454
+
455
+ ```js
456
+ import { LightningElement, wire, api } from 'lwc';
457
+ import { getRecord } from 'lightning/uiRecordApi';
458
+ import label from '@salesforce/label/My.Label';
459
+
460
+ export default class Example extends LightningElement {
461
+ @wire(getRecord, { recordId: label })
462
+ records;
463
+ }
464
+ ```
465
+
466
+ Or, try setting the value to a property before referencing.
467
+
468
+ ```js
469
+ import { LightningElement, wire, api } from 'lwc';
470
+ import { getRecord } from 'lightning/uiRecordApi';
471
+ import label from '@salesforce/label/My.Label';
472
+
473
+ export default class Example extends LightningElement {
474
+ @api label;
475
+ @wire(getRecord, { recordId: '$label' })
476
+ records;
477
+ }
478
+ ```
479
+
480
+ Or, try using a getter that returns the value.
481
+
482
+ ```js
483
+ import { LightningElement, wire, api } from 'lwc';
484
+ import { getRecord } from 'lightning/uiRecordApi';
485
+ import label from '@salesforce/label/My.Label';
486
+
487
+ export default class Example extends LightningElement {
488
+ get label() {
489
+ return label;
490
+ }
491
+ @wire(getRecord, { recordId: '$label' })
492
+ records;
493
+ }
494
+ ```
495
+
496
+ ## `komaci1014`: no-composition-on-unanalyzable-property-from-unresolvable-wire
497
+
498
+ | Code | Description | Message | Severity |
499
+ | ------------ | ----------------------------------------------------------------- | ---------------------------------------------------------------------------- | -------- |
500
+ | `komaci1014` | Flags when a property referenced in a template is not analyzable. | This {0} an unanalyzable property '{1}' that is wired by a unresolvable wire | error |
501
+
502
+ This flags when a template references a value that is not analyzable, such as invalid getter, or a wire output from an unsupported or unprimeable wire. Note, `{0}` in the message may reference iterators, image tags, or inputs to a child component.
503
+
504
+ ### ❌ Incorrect
505
+
506
+ ```js
507
+ import { LightningElement, wire, api } from 'lwc';
508
+ import { invalid } from 'x/invalid';
509
+ export default class Example extends LightningElement {
510
+ @wire(invalid, {})
511
+ wireOutput;
512
+ }
513
+ ```
514
+
515
+ ```html
516
+ <template>
517
+ <c-child input="{wireOutput}"></c-child>
518
+ </template>
519
+ ```
520
+
521
+ ### ✅ Correct
522
+
523
+ ```js
524
+ import { LightningElement, wire, api } from 'lwc';
525
+ import { getRecord } from 'lightning/uiRecordApi';
526
+ export default class Example extends LightningElement {
527
+ @wire(getRecord, {})
528
+ wireOutput;
529
+ }
530
+ ```
531
+
532
+ ```html
533
+ <template>
534
+ <c-child input="{wireOutput}"></c-child>
535
+ </template>
536
+ ```
537
+
538
+ ## `komaci1015`: no-composition-on-unanalyzable-property-non-public
539
+
540
+ | Code | Description | Message | Severity |
541
+ | ------------ | ----------------------------------------------------- | --------------------------------------------------------------------- | -------- |
542
+ | `komaci1015` | Flags property binding used in a template is private. | This {0} an unanalyzable property '{1}' that is not a public property | error |
543
+
544
+ ### ❌ Incorrect
545
+
546
+ ```js
547
+ import { LightningElement } from 'lwc';
548
+ export default class Example extends LightningElement {
549
+ notPublic;
550
+ }
551
+ ```
552
+
553
+ ```html
554
+ <template>
555
+ <c-child input="{notPublic}"></c-child>
556
+ </template>
557
+ ```
558
+
559
+ ### ✅ Correct
560
+
561
+ ```js
562
+ import { LightningElement } from 'lwc';
563
+ export default class Example extends LightningElement {
564
+ @api public;
565
+ }
566
+ ```
567
+
568
+ ```html
569
+ <template>
570
+ <c-child input="{public}"></c-child>
571
+ </template>
572
+ ```
573
+
574
+ ## `komaci1016`: no-composition-on-unanalyzable-getter-property
575
+
576
+ | Code | Description | Message | Severity |
577
+ | ------------ | --------------------------------------------------------------------- | ---------------------------------------------- | -------- |
578
+ | `komaci1016` | Flags template property bindings that reference unanalyzable getters. | This {0} an unanalyzable getter property '{1}' | error |
579
+
580
+ ### ❌ Incorrect
581
+
582
+ ```js
583
+ import { LightningElement } from 'lwc';
584
+ export default class Example extends LightningElement {
585
+ prop;
586
+ get invalidGetter() {
587
+ this.prop = 'new value'; // mutations not allowed
588
+ return this.prop;
589
+ }
590
+ }
591
+ ```
592
+
593
+ ```html
594
+ <template>
595
+ <c-child input="{invalidGetter}"></c-child>
596
+ </template>
597
+ ```
598
+
599
+ ### ✅ Correct
600
+
601
+ ```js
602
+ import { LightningElement } from 'lwc';
603
+ export default class Example extends LightningElement {
604
+ @api prop;
605
+ get getter() {
606
+ return this.prop;
607
+ }
608
+ }
609
+ ```
610
+
611
+ ```html
612
+ <template>
613
+ <c-child input="{getter}"></c-child>
614
+ </template>
615
+ ```
616
+
617
+ ## `komaci1017`: no-composition-on-unanalyzable-property-missing
618
+
619
+ | Code | Description | Message | Severity |
620
+ | ------------ | -------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | -------- |
621
+ | `komaci1017` | Property binding within the template references a property not found in the javascript file. | This {0} a property '{1}' which does not exist in the corresponding script file | error |
622
+
623
+ ### ❌ Incorrect
624
+
625
+ ```js
626
+ import { LightningElement } from 'lwc';
627
+ export default class Example extends LightningElement {}
628
+ ```
629
+
630
+ ```html
631
+ <template>
632
+ <c-child input="{doesNotExist}"></c-child>
633
+ </template>
634
+ ```
635
+
636
+ ### ✅ Correct
637
+
638
+ ```js
639
+ import { LightningElement } from 'lwc';
640
+ export default class Example extends LightningElement {
641
+ @api doesExist;
642
+ }
643
+ ```
644
+
645
+ ```html
646
+ <template>
647
+ <c-child input="{doesExist}"></c-child>
648
+ </template>
649
+ ```
650
+
651
+ ### 😟 Limitations
652
+
653
+ This will flag if a child class is referencing a property that's only defined on the parent class.
654
+
655
+ #### ❌ Incorrect
656
+
657
+ ```js
658
+ import Parent from 'x/parent';
659
+ export default class Example extends Parent {}
660
+ ```
661
+
662
+ ```html
663
+ <template>
664
+ <c-child input="{existsOnParent}"></c-child>
665
+ </template>
666
+ ```
667
+
668
+ ### ✅ Correct
669
+
670
+ To fix this, you must update the javascript file to explicitly define properties that are references in the template.
671
+
672
+ ```js
673
+ import Parent from 'x/parent';
674
+ export default class Example extends Parent {
675
+ @api existsOnParent;
676
+ }
677
+ ```
678
+
679
+ ```html
680
+ <template>
681
+ <c-child input="{existsOnParent}"></c-child>
682
+ </template>
683
+ ```
684
+
685
+ ## `komaci1018`: no-wire-config-property-circular-wire-dependency
686
+
687
+ | Code | Description | Message | Severity |
688
+ | ------------ | ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
689
+ | `komaci1018` | Flags when a wire's output is used as input into another wire, and that wire's output is used in the original wire. | The wire configuration input property '{0}' of this wire is part of a chain of circular wire dependencies, and will result an infinite loop during runtime. Please refactor code to remove the circular dependency. Dependency chain: '{1}' | error |
690
+
691
+ ### ❌ Incorrect
692
+
693
+ ```js
694
+ import { LightningElement, wire } from 'lwc';
695
+ import { getRecord } from 'lightning/uiRecordApi';
696
+ export default class Example extends LightningElement {
697
+ @wire(getRecord, { input: '$wireOutput2' })
698
+ wireOutput1;
699
+
700
+ @wire(getRecord, { input: '$wireOutput1' })
701
+ wireOutput2;
702
+ }
703
+ ```
704
+
705
+ ### ✅ Correct
706
+
707
+ Remove the ciruclar dependency.
708
+
709
+ ```js
710
+ import { LightningElement } from 'lwc';
711
+ export default class Example extends LightningElement {
712
+ @api input;
713
+ @wire(getRecord, { input: '$input' })
714
+ wireOutput;
715
+ }
716
+ ```
717
+
718
+ ## `komaci1022`: no-assignment-expression-assigns-value-to-member-variable
719
+
720
+ | Code | Description | Message | Severity |
721
+ | ------------ | -------------------------------------------- | -------------------------------------------------------------------- | -------- |
722
+ | `komaci1022` | Flags getters that mutate member properties. | Assignment expression cannot assign a value to member variable '{0}' | error |
723
+
724
+ ### ❌ Incorrect
725
+
726
+ ```js
727
+ import { LightningElement } from 'lwc';
728
+ export default class Example extends LightningElement {
729
+ prop;
730
+ get input() {
731
+ const value = 'value';
732
+ this.prop = value;
733
+ return value;
734
+ }
735
+ }
736
+ ```
737
+
738
+ ### ✅ Correct
739
+
740
+ ```js
741
+ import { LightningElement } from 'lwc';
742
+ export default class Example extends LightningElement {
743
+ prop;
744
+ get input() {
745
+ return 'value';
746
+ }
747
+ }
748
+ ```
749
+
750
+ ## `komaci1023`: no-assignment-expression-for-external-components
751
+
752
+ | Code | Description | Message | Severity |
753
+ | ------------ | ----------- | ---------------------------------------------------------------- | -------- |
754
+ | `komaci1023` | Flags | Assignment Expressions are not supported for external components | error |
755
+
756
+ ### ❌ Incorrect
757
+
758
+ ```js
759
+ import { LightningElement } from 'lwc';
760
+ export default class Example extends LightningElement {
761
+ prop;
762
+ get getter() {
763
+ return (this.prop = 'hi'), this.prop;
764
+ }
765
+ }
766
+ ```
767
+
768
+ ### ✅ Correct
769
+
770
+ ```js
771
+ import { LightningElement } from 'lwc';
772
+ export default class Example extends LightningElement {
773
+ @api prop;
774
+ get getter() {
775
+ return this.prop;
776
+ }
777
+ }
778
+ ```
779
+
780
+ ## `komaci1024`: no-tagged-template-expression-contains-unsupported-namespace
781
+
782
+ | Code | Description | Message | Severity |
783
+ | ------------ | ----------------------------------------------------------------------- | --------------------------------------------------------------------------------- | -------- |
784
+ | `komaci1024` | Flags when the tag in a tagged template is from an unspported resource. | Tagged Template Expression contains a reference to an unsupported namespace '{0}' | error |
785
+
786
+ ### ❌ Incorrect
787
+
788
+ ```js
789
+ import { LightningElement } from 'lwc';
790
+ import invalid from 'x/invalid';
791
+
792
+ export default class Example extends LightningElement {
793
+ invalidProp = invalid`normal string`;
794
+ }
795
+ ```
796
+
797
+ ### ✅ Correct
798
+
799
+ ```js
800
+ import { LightningElement } from 'lwc';
801
+ import { gql } from 'lightning/uiGraphQLApi';
802
+
803
+ export default class Example extends LightningElement {
804
+ validProp = gql`normal string`;
805
+ }
806
+ ```
807
+
808
+ ## `komaci1025`: no-getter-contains-more-than-return-statement
809
+
810
+ | Code | Description | Message | Severity |
811
+ | ------------ | ---------------------------------------------------- | ----------------------------------------------------- | -------- |
812
+ | `komaci1025` | Flags getters that do more than just return a value. | Supported getters can only contain a return statement | error |
813
+
814
+ ### ❌ Incorrect
815
+
816
+ ```js
817
+ import { LightningElement } from 'lwc';
818
+ export default class Example extends LightningElement {
819
+ get invalidGetter() {
820
+ const val = 'val';
821
+ return val;
822
+ }
823
+ }
824
+ ```
825
+
826
+ ### ✅ Correct
827
+
828
+ ```js
829
+ import { LightningElement } from 'lwc';
830
+ export default class Example extends LightningElement {
831
+ get invalidGetter() {
832
+ return 'val';
833
+ }
834
+ }
835
+ ```
836
+
837
+ ## `komaci1026`: no-expression-contains-module-level-variable-ref
838
+
839
+ | Code | Description | Message | Severity |
840
+ | ------------ | -------------------------------------------------------------------- | ------------------------------------------------------------------------ | -------- |
841
+ | `komaci1026` | Getter contains reference to a variable defined at the module level. | Expression contains a reference to a variable at the module level: '{0}' | error |
842
+
843
+ ### ❌ Incorrect
844
+
845
+ ```js
846
+ import { LightningElement } from 'lwc';
847
+ const moduleValue = 'val';
848
+ export default class Example extends LightningElement {
849
+ get invalid() {
850
+ return moduleValue;
851
+ }
852
+ }
853
+ ```
854
+
855
+ ### ✅ Correct
856
+
857
+ ```js
858
+ import { LightningElement } from 'lwc';
859
+ export default class Example extends LightningElement {
860
+ get propValue() {
861
+ return 'val';
862
+ }
863
+ get invalid() {
864
+ return this.propValue;
865
+ }
866
+ }
867
+ ```
868
+
869
+ ## `komaci1027`: no-call-expression-references-unsupported-namespace
870
+
871
+ | Code | Description | Message | Severity |
872
+ | ------------ | ----------------------------------------------------- | -------------------------------------------------------------------- | -------- |
873
+ | `komaci1027` | Getter invokes a function from an unsupported import. | Call expression contains reference to an unsupported namespace '{0}' | error |
874
+
875
+ ### ❌ Incorrect
876
+
877
+ ```js
878
+ import { LightningElement } from 'lwc';
879
+ import invalid from 'x/invalid';
880
+ export default class Example extends LightningElement {
881
+ get invalidGetter() {
882
+ return invalid();
883
+ }
884
+ }
885
+ ```
886
+
887
+ ### ✅ Correct
888
+
889
+ Invoking functions is not allowed in getters.
890
+
891
+ ```js
892
+ import { LightningElement } from 'lwc';
893
+ export default class Example extends LightningElement {}
894
+ ```
895
+
896
+ ## `komaci1028`: no-eval-usage
897
+
898
+ | Code | Description | Message | Severity |
899
+ | ------------ | ------------------------------------------- | ------------------------------------------------------ | -------- |
900
+ | `komaci1028` | Flags a getter that attempts to use `eval`. | Call expression contains non-portable identifier '{0}' | error |
901
+
902
+ ### ❌ Incorrect
903
+
904
+ ```js
905
+ import { LightningElement } from 'lwc';
906
+ export default class Example extends LightningElement {
907
+ get invalid() {
908
+ return eval('something evil');
909
+ }
910
+ }
911
+ ```
912
+
913
+ ### ✅ Correct
914
+
915
+ ```js
916
+ import { LightningElement } from 'lwc';
917
+ export default class Example extends LightningElement {
918
+ get valid() {
919
+ return 'do no evil';
920
+ }
921
+ }
922
+ ```
923
+
924
+ ## `komaci1029`: no-reference-to-class-functions
925
+
926
+ | Code | Description | Message | Severity |
927
+ | ------------ | ------------------------------------------------------ | ------------------------------------------------------------------------- | -------- |
928
+ | `komaci1029` | Flags when an expression references a member function. | Call expression contains reference to function defined on the class '{0}' | error |
929
+
930
+ ### ❌ Incorrect
931
+
932
+ ```js
933
+ import { LightningElement } from 'lwc';
934
+ export default class Example extends LightningElement {
935
+ doSomething() {
936
+ return 'value';
937
+ }
938
+
939
+ get value() {
940
+ return this.doSomething(); // flags
941
+ }
942
+
943
+ someProp = `${this.doSomething()}`; // flags
944
+ }
945
+ ```
946
+
947
+ ### ✅ Correct
948
+
949
+ Replace with getter if you can.
950
+
951
+ ```js
952
+ import { LightningElement } from 'lwc';
953
+ export default class Example extends LightningElement {
954
+ get something() {
955
+ return 'value';
956
+ }
957
+ get value() {
958
+ return this.something;
959
+ }
960
+
961
+ someProp = `${this.something}`;
962
+ }
963
+ ```
964
+
965
+ ## `komaci1030`: no-reference-to-module-functions
966
+
967
+ | Code | Description | Message | Severity |
968
+ | ------------ | ------------------------------------------------------------- | -------------------------------------------------------------------------- | -------- |
969
+ | `komaci1030` | Expression references a function defined at the module level. | Call expression contains reference to function defined on the module '{0}' | error |
970
+
971
+ ### ❌ Incorrect
972
+
973
+ ```js
974
+ import { LightningElement } from 'lwc';
975
+
976
+ // Module level function
977
+ function doSomething() {
978
+ return 'value';
979
+ }
980
+
981
+ export default class Example extends LightningElement {
982
+ get value() {
983
+ return doSomething(); // flags
984
+ }
985
+
986
+ someProp = `${doSomething()}`; // flags
987
+ }
988
+ ```
989
+
990
+ ### ✅ Correct
991
+
992
+ Replace with getter if you can.
993
+
994
+ ```js
995
+ import { LightningElement } from 'lwc';
996
+
997
+ export default class Example extends LightningElement {
998
+ get something() {
999
+ return 'value';
1000
+ }
1001
+ get value() {
1002
+ return this.something;
1003
+ }
1004
+
1005
+ someProp = `${this.something}`;
1006
+ }
1007
+ ```
1008
+
1009
+ ## `komaci1031`: no-functions-declared-within-getter-method
1010
+
1011
+ | Code | Description | Message | Severity |
1012
+ | ------------ | -------------------------------------------------------------- | ---------------------------------------------------- | -------- |
1013
+ | `komaci1031` | Flags when a getter or template expression defines a function. | Functions may not be declared within a getter method | error |
1014
+
1015
+ ### ❌ Incorrect
1016
+
1017
+ ```js
1018
+ import { LightningElement } from 'lwc';
1019
+
1020
+ export default class Example extends LightningElement {
1021
+ get value() {
1022
+ return (() => 'value')(); // flags
1023
+ }
1024
+
1025
+ str = `${(() => 'value')()}`; // flags
1026
+ }
1027
+ ```
1028
+
1029
+ ### ✅ Correct
1030
+
1031
+ ```js
1032
+ import { LightningElement } from 'lwc';
1033
+ export default class Example extends LightningElement {
1034
+ get value() {
1035
+ return 'value';
1036
+ }
1037
+
1038
+ str = `value`;
1039
+ }
1040
+ ```
1041
+
1042
+ ## `komaci1032`: no-unsupported-member-variable-in-member-expression
1043
+
1044
+ | Code | Description | Message | Severity |
1045
+ | ------------ | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | -------- |
1046
+ | `komaci1032` | Flags when a getter or template expression references an unsupported (e.g., private) member variable. | Member expression contains reference to unsupported member variable '{0}' | error |
1047
+
1048
+ ### ❌ Incorrect
1049
+
1050
+ ```js
1051
+ import { LightningElement } from 'lwc';
1052
+ export default class Example extends LightningElement {
1053
+ privateProp; // unsupported member variable
1054
+
1055
+ get value() {
1056
+ return this.privateProp; // flags
1057
+ }
1058
+
1059
+ otherValue = `${this.privateProp}`; // flags
1060
+ }
1061
+ ```
1062
+
1063
+ ### ✅ Correct
1064
+
1065
+ ```js
1066
+ import { LightningElement } from 'lwc';
1067
+ export default class Example extends LightningElement {
1068
+ @api prop;
1069
+
1070
+ get value() {
1071
+ return this.prop;
1072
+ }
1073
+
1074
+ otherValue = `${this.prop}`;
1075
+ }
1076
+ ```
1077
+
1078
+ ## `komaci1033`: no-member-expression-reference-to-non-existent-member-variable
1079
+
1080
+ | Code | Description | Message | Severity |
1081
+ | ------------ | ------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------- | -------- |
1082
+ | `komaci1033` | Expression references a member variable that has not been explicitly defined on the class. | Member expression contains reference to non-existent member variable '{0}' | error |
1083
+
1084
+ ### ❌ Incorrect
1085
+
1086
+ ```js
1087
+ import { LightningElement } from 'lwc';
1088
+ export default class Example extends LightningElement {
1089
+ get value() {
1090
+ return this.doesNotExist;
1091
+ }
1092
+
1093
+ otherValue = `${this.doesNotExist}`;
1094
+ }
1095
+ ```
1096
+
1097
+ ### ✅ Correct
1098
+
1099
+ ```js
1100
+ import { LightningElement } from 'lwc';
1101
+ export default class Example extends LightningElement {
1102
+ @api doesExist;
1103
+ get value() {
1104
+ return this.doesExist;
1105
+ }
1106
+
1107
+ otherValue = `${this.doesExist}`;
1108
+ }
1109
+ ```
1110
+
1111
+ ## `komaci1034`: no-member-expression-reference-to-unsupported-namespace-reference
1112
+
1113
+ | Code | Description | Message | Severity |
1114
+ | ------------ | -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | -------- |
1115
+ | `komaci1034` | Flags when an expression references a property on a resouce that is unsupported. | Member expression contains reference to unsupported namespace reference: '{0}' | error |
1116
+
1117
+ ### ❌ Incorrect
1118
+
1119
+ ```js
1120
+ import { LightningElement } from 'lwc';
1121
+ import invalid from 'x/invalid';
1122
+ export default class Example extends LightningElement {
1123
+ get value() {
1124
+ return invalid.foo;
1125
+ }
1126
+
1127
+ str = `${invalid.foo}`;
1128
+ }
1129
+ ```
1130
+
1131
+ ### ✅ Correct
1132
+
1133
+ ```js
1134
+ import { LightningElement } from 'lwc';
1135
+ export default class Example extends LightningElement {}
1136
+ ```
1137
+
1138
+ ## `komaci1035`: no-member-expression-contains-non-portable-identifier
1139
+
1140
+ | Code | Description | Message | Severity |
1141
+ | ------------ | ---------------------------------------------------------------------------------------- | -------------------------------------------------------- | -------- |
1142
+ | `komaci1035` | Flags when an expression references a non-portable variable like `document` or `window`. | Member expression contains non-portable identifier '{0}' | error |
1143
+
1144
+ ### ❌ Incorrect
1145
+
1146
+ ```js
1147
+ import { LightningElement } from 'lwc';
1148
+ export default class Example extends LightningElement {
1149
+ get value() {
1150
+ return window.foo;
1151
+ }
1152
+
1153
+ str = `${window.foo}`;
1154
+ }
1155
+ ```
1156
+
1157
+ ### ✅ Correct
1158
+
1159
+ ```js
1160
+ import { LightningElement } from 'lwc';
1161
+ export default class Example extends LightningElement {}
1162
+ ```
1163
+
1164
+ ## `komaci1036`: no-member-expression-reference-to-super-class
1165
+
1166
+ | Code | Description | Message | Severity |
1167
+ | ------------ | ------------------------------------------- | ---------------------------------------------------------- | -------- |
1168
+ | `komaci1036` | Flags when an expression references `super` | Member expression contains reference to super class: '{0}' | error |
1169
+
1170
+ ### ❌ Incorrect
1171
+
1172
+ ```js
1173
+ import Parent from 'x/parent';
1174
+ export default class Example extends Parent {
1175
+ get value() {
1176
+ return super.value;
1177
+ }
1178
+
1179
+ str = `${super.value}`;
1180
+ }
1181
+ ```
1182
+
1183
+ ### ✅ Correct
1184
+
1185
+ ```js
1186
+ import Parent from 'x/parent';
1187
+ export default class Example extends Parent {
1188
+ @api value;
1189
+ get value() {
1190
+ return this.value;
1191
+ }
1192
+
1193
+ str = `${this.value}`;
1194
+ }
1195
+ ```
1196
+
1197
+ ## `komaci1037`: no-member-expression-reference-to-unsupported-global
1198
+
1199
+ | Code | Description | Message | Severity |
1200
+ | ------------ | ------------------------------------------------------------------------------- | ----------------------------------------------------------------- | -------- |
1201
+ | `komaci1037` | Flags when an expression references a global variable like `String` or `Object` | Member expression contains reference to unsupported global: '{0}' | error |
1202
+
1203
+ ### ❌ Incorrect
1204
+
1205
+ ```js
1206
+ import { LightningElement } from 'lwc';
1207
+ export default class Example extends LightningElement {
1208
+ get value() {
1209
+ return new String.foo();
1210
+ }
1211
+
1212
+ str = `${String.foo}`;
1213
+ }
1214
+ ```
1215
+
1216
+ ### ✅ Correct
1217
+
1218
+ ```js
1219
+ import { LightningElement } from 'lwc';
1220
+ export default class Example extends LightningElement {}
1221
+ ```
1222
+
1223
+ ## `komaci1038`: no-reference-to-unsupported-namespace-reference
1224
+
1225
+ | Code | Description | Message | Severity |
1226
+ | ------------ | -------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | -------- |
1227
+ | `komaci1038` | Flags when a resource imported from an unspported namespaces is used in an expression. | Reference to import '{0}' from an unsupported namespace is not allowed | error |
1228
+
1229
+ ### ❌ Incorrect
1230
+
1231
+ ```js
1232
+ import { LightningElement } from 'lwc';
1233
+ import invalid from 'x/invalid';
1234
+ export default class Example extends LightningElement {
1235
+ get value() {
1236
+ return invalid;
1237
+ }
1238
+ }
1239
+ ```
1240
+
1241
+ ### ✅ Correct
1242
+
1243
+ You can only use values imported from supported namespaces like `@salesforce/*`.
1244
+
1245
+ ```js
1246
+ import { LightningElement } from 'lwc';
1247
+ import valid from '@salesforce/label/My.Label';
1248
+ export default class Example extends LightningElement {
1249
+ get value() {
1250
+ return valid;
1251
+ }
1252
+ }
1253
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@komaci/static-analyzer",
3
- "version": "242.1.0",
3
+ "version": "242.1.3",
4
4
  "description": "Komaci Diagnostics API",
5
5
  "homepage": "https://komaci.dev/",
6
6
  "repository": {
@@ -23,15 +23,17 @@
23
23
  },
24
24
  "files": [
25
25
  "build/**/*.js",
26
- "build/**/*.d.ts"
26
+ "build/**/*.d.ts",
27
+ "**/*.md",
28
+ "!**/RULES.todo.md"
27
29
  ],
28
30
  "dependencies": {
29
- "@komaci/common-shared": "242.1.0",
31
+ "@komaci/common-shared": "242.1.3",
30
32
  "@lwc/metadata": "2.22.0-0",
31
33
  "@lwc/sfdc-compiler-utils": "2.22.0-0"
32
34
  },
33
35
  "devDependencies": {
34
36
  "@babel/types": "^7.9.0",
35
- "@komaci/types": "242.1.0"
37
+ "@komaci/types": "242.1.3"
36
38
  }
37
39
  }