@atlaskit/eslint-plugin-design-system 10.12.4 → 10.12.5

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.
@@ -1,5 +1,5 @@
1
1
  import { isNodeOfType } from 'eslint-codemod-utils';
2
- import { canAutoMigrateNewIconBasedOnSize, canMigrateColor, createAutoMigrationError, createCantFindSuitableReplacementError, createCantMigrateColorError, createCantMigrateFunctionUnknownError, createCantMigrateIdentifierError, createCantMigrateReExportError, createCantMigrateSizeUnknown, createCantMigrateSpreadPropsError, createGuidance, createHelpers, getMigrationMapObject, getUpcomingIcons, isSize, locToString } from './helpers';
2
+ import { addToListOfRanges, canAutoMigrateNewIconBasedOnSize, canMigrateColor, createAutoMigrationError, createCantFindSuitableReplacementError, createCantMigrateColorError, createCantMigrateFunctionUnknownError, createCantMigrateIdentifierError, createCantMigrateIdentifierMapOrArrayError, createCantMigrateReExportError, createCantMigrateSizeUnknown, createCantMigrateSpreadPropsError, createGuidance, createHelpers, getMigrationMapObject, getUpcomingIcons, isInRangeList, isSize, locToString } from './helpers';
3
3
  export const createChecks = context => {
4
4
  //create global variables to be shared by the checks
5
5
  const {
@@ -17,6 +17,9 @@ export const createChecks = context => {
17
17
  const shouldErrorForAutoMigration = getConfigFlag('shouldErrorForAutoMigration', true);
18
18
  const isQuietMode = getConfigFlag('quiet', false);
19
19
 
20
+ // Sorted list of ranges
21
+ let errorRanges = [];
22
+
20
23
  /**
21
24
  * Adds the legacy Icon and new button imports to the correct global arrays to be used by the other checks
22
25
  * @param node The import node found by ESLint
@@ -56,8 +59,8 @@ export const createChecks = context => {
56
59
  if (isNodeOfType(node, 'VariableDeclaration')) {
57
60
  const isExported = node.parent && isNodeOfType(node.parent, 'ExportNamedDeclaration');
58
61
  for (const decl of node.declarations) {
59
- if (isNodeOfType(decl, 'VariableDeclarator') && 'init' in decl && 'id' in decl && decl.init && decl.id && 'name' in decl.id && decl.id.name && isNodeOfType(decl.init, 'Identifier')) {
60
- if (decl.init.name in legacyIconImports) {
62
+ if (isNodeOfType(decl, 'VariableDeclarator') && Object.keys(decl).includes('init') && Object.keys(decl).includes('id') && decl.init && decl.id && 'name' in decl.id && decl.id.name && isNodeOfType(decl.init, 'Identifier')) {
63
+ if (Object.keys(legacyIconImports).includes(decl.init.name)) {
61
64
  legacyIconImports[decl.id.name] = {
62
65
  packageName: legacyIconImports[decl.init.name].packageName,
63
66
  exported: legacyIconImports[decl.init.name].exported || isExported
@@ -77,16 +80,17 @@ export const createChecks = context => {
77
80
  const checkExportDefaultDeclaration = node => {
78
81
  let exportName = '';
79
82
  let packageName = '';
80
- if ('declaration' in node && node.declaration && isNodeOfType(node.declaration, 'Identifier') && node.declaration.name in legacyIconImports) {
83
+ if (Object.keys(node).includes('declaration') && node.declaration && isNodeOfType(node.declaration, 'Identifier') && Object.keys(legacyIconImports).includes(node.declaration.name)) {
81
84
  packageName = legacyIconImports[node.declaration.name].packageName;
82
85
  exportName = 'Default export';
83
- } else if ('declaration' in node && node.declaration && isNodeOfType(node.declaration, 'AssignmentExpression') && isNodeOfType(node.declaration.left, 'Identifier') && isNodeOfType(node.declaration.right, 'Identifier') && node.declaration.right.name in legacyIconImports) {
86
+ } else if (Object.keys(node).includes('declaration') && node.declaration && isNodeOfType(node.declaration, 'AssignmentExpression') && isNodeOfType(node.declaration.left, 'Identifier') && isNodeOfType(node.declaration.right, 'Identifier') && Object.keys(legacyIconImports).includes(node.declaration.right.name)) {
84
87
  packageName = legacyIconImports[node.declaration.right.name].packageName;
85
88
  exportName = node.declaration.left.name;
86
89
  } else {
87
90
  return;
88
91
  }
89
92
  createCantMigrateReExportError(node, packageName, exportName, errorsManual);
93
+ addToListOfRanges(node, errorRanges);
90
94
  guidance[locToString(node)] = createGuidance(packageName);
91
95
  };
92
96
 
@@ -96,19 +100,21 @@ export const createChecks = context => {
96
100
  */
97
101
  const checkExportNamedVariables = node => {
98
102
  // export {default as AddIcon} from '@atlaskit/icon/glyph/add';
99
- if (node.source && isNodeOfType(node.source, 'Literal') && 'value' in node.source) {
103
+ if (node.source && isNodeOfType(node.source, 'Literal') && Object.keys(node.source).includes('value')) {
100
104
  const moduleSource = node.source.value;
101
105
  if (typeof moduleSource === 'string' && ['@atlaskit/icon/glyph/', '@atlaskit/icon-object/glyph/'].find(val => moduleSource.startsWith(val)) && node.specifiers.length) {
102
106
  for (const spec of node.specifiers) {
103
107
  createCantMigrateReExportError(spec, moduleSource, spec.exported.name, errorsManual);
108
+ addToListOfRanges(spec, errorRanges);
104
109
  guidance[locToString(spec)] = createGuidance(moduleSource);
105
110
  }
106
111
  }
107
112
  } else if (node.declaration && isNodeOfType(node.declaration, 'VariableDeclaration')) {
108
113
  // export const Icon = AddIcon;
109
114
  for (const decl of node.declaration.declarations) {
110
- if (isNodeOfType(decl, 'VariableDeclarator') && 'init' in decl && decl.init && isNodeOfType(decl.init, 'Identifier') && decl.init.name in legacyIconImports) {
115
+ if (isNodeOfType(decl, 'VariableDeclarator') && Object.keys(decl).includes('init') && decl.init && isNodeOfType(decl.init, 'Identifier') && Object.keys(legacyIconImports).includes(decl.init.name)) {
111
116
  createCantMigrateReExportError(node, legacyIconImports[decl.init.name].packageName, decl.init.name, errorsManual);
117
+ addToListOfRanges(node, errorRanges);
112
118
  guidance[locToString(node)] = createGuidance(legacyIconImports[decl.init.name].packageName);
113
119
  }
114
120
  }
@@ -120,13 +126,14 @@ export const createChecks = context => {
120
126
  * export { AddIcon, CrossIcon as default }
121
127
  */
122
128
  for (const spec of node.specifiers) {
123
- if (spec.local.name in legacyIconImports) {
129
+ if (Object.keys(legacyIconImports).includes(spec.local.name)) {
124
130
  //update legacy imports to be exported
125
131
  legacyIconImports[spec.local.name] = {
126
132
  packageName: legacyIconImports[spec.local.name].packageName,
127
133
  exported: true
128
134
  };
129
135
  createCantMigrateReExportError(spec, legacyIconImports[spec.local.name].packageName, spec.exported.name, errorsManual);
136
+ addToListOfRanges(spec, errorRanges);
130
137
  guidance[locToString(spec)] = createGuidance(legacyIconImports[spec.local.name].packageName);
131
138
  }
132
139
  }
@@ -141,8 +148,9 @@ export const createChecks = context => {
141
148
  if (!isNodeOfType(node, 'Identifier')) {
142
149
  return;
143
150
  }
144
- if (node.name && node.name in legacyIconImports && legacyIconImports[node.name].packageName) {
145
- createCantMigrateIdentifierError(node, legacyIconImports[node.name].packageName, node.name, errorsManual);
151
+ if (node.name && Object.keys(legacyIconImports).includes(node.name) && legacyIconImports[node.name].packageName) {
152
+ createCantMigrateIdentifierMapOrArrayError(node, legacyIconImports[node.name].packageName, node.name, errorsManual);
153
+ addToListOfRanges(node, errorRanges);
146
154
  guidance[locToString(node)] = createGuidance(legacyIconImports[node.name].packageName);
147
155
  }
148
156
  };
@@ -161,7 +169,7 @@ export const createChecks = context => {
161
169
  if (!isNodeOfType(node.parent, 'JSXExpressionContainer') || !isNodeOfType(node.parent.parent, 'JSXAttribute') || !isNodeOfType(node.parent.parent.parent, 'JSXOpeningElement')) {
162
170
  return;
163
171
  }
164
- if (node.name in legacyIconImports && isNodeOfType(node.parent.parent.name, 'JSXIdentifier') && node.parent.parent.name.name !== 'LEGACY_fallbackIcon') {
172
+ if (Object.keys(legacyIconImports).includes(node.name) && isNodeOfType(node.parent.parent.name, 'JSXIdentifier') && node.parent.parent.name.name !== 'LEGACY_fallbackIcon') {
165
173
  var _migrationMapObject$s;
166
174
  const migrationMapObject = getMigrationMapObject(legacyIconImports[node.name].packageName);
167
175
  const upcomingIcon = getUpcomingIcons(legacyIconImports[node.name].packageName);
@@ -170,16 +178,35 @@ export const createChecks = context => {
170
178
  const isInNewButton = isNodeOfType(node.parent.parent.parent.name, 'JSXIdentifier') && newButtonImports.has(node.parent.parent.parent.name.name);
171
179
  if (newIcon && isInNewButton && isNewIconMigratable || upcomingIcon && isInNewButton && isNewIconMigratable) {
172
180
  createAutoMigrationError(node, legacyIconImports[node.name].packageName, node.name, errorsAuto);
181
+ addToListOfRanges(node, errorRanges);
173
182
  guidance[locToString(node)] = createGuidance(legacyIconImports[node.name].packageName, isInNewButton, 'medium');
174
183
  } else if (!newIcon && !upcomingIcon || !isNewIconMigratable) {
175
184
  createCantFindSuitableReplacementError(node, legacyIconImports[node.name].packageName, node.name, errorsManual);
185
+ addToListOfRanges(node, errorRanges);
176
186
  guidance[locToString(node)] = createGuidance(legacyIconImports[node.name].packageName, isInNewButton);
177
187
  } else if (!isInNewButton) {
178
188
  createCantMigrateFunctionUnknownError(node, legacyIconImports[node.name].packageName, node.name, errorsManual);
189
+ addToListOfRanges(node, errorRanges);
179
190
  guidance[locToString(node)] = createGuidance(legacyIconImports[node.name].packageName, isInNewButton);
180
191
  }
181
192
  }
182
193
  };
194
+ const checkIconReference = node => {
195
+ //check the reference to see if it's a legacy icon, if not exit early
196
+ if (!Object.keys(legacyIconImports).includes(node.name)) {
197
+ return;
198
+ }
199
+ //if this is an import statement then exit early
200
+ if (node.parent && (isNodeOfType(node.parent, 'ImportSpecifier') || isNodeOfType(node.parent, 'ImportDefaultSpecifier'))) {
201
+ return;
202
+ }
203
+ //if in Fallback prop, do not error
204
+ if (node.parent && node.parent.parent && isNodeOfType(node.parent.parent, 'JSXAttribute') && isNodeOfType(node.parent.parent.name, 'JSXIdentifier') && node.parent.parent.name.name === 'LEGACY_fallbackIcon') {
205
+ return;
206
+ }
207
+ // manually error
208
+ createCantMigrateIdentifierError(node, legacyIconImports[node.name].packageName, node.name, errorsManual);
209
+ };
183
210
 
184
211
  /**
185
212
  * Checks if a legacy icon is being rendered and stores the errors in the global array
@@ -197,7 +224,7 @@ export const createChecks = context => {
197
224
  }
198
225
  const name = node.openingElement.name.name;
199
226
  // Legacy icons rendered as JSX elements
200
- if (name in legacyIconImports) {
227
+ if (Object.keys(legacyIconImports).includes(name)) {
201
228
  var _node$parent2, _node$parent2$parent, _node$parent3, _node$parent3$parent, _node$parent3$parent$, _size, _size2;
202
229
  // Determine if inside a new button - if so:
203
230
  // - Assume spread props are safe - still error if props explicitly set to unmigratable values
@@ -277,6 +304,7 @@ export const createChecks = context => {
277
304
  } else if ((!newIcon && !upcomingIcon || !isNewIconMigratable) && size) {
278
305
  createCantFindSuitableReplacementError(node, legacyIconImports[name].packageName, name, errorsManual, upcomingIcon ? true : migrationMapObject ? true : false);
279
306
  }
307
+ addToListOfRanges(node, errorRanges);
280
308
  guidance[locToString(node)] = createGuidance(legacyIconImports[name].packageName, insideNewButton, size && isSize(size) ? size : undefined);
281
309
  }
282
310
  };
@@ -286,10 +314,11 @@ export const createChecks = context => {
286
314
  * @param node The function call node found by ESLint
287
315
  */
288
316
  const checkCallExpression = node => {
289
- if ('arguments' in node && node.arguments.length) {
317
+ if (Object.keys(node).includes('arguments') && node.arguments.length) {
290
318
  for (const arg of node.arguments) {
291
- if (isNodeOfType(arg, 'Identifier') && arg.name in legacyIconImports && legacyIconImports[arg.name].packageName) {
319
+ if (isNodeOfType(arg, 'Identifier') && Object.keys(legacyIconImports).includes(arg.name) && legacyIconImports[arg.name].packageName) {
292
320
  createCantMigrateFunctionUnknownError(node, legacyIconImports[arg.name].packageName, arg.name, errorsManual);
321
+ addToListOfRanges(node, errorRanges);
293
322
  guidance[locToString(node)] = createGuidance(legacyIconImports[arg.name].packageName);
294
323
  }
295
324
  }
@@ -303,20 +332,29 @@ export const createChecks = context => {
303
332
  if (shouldErrorForManualMigration) {
304
333
  for (const [key, errorList] of Object.entries(errorsManual)) {
305
334
  const node = 'node' in errorList.errors[0] ? errorList.errors[0].node : null;
335
+ const cantMigrateIdentifierError = errorList.errors.find(x => 'messageId' in x && x.messageId === 'cantMigrateIdentifier');
306
336
  if (node) {
307
- const guidanceMessage = key in guidance ? guidance[key] : '';
308
- context.report({
309
- node,
310
- messageId: 'noLegacyIconsManualMigration',
311
- data: {
312
- iconName: errorList.iconName,
313
- importSource: errorList.importSource,
314
- guidance: isQuietMode ? guidanceMessage : `${guidanceMessage}For more information see the below errors.\n`
315
- }
316
- });
317
- if (!isQuietMode) {
318
- for (const error of errorList.errors) {
319
- context.report(error);
337
+ let isInRange = false;
338
+ if (cantMigrateIdentifierError && isInRangeList(node, errorRanges)) {
339
+ isInRange = true;
340
+ }
341
+ if (isInRange && errorList.errors.length - 1 > 0 || !isInRange && errorList.errors.length > 0) {
342
+ const guidanceMessage = Object.keys(guidance).includes(key) ? guidance[key] : '';
343
+ context.report({
344
+ node,
345
+ messageId: 'noLegacyIconsManualMigration',
346
+ data: {
347
+ iconName: errorList.iconName,
348
+ importSource: errorList.importSource,
349
+ guidance: isQuietMode ? guidanceMessage : `${guidanceMessage}For more information see the below errors.\n`
350
+ }
351
+ });
352
+ if (!isQuietMode) {
353
+ for (const error of errorList.errors) {
354
+ if ('messageId' in error && (error.messageId !== 'cantMigrateIdentifier' || error.messageId === 'cantMigrateIdentifier' && !isInRange)) {
355
+ context.report(error);
356
+ }
357
+ }
320
358
  }
321
359
  }
322
360
  }
@@ -326,14 +364,17 @@ export const createChecks = context => {
326
364
  for (const [key, error] of Object.entries(errorsAuto)) {
327
365
  // If there's a manual error that exists for this same component,
328
366
  // don't throw the auto error
329
- if (key in errorsManual) {
330
- delete errorsAuto[key];
331
- continue;
367
+ if (Object.keys(errorsManual).includes(key)) {
368
+ const cantMigrateIdentifierError = errorsManual[key].errors.find(x => 'messageId' in x && x.messageId === 'cantMigrateIdentifier');
369
+ if (!cantMigrateIdentifierError || cantMigrateIdentifierError && errorsManual[key].errors.length > 1) {
370
+ delete errorsAuto[key];
371
+ continue;
372
+ }
332
373
  }
333
374
  const node = 'node' in error ? error.node : null;
334
375
  if (node) {
335
- const guidanceMessage = key in guidance ? guidance[key] : '';
336
- if ('data' in error && error.data) {
376
+ const guidanceMessage = Object.keys(guidance).includes(key) ? guidance[key] : '';
377
+ if (Object.keys(error).includes('data') && error.data) {
337
378
  error.data.guidance = guidanceMessage;
338
379
  }
339
380
  context.report(error);
@@ -350,6 +391,7 @@ export const createChecks = context => {
350
391
  checkIconAsProp,
351
392
  checkJSXElement,
352
393
  checkCallExpression,
353
- throwErrors
394
+ throwErrors,
395
+ checkIconReference
354
396
  };
355
397
  };
@@ -90,12 +90,12 @@ export const createGuidance = (iconPackage, insideNewButton = false, size) => {
90
90
  } else {
91
91
  guidance += `No equivalent icon for this size, ${size}, in new set.`;
92
92
  }
93
- guidance += `${migrationMapObject.sizeGuidance[size] in migrationOutcomeDescriptionMap ? ` Please: ${migrationOutcomeDescriptionMap[migrationMapObject.sizeGuidance[size]]}` : ' No migration size advice given.'}\n`;
93
+ guidance += `${Object.keys(migrationOutcomeDescriptionMap).includes(migrationMapObject.sizeGuidance[size]) ? ` Please: ${migrationOutcomeDescriptionMap[migrationMapObject.sizeGuidance[size]]}` : ' No migration size advice given.'}\n`;
94
94
  } else {
95
95
  guidance = `Use ${newIcon.name} from ${newIcon.package}/${newIcon.type}/${newIcon.name} instead.\nMigration suggestions, depending on the legacy icon size:\n`;
96
96
  Object.entries(migrationMapObject.sizeGuidance).forEach(([size, value]) => {
97
97
  guidance += `\t- ${size}: `;
98
- if (!(value in migrationOutcomeDescriptionMap)) {
98
+ if (!Object.keys(migrationOutcomeDescriptionMap).includes(value)) {
99
99
  guidance += 'No migration advice given.\n';
100
100
  } else {
101
101
  guidance += `${migrationOutcomeDescriptionMap[value]}.\n`;
@@ -134,8 +134,11 @@ export const canMigrateColor = color => {
134
134
  }
135
135
  };
136
136
  export const locToString = node => {
137
- var _node$loc, _node$loc2, _node$loc3, _node$loc4;
138
- return `${(_node$loc = node.loc) === null || _node$loc === void 0 ? void 0 : _node$loc.start.line}:${(_node$loc2 = node.loc) === null || _node$loc2 === void 0 ? void 0 : _node$loc2.start.column}:${(_node$loc3 = node.loc) === null || _node$loc3 === void 0 ? void 0 : _node$loc3.end.line}:${(_node$loc4 = node.loc) === null || _node$loc4 === void 0 ? void 0 : _node$loc4.end.column}`;
137
+ if (node.range && node.range.length >= 2) {
138
+ return `${node.range[0]}:${node.range[1]}`;
139
+ } else {
140
+ return '';
141
+ }
139
142
  };
140
143
  export const createCantMigrateReExportError = (node, packageName, exportName, errors) => {
141
144
  const myError = {
@@ -148,10 +151,10 @@ export const createCantMigrateReExportError = (node, packageName, exportName, er
148
151
  };
149
152
  pushManualError(locToString(node), errors, myError, packageName, exportName);
150
153
  };
151
- export const createCantMigrateIdentifierError = (node, packageName, exportName, errors) => {
154
+ export const createCantMigrateIdentifierMapOrArrayError = (node, packageName, exportName, errors) => {
152
155
  const myError = {
153
156
  node,
154
- messageId: 'cantMigrateIdentifier',
157
+ messageId: 'cantMigrateIdentifierMapOrArray',
155
158
  data: {
156
159
  packageName,
157
160
  exportName
@@ -159,6 +162,17 @@ export const createCantMigrateIdentifierError = (node, packageName, exportName,
159
162
  };
160
163
  pushManualError(locToString(node), errors, myError, packageName, exportName);
161
164
  };
165
+ export const createCantMigrateIdentifierError = (node, packageName, exportName, errors) => {
166
+ const myError = {
167
+ node,
168
+ messageId: 'cantMigrateIdentifier',
169
+ data: {
170
+ iconSource: packageName,
171
+ iconName: exportName
172
+ }
173
+ };
174
+ pushManualError(locToString(node), errors, myError, packageName, exportName);
175
+ };
162
176
  export const createCantFindSuitableReplacementError = (node, importSource, iconName, errors, sizeIssue) => {
163
177
  const myError = {
164
178
  node,
@@ -221,7 +235,7 @@ export const createAutoMigrationError = (node, importSource, iconName, errors) =
221
235
  errors[locToString(node)] = myError;
222
236
  };
223
237
  const pushManualError = (key, errors, myError, importSource, iconName) => {
224
- if (key in errors) {
238
+ if (Object.keys(errors).includes(key)) {
225
239
  errors[key].errors.push(myError);
226
240
  } else {
227
241
  errors[key] = {
@@ -269,7 +283,7 @@ export const createHelpers = context => {
269
283
  * @returns defaultValue if the configuration flag is not set, the defaultValue of the configuration flag otherwise
270
284
  */
271
285
  const getConfigFlag = (key, defaultValue) => {
272
- if (context.options.length > 0 && context.options[0] && key in context.options[0]) {
286
+ if (context.options.length > 0 && context.options[0] && Object.keys(context.options[0]).includes(key)) {
273
287
  return context.options[0][key] === !defaultValue ? !defaultValue : defaultValue;
274
288
  }
275
289
  return defaultValue;
@@ -288,4 +302,22 @@ export const createHelpers = context => {
288
302
  getTokenCallValue,
289
303
  getConfigFlag
290
304
  };
305
+ };
306
+ export const addToListOfRanges = (node, sortedListOfRangesForErrors) => {
307
+ if (node.range && node.range.length >= 2) {
308
+ sortedListOfRangesForErrors.push({
309
+ start: node.range[0],
310
+ end: node.range[1]
311
+ });
312
+ }
313
+ };
314
+ export const isInRangeList = (node, sortedListOfRangesForErrors) => {
315
+ const {
316
+ range
317
+ } = node;
318
+ if (!range || range.length < 2) {
319
+ return false;
320
+ }
321
+ const found = sortedListOfRangesForErrors.find(currRange => range[0] >= currRange.start && range[1] <= currRange.end);
322
+ return !!found;
291
323
  };
@@ -35,8 +35,8 @@ const rule = createLintRule({
35
35
  cantMigrateSpreadProps: `This usage of Icon uses spread props in a way that can't be automatically migrated. Please explicitly define the following props after spread: '{{missingProps}}' `,
36
36
  cantMigrateSizeUnknown: `This usage of Icon sets the size via a variable or function that can't be determined.`,
37
37
  cantMigrateFunctionUnknown: `'{{iconName}}' from legacy '{{importSource}}' is used in unknown function/component. Please manually migrate this icon.`,
38
- cantMigrateIdentifier: `This icon is passed to other components via a map or array, in a way that can't be automatically migrated. Please manually migrate wherever this expression is used and use the icon components directly.`,
39
- cantMigrateUnsafeProp: `Property '{{propName}}' with value of '{{value}}' is unable to be auto-migrated to the new button. Please manually migrate this icon.`
38
+ cantMigrateIdentifierMapOrArray: `This icon is passed to other components via a map or array, in a way that can't be automatically migrated. Please manually migrate wherever this expression is used and use the icon components directly.`,
39
+ cantMigrateIdentifier: `This is a legacy icon, {{iconName}} from {{iconSource}}, being referenced. Please manually migrate.`
40
40
  }
41
41
  },
42
42
  create(context) {
@@ -53,7 +53,8 @@ const rule = createLintRule({
53
53
  checkIconAsProp,
54
54
  checkJSXElement,
55
55
  checkCallExpression,
56
- throwErrors
56
+ throwErrors,
57
+ checkIconReference
57
58
  } = createChecks(context);
58
59
  return errorBoundary({
59
60
  // Track imports of relevant components
@@ -70,6 +71,7 @@ const rule = createLintRule({
70
71
  JSXElement: checkJSXElement,
71
72
  // Icons called as an argument of a function (i.e. icon={DefaultIcon(AddIcon)})
72
73
  CallExpression: checkCallExpression,
74
+ Identifier: checkIconReference,
73
75
  'Program:exit': throwErrors
74
76
  }, failSilently);
75
77
  }