@spinnaker/eslint-plugin 0.0.0-2025.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.
Files changed (62) hide show
  1. package/.eslintignore +3 -0
  2. package/CHANGELOG.md +96 -0
  3. package/LICENSE.txt +203 -0
  4. package/README.md +259 -0
  5. package/babel.config.js +3 -0
  6. package/base.config.js +86 -0
  7. package/create-rule.js +67 -0
  8. package/eslint-plugin.ts +47 -0
  9. package/index.js +6 -0
  10. package/newrule.sh +88 -0
  11. package/none.config.js +18 -0
  12. package/package.json +56 -0
  13. package/rules/api-deprecation.spec.ts +79 -0
  14. package/rules/api-deprecation.ts +255 -0
  15. package/rules/api-no-slashes.spec.ts +84 -0
  16. package/rules/api-no-slashes.ts +148 -0
  17. package/rules/api-no-unused-chaining.spec.ts +26 -0
  18. package/rules/api-no-unused-chaining.ts +47 -0
  19. package/rules/import-from-alias-not-npm.spec.ts +22 -0
  20. package/rules/import-from-alias-not-npm.ts +53 -0
  21. package/rules/import-from-npm-not-alias.spec.ts +24 -0
  22. package/rules/import-from-npm-not-alias.ts +56 -0
  23. package/rules/import-from-npm-not-relative.spec.ts +22 -0
  24. package/rules/import-from-npm-not-relative.ts +57 -0
  25. package/rules/import-from-presentation-not-core.spec.ts +44 -0
  26. package/rules/import-from-presentation-not-core.ts +107 -0
  27. package/rules/import-relative-within-subpackage.spec.ts +51 -0
  28. package/rules/import-relative-within-subpackage.ts +71 -0
  29. package/rules/import-sort.spec.ts +85 -0
  30. package/rules/import-sort.ts +281 -0
  31. package/rules/migrate-to-mock-http-client.spec.ts +78 -0
  32. package/rules/migrate-to-mock-http-client.ts +123 -0
  33. package/rules/ng-no-component-class.spec.ts +45 -0
  34. package/rules/ng-no-component-class.ts +68 -0
  35. package/rules/ng-no-module-export.spec.ts +26 -0
  36. package/rules/ng-no-module-export.ts +117 -0
  37. package/rules/ng-no-require-angularjs.spec.ts +27 -0
  38. package/rules/ng-no-require-angularjs.ts +94 -0
  39. package/rules/ng-no-require-module-deps.spec.ts +33 -0
  40. package/rules/ng-no-require-module-deps.ts +211 -0
  41. package/rules/ng-strictdi.spec.ts +100 -0
  42. package/rules/ng-strictdi.ts +304 -0
  43. package/rules/prefer-promise-like.spec.ts +75 -0
  44. package/rules/prefer-promise-like.ts +108 -0
  45. package/rules/react2angular-with-error-boundary.spec.ts +29 -0
  46. package/rules/react2angular-with-error-boundary.ts +118 -0
  47. package/rules/rest-prefer-static-strings-in-initializer.spec.ts +34 -0
  48. package/rules/rest-prefer-static-strings-in-initializer.ts +89 -0
  49. package/template/template-rule.spec.ts +17 -0
  50. package/template/template-rule.ts +21 -0
  51. package/test.eslintrc +20 -0
  52. package/test_rule_against_deck_source.sh +18 -0
  53. package/tsconfig.json +17 -0
  54. package/utils/angular-rule/angular-rule.js +302 -0
  55. package/utils/angular-rule/false-values.js +6 -0
  56. package/utils/angular-rule/utils.js +624 -0
  57. package/utils/ast.ts +11 -0
  58. package/utils/import-aliases.mock.ts +17 -0
  59. package/utils/import-aliases.ts +91 -0
  60. package/utils/mockModule.js +15 -0
  61. package/utils/ruleTester.js +8 -0
  62. package/utils/utils.ts +90 -0
