Browse Source

build: enable `useFlatMap` and `useIsArray` rules (#64693)

Enables `useFlatMap` for reducing array iterations where `.map().flat()`
exist

---------

Co-authored-by: getsantry[bot] <66042841+getsantry[bot]@users.noreply.github.com>
Yagiz Nizipli 1 year ago
parent
commit
ac45f7f9bb

+ 6 - 0
biome.json

@@ -13,11 +13,17 @@
     "enabled": true,
     "rules": {
       "recommended": false,
+      "complexity": {
+        "useFlatMap": "error"
+      },
       "nursery": {
         "noDuplicateJsonKeys": "error",
         "noNodejsModules": "error",
         "useExportType": "error",
         "useImportType": "error"
+      },
+      "suspicious": {
+        "useIsArray": "error"
       }
     }
   },

+ 1 - 2
static/app/components/compactSelect/utils.tsx

@@ -112,7 +112,7 @@ export function getHiddenOptions<Value extends React.Key>(
 
   const hiddenOptionsSet = new Set<Value>();
   const remainingItems = items
-    .map<SelectOptionOrSection<Value> | null>(item => {
+    .flatMap<SelectOptionOrSection<Value> | null>(item => {
       if ('options' in item) {
         const filteredOptions = item.options
           .map(opt => {
@@ -135,7 +135,6 @@ export function getHiddenOptions<Value extends React.Key>(
       hiddenOptionsSet.add(item.value);
       return null;
     })
-    .flat()
     .filter((item): item is SelectOptionOrSection<Value> => !!item);
 
   //

+ 2 - 3
static/app/components/events/interfaces/crashContent/exception/actionableItems.tsx

@@ -326,13 +326,12 @@ function groupedErrors(
   const {_meta} = event;
   const errors = [...data.errors, ...progaurdErrors]
     .filter(error => shouldErrorBeShown(error, event))
-    .map((error, errorIdx) =>
+    .flatMap((error, errorIdx) =>
       getErrorMessage(error, _meta?.errors?.[errorIdx]).map(message => ({
         ...message,
         type: error.type,
       }))
-    )
-    .flat();
+    );
 
   const grouped = errors.reduce((rv, error) => {
     rv[error.type] = rv[error.type] || [];

+ 4 - 9
static/app/components/events/interfaces/crashContent/exception/sourceMapDebug.tsx

@@ -217,17 +217,12 @@ function combineErrors(
   sdkName?: string
 ) {
   const combinedErrors = uniqBy(
-    response
-      .map(res => res?.errors)
-      .flat()
-      .filter(defined),
+    response.flatMap(res => res?.errors).filter(defined),
     error => error?.type
   );
-  const errors = combinedErrors
-    .map(error =>
-      getErrorMessage(error, sdkName).map(message => ({...message, type: error.type}))
-    )
-    .flat();
+  const errors = combinedErrors.flatMap(error =>
+    getErrorMessage(error, sdkName).map(message => ({...message, type: error.type}))
+  );
 
   return errors;
 }

+ 5 - 4
static/app/components/events/interfaces/spans/traceView.tsx

@@ -86,11 +86,12 @@ function TraceView(props: Props) {
     (!waterfallModel.affectedSpanIds || !waterfallModel.affectedSpanIds.length) &&
     performanceIssues
   ) {
-    const suspectSpans = performanceIssues.map(issue => issue.suspect_spans).flat();
+    const suspectSpans = performanceIssues.flatMap(issue => issue.suspect_spans);
     if (suspectSpans.length) {
-      waterfallModel.affectedSpanIds = performanceIssues
-        .map(issue => [...issue.suspect_spans, ...issue.span])
-        .flat();
+      waterfallModel.affectedSpanIds = performanceIssues.flatMap(issue => [
+        ...issue.suspect_spans,
+        ...issue.span,
+      ]);
     }
   }
 

+ 1 - 1
static/app/components/smartSearchBar/utils.tsx

@@ -333,7 +333,7 @@ export function getValidOps(
 
   // Find all valid operations
   const validOps = new Set<TermOperator>(
-    allValidTypes.map(type => filterTypeConfig[type].validOps).flat()
+    allValidTypes.flatMap(type => filterTypeConfig[type].validOps)
   );
 
   return [...validOps];

+ 10 - 16
static/app/utils/events.tsx

@@ -17,7 +17,7 @@ import {
   IssueCategory,
   IssueType,
 } from 'sentry/types';
-import type {Event, ExceptionValue, Thread} from 'sentry/types/event';
+import type {Event, ExceptionValue, Frame, Thread} from 'sentry/types/event';
 import {EntryType} from 'sentry/types/event';
 import {defined} from 'sentry/utils';
 import type {BaseEventAnalyticsParams} from 'sentry/utils/analytics/workflowAnalyticsEvents';
@@ -309,10 +309,8 @@ export function getFrameBreakdownOfSourcemaps(event?: Event | null) {
 function getExceptionFrames(event: Event, inAppOnly: boolean) {
   const exceptions = getExceptionEntries(event);
   const frames = exceptions
-    .map(exception => exception.data.values || [])
-    .flat()
-    .map(exceptionValue => exceptionValue?.stacktrace?.frames || [])
-    .flat();
+    .flatMap(exception => exception.data.values || [])
+    .flatMap(exceptionValue => exceptionValue?.stacktrace?.frames || []);
   return inAppOnly ? frames.filter(frame => frame.inApp) : frames;
 }
 
@@ -327,18 +325,14 @@ function getExceptionEntries(event: Event) {
 /**
  * Returns all stack frames of type 'exception' or 'threads' of this event
  */
-function getAllFrames(event: Event, inAppOnly: boolean) {
-  const exceptions = getEntriesWithFrames(event);
-  const frames = exceptions
-    .map(
-      (withStacktrace: EntryException | EntryThreads) => withStacktrace.data.values || []
-    )
-    .flat()
-    .map(
+function getAllFrames(event: Event, inAppOnly: boolean): Frame[] {
+  const exceptions: EntryException[] | EntryThreads[] = getEntriesWithFrames(event);
+  const frames: Frame[] = exceptions
+    .flatMap(withStacktrace => withStacktrace.data.values ?? [])
+    .flatMap(
       (withStacktrace: ExceptionValue | Thread) =>
-        withStacktrace?.stacktrace?.frames || []
-    )
-    .flat();
+        withStacktrace?.stacktrace?.frames ?? []
+    );
   return inAppOnly ? frames.filter(frame => frame.inApp) : frames;
 }
 

+ 1 - 2
static/app/utils/metrics/useMetricsCorrelations.tsx

@@ -152,8 +152,7 @@ export function useMetricSamples(
   }
 
   const data = queryInfo.data.metrics
-    .map(m => m.metricSpans)
-    .flat()
+    .flatMap(m => m.metricSpans)
     .filter(correlation => !!correlation)
     .slice(0, 10) as MetricCorrelation[];
 

+ 6 - 8
static/app/utils/middleEllipsis.tsx

@@ -54,16 +54,14 @@ export function middleEllipsis(
   if (getLength(words) <= maxLength) {
     const divider = Math.floor(words.length / 2);
     const firstHalf = words.slice(0, divider);
-    const firstHalfWithDelimiters = firstHalf
-      .map((word, i) => (i === divider - 1 ? [word] : [word, delimiters[i]]))
-      .flat();
+    const firstHalfWithDelimiters = firstHalf.flatMap((word, i) =>
+      i === divider - 1 ? [word] : [word, delimiters[i]]
+    );
 
     const secondHalf = words.slice(divider);
-    const secondHalfWithDelimiters = secondHalf
-      .map((word, i) =>
-        i === 0 ? [word] : [delimiters[delimiters.length - secondHalf.length + i], word]
-      )
-      .flat();
+    const secondHalfWithDelimiters = secondHalf.flatMap((word, i) =>
+      i === 0 ? [word] : [delimiters[delimiters.length - secondHalf.length + i], word]
+    );
 
     return `${firstHalfWithDelimiters.join('')}\u2026${secondHalfWithDelimiters.join(
       ''

+ 11 - 13
static/app/utils/prism.tsx

@@ -16,20 +16,18 @@ Prism.manual = true;
  * (`javascript`).
  */
 const PRISM_LANGUAGE_MAP: Record<string, string> = Object.fromEntries(
-  Object.entries(prismComponents.languages)
-    .map(([lang, value]) => {
-      if (!value.alias) {
-        return [[lang, lang]]; // map the full language name to itself
-      }
+  Object.entries(prismComponents.languages).flatMap(([lang, value]) => {
+    if (!value.alias) {
+      return [[lang, lang]]; // map the full language name to itself
+    }
 
-      return [
-        [lang, lang], // map the full language name to itself
-        ...(Array.isArray(value.alias) // map aliases to full language name
-          ? value.alias.map(alias => [alias, lang])
-          : [[value.alias, lang]]),
-      ];
-    })
-    .flat(1)
+    return [
+      [lang, lang], // map the full language name to itself
+      ...(Array.isArray(value.alias) // map aliases to full language name
+        ? value.alias.map(alias => [alias, lang])
+        : [[value.alias, lang]]),
+    ];
+  })
 );
 
 // Aliases that don't already exist in Prism.js

Some files were not shown because too many files changed in this diff