@@ -0,0 +1,624 @@
1
+ 'use strict';
2
+ var falseConfigValues = require('./false-values').config;
3
+ var falseRunValues = require('./false-values').run;
4
+
5
+ var scopeProperties = [
6
+ '$id',
7
+ '$parent',
8
+ '$root',
9
+ '$destroy',
10
+ '$broadcast',
11
+ '$emit',
12
+ '$on',
13
+ '$applyAsync',
14
+ '$apply',
15
+ '$evalAsync',
16
+ '$eval',
17
+ '$digest',
18
+ '$watchCollection',
19
+ '$watchGroup',
20
+ '$watch',
21
+ '$new',
22
+ ];
23
+
24
+ module.exports = {
25
+ // Properties
26
+ scopeProperties: scopeProperties,
27
+
28
+ // Functions
29
+ convertPrefixToRegex: convertPrefixToRegex,
30
+ convertStringToRegex: convertStringToRegex,
31
+ isTypeOfStatement: isTypeOfStatement,
32
+ isToStringStatement: isToStringStatement,
33
+ isArrayType: isArrayType,
34
+ isFunctionType: isFunctionType,
35
+ isNamedInlineFunction: isNamedInlineFunction,
36
+ isIdentifierType: isIdentifierType,
37
+ isMemberExpression: isMemberExpression,
38
+ isLiteralType: isLiteralType,
39
+ isCallExpression: isCallExpression,
40
+ isEmptyFunction: isEmptyFunction,
41
+ isStringRegexp: isStringRegexp,
42
+ isAngularComponent: isAngularComponent,
43
+ isAngularComponentDeclaration: isAngularComponentDeclaration,
44
+ isAngularControllerDeclaration: isAngularControllerDeclaration,
45
+ isAngularFilterDeclaration: isAngularFilterDeclaration,
46
+ isAngularDirectiveDeclaration: isAngularDirectiveDeclaration,
47
+ isAngularServiceDeclarationDeprecated: isAngularServiceDeclarationDeprecated,
48
+ isAngularServiceDeclaration: isAngularServiceDeclaration,
49
+ isAngularProviderDeclaration: isAngularProviderDeclaration,
50
+ isAngularFactoryDeclaration: isAngularFactoryDeclaration,
51
+ isAngularConstantDeclaration: isAngularConstantDeclaration,
52
+ isAngularValueDeclaration: isAngularValueDeclaration,
53
+ isAngularModuleDeclaration: isAngularModuleDeclaration,
54
+ isAngularModuleGetter: isAngularModuleGetter,
55
+ isAngularRunSection: isAngularRunSection,
56
+ isAngularConfigSection: isAngularConfigSection,
57
+ isRouteDefinition: isRouteDefinition,
58
+ isUIRouterStateDefinition: isUIRouterStateDefinition,
59
+ findIdentiferInScope: findIdentiferInScope,
60
+ getControllerDefinition: getControllerDefinition,
61
+ isAngularServiceImport: isAngularServiceImport,
62
+ getToStringTagType: getToStringTagType,
63
+ };
64
+
65
+ /**
66
+ * Recursively grab the callee until an Identifier is found.
67
+ *
68
+ * @todo Needs better documentation.
69
+ */
70
+ function getCallingIdentifier(calleeObject) {
71
+ if (calleeObject.type && calleeObject.type === 'Identifier') {
72
+ return calleeObject;
73
+ }
74
+ if (calleeObject.callee && calleeObject.callee.object) {
75
+ return getCallingIdentifier(calleeObject.callee.object);
76
+ }
77
+ return null;
78
+ }
79
+
80
+ /**
81
+ * Convert a prefix string to a RegExp.
82
+ *
83
+ * `'/app/'` → `/app.*\/`
84
+ *
85
+ * @param {string} prefix
86
+ * @returns {RegExp}
87
+ */
88
+ function convertPrefixToRegex(prefix) {
89
+ if (typeof prefix !== 'string') {
90
+ return prefix;
91
+ }
92
+
93
+ if (prefix[0] === '/' && prefix[prefix.length - 1] === '/') {
94
+ prefix = prefix.substring(1, prefix.length - 1);
95
+ }
96
+
97
+ return new RegExp(prefix + '.*');
98
+ }
99
+
100
+ /**
101
+ * Convert a string to a RegExp.
102
+ *
103
+ * `'app'` → `/app/`
104
+ * `'/app/'` → `/app/`
105
+ *
106
+ * @param {string} prefix
107
+ * @returns {RegExp}
108
+ */
109
+ function convertStringToRegex(string) {
110
+ if (string[0] === '/' && string[string.length - 1] === '/') {
111
+ string = string.substring(1, string.length - 1);
112
+ }
113
+ return new RegExp(string);
114
+ }
115
+
116
+ /**
117
+ * @todo Missing documentation
118
+ */
119
+ function isTypeOfStatement(node) {
120
+ return node.type === 'Identifier' || (node.type === 'UnaryExpression' && node.operator === 'typeof');
121
+ }
122
+
123
+ /**
124
+ * @todo Missing documentation
125
+ *
126
+ * @param {Object} node The node to check.
127
+ * @returns {boolean} Whether or not the node is a `toString` statement.
128
+ */
129
+ function isToStringStatement(node) {
130
+ return (
131
+ node.type === 'CallExpression' &&
132
+ node.callee.type === 'MemberExpression' &&
133
+ node.callee.object.type === 'MemberExpression' &&
134
+ node.callee.object.property.name === 'toString' &&
135
+ node.callee.property.name === 'call' &&
136
+ node.callee.object.object.type === 'MemberExpression' &&
137
+ node.callee.object.object.object.name === 'Object' &&
138
+ node.callee.object.object.property.name === 'prototype'
139
+ );
140
+ }
141
+
142
+ /**
143
+ * Check whether or not a node is an ArrayExpression.
144
+ *
145
+ * @param {Object} node The node to check.
146
+ * @returns {boolean} Whether or not the node is an ArrayExpression.
147
+ */
148
+ function isArrayType(node) {
149
+ return node !== undefined && node.type === 'ArrayExpression';
150
+ }
151
+
152
+ /**
153
+ * Check whether or not a node is an FunctionExpression.
154
+ *
155
+ * @param {Object} node The node to check.
156
+ * @returns {boolean} Whether or not the node is an FunctionExpression.
157
+ */
158
+ function isFunctionType(node) {
159
+ return node !== undefined && (node.type === 'FunctionExpression' || node.type === 'ArrowFunctionExpression');
160
+ }
161
+
162
+ /**
163
+ * Check whether or not a node is an named FunctionExpression.
164
+ *
165
+ * @param {Object} node The node to check.
166
+ * @returns {boolean} Whether or not the node is an named FunctionExpression.
167
+ */
168
+ function isNamedInlineFunction(node) {
169
+ return this.isFunctionType(node) && node.id && node.id.name && node.id.name.length > 0;
170
+ }
171
+
172
+ /**
173
+ * Check whether or not a node is an Identifier.
174
+ *
175
+ * @param {Object} node The node to check.
176
+ * @returns {boolean} Whether or not the node is an Identifier.
177
+ */
178
+ function isIdentifierType(node) {
179
+ return node !== undefined && node.type === 'Identifier';
180
+ }
181
+
182
+ /**
183
+ * Check whether or not a node is an MemberExpression.
184
+ *
185
+ * @param {Object} node The node to check.
186
+ * @returns {boolean} Whether or not the node is an MemberExpression.
187
+ */
188
+ function isMemberExpression(node) {
189
+ return node !== undefined && node.type === 'MemberExpression';
190
+ }
191
+
192
+ /**
193
+ * Check whether or not a node is an Literal.
194
+ *
195
+ * @param {Object} node The node to check.
196
+ * @returns {boolean} Whether or not the node is an Literal.
197
+ */
198
+ function isLiteralType(node) {
199
+ return node !== undefined && node.type === 'Literal';
200
+ }
201
+
202
+ /**
203
+ * Check whether or not a node is a CallExpression.
204
+ *
205
+ * @param {Object} node The node to check.
206
+ * @returns {boolean} Whether or not the node is a CallExpression.
207
+ */
208
+ function isCallExpression(node) {
209
+ return node !== undefined && node.type === 'CallExpression';
210
+ }
211
+
212
+ /**
213
+ * Check whether or not a node is an isEmptyFunction.
214
+ *
215
+ * @param {Object} node The node to check.
216
+ * @returns {boolean} Whether or not the node is an isEmptyFunction.
217
+ */
218
+ function isEmptyFunction(fn) {
219
+ return fn.body.body.length === 0;
220
+ }
221
+
222
+ /**
223
+ * Check whether or not a string resembles a regular expression.
224
+ *
225
+ * A string is considered a regular expression if it starts and ends with `/`.
226
+ *
227
+ * @param {string} The string to check.
228
+ * @returns {boolean} Whether or not a string resembles a regular expression.
229
+ */
230
+ function isStringRegexp(string) {
231
+ return string[0] === '/' && string[string.length - 1] === '/';
232
+ }
233
+
234
+ /**
235
+ * Check if a CallExpression node somewhat resembles an Angular component.
236
+ *
237
+ * The following are considered Angular components
238
+ * ```js
239
+ * app.factory('kittenService', function() {})
240
+ * ^^^^^^^
241
+ * app.factory('kittenService', kittenService)
242
+ * ^^^^^^^
243
+ * app.factory('kittenService', [])
244
+ * ^^^^^^^
245
+ * app.factory('kittenService', require(""))
246
+ * ^^^^^^^
247
+ * asyncFn('value', callback)
248
+ * ^^^^^^^
249
+ * ```
250
+ *
251
+ * @todo FIXME
252
+ *
253
+ * @param {Object} node The CallExpression node to check.
254
+ * @returns {boolean} Whether or not the node somewhat resembles an Angular component.
255
+ */
256
+ function isAngularComponent(node) {
257
+ return (
258
+ node.arguments !== undefined &&
259
+ node.arguments.length === 2 &&
260
+ (isLiteralType(node.arguments[0]) || isIdentifierType(node.arguments[0])) &&
261
+ (isIdentifierType(node.arguments[1]) ||
262
+ isFunctionType(node.arguments[1]) ||
263
+ isArrayType(node.arguments[1]) ||
264
+ isCallExpression(node.arguments[1]))
265
+ );
266
+ }
267
+
268
+ /**
269
+ * Check whether a CallExpression node defines an Angular component.
270
+ *
271
+ * @param {Object} node The CallExpression node to check.
272
+ * @returns {boolean} Whether or not the node defines an Angular component.
273
+ */
274
+ function isAngularComponentDeclaration(node) {
275
+ return (
276
+ node.arguments !== undefined &&
277
+ node.arguments.length === 2 &&
278
+ isLiteralType(node.arguments[0]) &&
279
+ (node.arguments[1].type === 'ObjectExpression' || isIdentifierType(node.arguments[1])) &&
280
+ isMemberExpression(node.callee) &&
281
+ node.callee.property.name === 'component'
282
+ );
283
+ }
284
+
285
+ /**
286
+ * Check whether a CallExpression node defines an Angular controller.
287
+ *
288
+ * @param {Object} node The CallExpression node to check.
289
+ * @returns {boolean} Whether or not the node defines an Angular controller.
290
+ */
291
+ function isAngularControllerDeclaration(node) {
292
+ return isAngularComponent(node) && isMemberExpression(node.callee) && node.callee.property.name === 'controller';
293
+ }
294
+
295
+ /**
296
+ * Check whether a CallExpression node defines an Angular filter.
297
+ *
298
+ * @param {Object} node The CallExpression node to check.
299
+ * @returns {boolean} Whether or not the node defines an Angular filter.
300
+ */
301
+ function isAngularFilterDeclaration(node) {
302
+ return isAngularComponent(node) && isMemberExpression(node.callee) && node.callee.property.name === 'filter';
303
+ }
304
+
305
+ /**
306
+ * Check whether a CallExpression node defines an Angular directive.
307
+ *
308
+ * @param {Object} node The CallExpression node to check.
309
+ * @returns {boolean} Whether or not the node defines an Angular directive.
310
+ */
311
+ function isAngularDirectiveDeclaration(node) {
312
+ return isAngularComponent(node) && isMemberExpression(node.callee) && node.callee.property.name === 'directive';
313
+ }
314
+
315
+ /**
316
+ * Check whether a node defines an Angular service.
317
+ *
318
+ * The following are considered services
319
+ * ```js
320
+ * app.provider('kittenServiceProvider', function() {})
321
+ * ^^^^^^^^
322
+ * app.factory('kittenService', function() {})
323
+ * ^^^^^^^
324
+ * app.service('kittenService', function() {})
325
+ * ^^^^^^^
326
+ * app.constant('KITTENS', function() {})
327
+ * ^^^^^^^^
328
+ * app.value('KITTENS', function() {})
329
+ * ^^^^^
330
+ * ```
331
+ *
332
+ * The following are not considered services
333
+ * ```js
334
+ * $provide.factory('kittenService', function() {})
335
+ * app.constant('KITTENS', 'meow')
336
+ * app.value('KITTENS', 'purr')
337
+ * this.$get = function() {}
338
+ * ```
339
+ *
340
+ * @todo FIXME
341
+ *
342
+ * @param {Object} node The CallExpression node to check.
343
+ * @returns {boolean} Whether or not the node defines an Angular controller.
344
+ */
345
+ function isAngularServiceDeclarationDeprecated(node) {
346
+ return (
347
+ isAngularComponent(node) &&
348
+ isMemberExpression(node.callee) &&
349
+ node.callee.object.name !== '$provide' &&
350
+ (node.callee.property.name === 'provider' ||
351
+ node.callee.property.name === 'service' ||
352
+ node.callee.property.name === 'factory' ||
353
+ node.callee.property.name === 'constant' ||
354
+ node.callee.property.name === 'value')
355
+ );
356
+ }
357
+
358
+ /*
359
+ * @param {Object}
360
+ * @returns {boolean}
361
+ */
362
+ function isAngularServiceDeclaration(node) {
363
+ return (
364
+ isAngularComponent(node) &&
365
+ isMemberExpression(node.callee) &&
366
+ node.callee.object.name !== '$provide' &&
367
+ node.callee.property.name === 'service'
368
+ );
369
+ }
370
+
371
+ /*
372
+ * @param {Object}
373
+ * @returns {boolean}
374
+ */
375
+ function isAngularProviderDeclaration(node) {
376
+ return (
377
+ isAngularComponent(node) &&
378
+ isMemberExpression(node.callee) &&
379
+ node.callee.object.name !== '$provide' &&
380
+ node.callee.property.name === 'provider'
381
+ );
382
+ }
383
+
384
+ /*
385
+ * @param {Object}
386
+ * @returns {boolean}
387
+ */
388
+ function isAngularFactoryDeclaration(node) {
389
+ return (
390
+ isAngularComponent(node) &&
391
+ isMemberExpression(node.callee) &&
392
+ node.callee.object.name !== '$provide' &&
393
+ node.callee.property.name === 'factory'
394
+ );
395
+ }
396
+
397
+ /*
398
+ * @param {Object}
399
+ * @returns {boolean}
400
+ */
401
+ function isAngularConstantDeclaration(node) {
402
+ return (
403
+ isAngularComponent(node) &&
404
+ isMemberExpression(node.callee) &&
405
+ node.callee.object.name !== '$provide' &&
406
+ node.callee.property.name === 'constant'
407
+ );
408
+ }
409
+
410
+ function isAngularValueDeclaration(node) {
411
+ return (
412
+ isAngularComponent(node) &&
413
+ isMemberExpression(node.callee) &&
414
+ node.callee.object.name !== '$provide' &&
415
+ node.callee.property.name === 'value'
416
+ );
417
+ }
418
+
419
+ /**
420
+ * Check whether a CallExpression node declares an Angular module.
421
+ *
422
+ * @param {Object} node The CallExpression node to check.
423
+ * @returns {boolean} Whether or not the node declares an Angular module.
424
+ */
425
+ function isAngularModuleDeclaration(node) {
426
+ return isAngularComponent(node) && isMemberExpression(node.callee) && node.callee.property.name === 'module';
427
+ }
428
+
429
+ /**
430
+ * Check whether a CallExpression node gets or declares an Angular module.
431
+ *
432
+ * @param {Object} node The CallExpression node to check.
433
+ * @returns {boolean} Whether or not the node gets or declares an Angular module.
434
+ */
435
+ function isAngularModuleGetter(node) {
436
+ return (
437
+ node.arguments !== undefined &&
438
+ node.arguments.length > 0 &&
439
+ (isLiteralType(node.arguments[0]) || isIdentifierType(node.arguments[0])) &&
440
+ node.callee.type === 'MemberExpression' &&
441
+ node.callee.property.name === 'module'
442
+ );
443
+ }
444
+
445
+ /**
446
+ * Check whether a CallExpression node defines an Angular run function.
447
+ *
448
+ * The following are considered run functions
449
+ * ```js
450
+ * app.run()
451
+ * ^^^
452
+ * app.run(function() {})
453
+ * ^^^
454
+ * ```
455
+ *
456
+ * The following are not considered run functions
457
+ * ```js
458
+ * angular.module('myApp').run(function() {})
459
+ * angular.module('myApp', []).run(function() {})
460
+ * mocha.run()
461
+ * ```
462
+ *
463
+ * @todo FIXME
464
+ *
465
+ * @param {Object} node The CallExpression node to check.
466
+ * @returns {boolean} Whether or not the node defines an Angular run function.
467
+ */
468
+ function isAngularRunSection(node) {
469
+ return (
470
+ isMemberExpression(node.callee) &&
471
+ node.callee.property.type === 'Identifier' &&
472
+ node.callee.property.name === 'run' &&
473
+ !falseRunValues.find((pattern) => new RegExp(pattern).test(node.callee.object.name))
474
+ );
475
+ }
476
+
477
+ /**
478
+ * Check whether a CallExpression node defines an Angular config function.
479
+ *
480
+ * The following are considered config functions
481
+ * ```js
482
+ * app.config()
483
+ * ^^^^^^
484
+ * app.config(function() {})
485
+ * ^^^^^^
486
+ * ```
487
+ *
488
+ * The following are not considered run functions
489
+ * ```js
490
+ * angular.module('myApp').config(function() {})
491
+ * angular.module('myApp', []).config(function() {})
492
+ * ```
493
+ *
494
+ * @todo FIXME
495
+ *
496
+ * @param {Object} node The CallExpression node to check.
497
+ * @returns {boolean} Whether or not the node defines an Angular config function.
498
+ */
499
+ function isAngularConfigSection(node) {
500
+ return (
501
+ isMemberExpression(node.callee) &&
502
+ node.callee.property.type === 'Identifier' &&
503
+ node.callee.property.name === 'config' &&
504
+ !falseConfigValues.find((pattern) => new RegExp(pattern).test(node.callee.object.name))
505
+ );
506
+ }
507
+
508
+ /**
509
+ * Check whether a CallExpression node defines a route using $routeProvider.
510
+ *
511
+ * The following are considered routes:
512
+ * ```js
513
+ * $routeProvider.when()
514
+ * ^^^^
515
+ * ```
516
+ *
517
+ * @param {Object} node The CallExpression node to check.
518
+ * @returns {boolean} Whether or not the node defines a route.
519
+ */
520
+ function isRouteDefinition(node) {
521
+ // the route def function is .when(), so when we find that, go up through the chain and make sure
522
+ // $routeProvider is the calling object
523
+ if (node.callee.property && node.callee.property.name === 'when') {
524
+ var callObject = getCallingIdentifier(node.callee.object);
525
+ return callObject && callObject.name === '$routeProvider';
526
+ }
527
+ return false;
528
+ }
529
+
530
+ /**
531
+ * Check whether a CallExpression node defines a state using $stateProvider.
532
+ *
533
+ * The following are considered states:
534
+ * ```js
535
+ * $stateProvider.state()
536
+ * ^^^^^
537
+ * ```
538
+ *
539
+ * @param {Object} node The CallExpression node to check.
540
+ * @returns {boolean} Whether or not the node defines a state.
541
+ */
542
+ function isUIRouterStateDefinition(node) {
543
+ // the state def function is .state(), so when we find that, go up through the chain and make sure
544
+ // $stateProvider is the calling object
545
+ if (node.callee.property && node.callee.property.name === 'state') {
546
+ var callObject = getCallingIdentifier(node.callee.object);
547
+ return callObject && callObject.name === '$stateProvider';
548
+ }
549
+ return false;
550
+ }
551
+
552
+ /**
553
+ * Find an identifier node in the current scope.
554
+ *
555
+ * @param {Object} context The context to use to get the scope.
556
+ * @param {Object} identifier The identifier node to look up.
557
+ *
558
+ * @returns {Object} The node declaring the identifier.
559
+ */
560
+ function findIdentiferInScope(context, identifier) {
561
+ var identifierNode = null;
562
+ context.getScope().variables.forEach(function (variable) {
563
+ if (variable.name === identifier.name) {
564
+ identifierNode = variable.defs[0].node;
565
+ if (identifierNode.type === 'VariableDeclarator') {
566
+ identifierNode = identifierNode.init;
567
+ }
568
+ }
569
+ });
570
+ return identifierNode;
571
+ }
572
+
573
+ /**
574
+ * Find the function definition of a controller in the current context.
575
+ *
576
+ * @param {Object} context The context to use to find the controller declaration.
577
+ * @param {Object} node The Angular controller call to look up the declaration for.
578
+ *
579
+ * @returns {Object} The identifier declaring the controller function.
580
+ */
581
+ function getControllerDefinition(context, node) {
582
+ var controllerArg = node.arguments[1];
583
+
584
+ // Three ways of creating a controller function: function expression,
585
+ // variable name that references a function, and an array with a function
586
+ // as the last item
587
+ if (isFunctionType(controllerArg)) {
588
+ return controllerArg;
589
+ }
590
+ if (isArrayType(controllerArg)) {
591
+ controllerArg = controllerArg.elements[controllerArg.elements.length - 1];
592
+
593
+ if (isIdentifierType(controllerArg)) {
594
+ return findIdentiferInScope(context, controllerArg);
595
+ }
596
+ return controllerArg;
597
+ }
598
+ if (isIdentifierType(controllerArg)) {
599
+ return findIdentiferInScope(context, controllerArg);
600
+ }
601
+ }
602
+
603
+ /**
604
+ * Check if the imported service support these two syntaxes : serviceName and _serviceName_
605
+ *
606
+ * @param {string} parameterName The label of the parameter.
607
+ * @param {string} serviceName The name of the service.
608
+ *
609
+ * @returns {boolean} True if the service use on of these previous syntaxes.
610
+ */
611
+ function isAngularServiceImport(parameterName, serviceName) {
612
+ var r = new RegExp('^_?' + serviceName.replace(/[!@#$%^&*()+=\-[\]\\';,./{}|":<>?~_]/g, '\\$&') + '_?$', 'i');
613
+ return r.test(parameterName);
614
+ }
615
+
616
+ /**
617
+ * Return the value of the given param that retrieved by Object#toString()
618
+ *
619
+ * @param {*} obj
620
+ * @return {string}
621
+ */
622
+ function getToStringTagType(obj) {
623
+ return Object.prototype.toString.apply(obj).match(/^\[object\s(.+)]$/)[1];
624
+ }
package/utils/ast.ts ADDED
@@ -0,0 +1,11 @@
1
+ import type { Identifier, Literal } from 'estree';
2
+
3
+ export function getImportName(node: Identifier | Literal): string {
4
+ if (node.type === 'Identifier') {
5
+ return node.name;
6
+ }
7
+ if (node.type === 'Literal' && typeof node.value === 'string') {
8
+ return node.value;
9
+ }
10
+ return '';
11
+ }
@@ -0,0 +1,17 @@
1
+ const mock = mockModule('./import-aliases');
2
+ mock.getAllSpinnakerPackages.mockImplementation(() => ['core', 'amazon', 'kubernetes']);
3
+ export default mock;
4
+
5
+ export function mockModule(moduleName: string) {
6
+ jest.mock(moduleName);
7
+ const mockedModule = require(moduleName);
8
+ const actualModule = jest.requireActual(moduleName);
9
+ for (const tuple of Object.entries(actualModule)) {
10
+ const [key, value] = tuple;
11
+ if (typeof value === 'function') {
12
+ mockedModule[key].mockImplementation(value);
13
+ }
14
+ }
15
+
16
+ return require(moduleName);
17
+ }