Просмотр исходного кода

ref(js) remove lodash/get (#16614)

* Add no lodash/get to es-lint

* Remove lodash/get from contexts.jsx

* Remove lodash/get from utils

* Remove lodash/get from permissionSelection

* Remove lodash/get from header.tsx

* Remove lodash/get from sentryApplicationDetails.tsx

* Remove lodash/get from modal.jsx

* Remove lodash/get from navigation.jsx

* Remove lodash/get from stacktraceContent.jsx

* Remove lodash/get from app.jsx

* Remove lodash/get from sentryAppExternalInstallation.tsx

* Remove lodash/get from api.tsx

* Remove lodash/get from debugmeta.jsx

* Partially remove lodash/get from traceView.tsx

* Remove lodash/get from spanTree.tsx

* Remove lodash/get from formatters.tsx

* Remove lodash/get from spanBar.tsx

* Remove lodash/get from spanDetail.tsx

* Add TODO

* Update eslintrc message

* fix remaining lodash/get

Co-authored-by: Billy Vong <billy@sentry.io>
jeffkwoh 5 лет назад
Родитель
Сommit
5a7c73fba5

+ 10 - 1
.eslintrc.js

@@ -9,7 +9,16 @@ module.exports = {
     tick: true,
     jest: true,
   },
-  rules: {},
+  rules: {
+    'no-restricted-imports': [
+      'error',
+      {
+        name: 'lodash/get',
+        message:
+          'Optional chaining `?.` and nullish coalescing operators `??` are available and preferred over using `lodash/get`',
+      },
+    ],
+  },
   overrides: [
     {
       files: ['*.ts', '*.tsx'],

+ 8 - 5
src/sentry/static/sentry/app/actionCreators/navigation.tsx

@@ -1,16 +1,17 @@
-import React from 'react';
-import get from 'lodash/get';
 import {InjectedRouter} from 'react-router/lib/Router';
+import {Location} from 'history';
+import React from 'react';
 
 import {openModal} from 'app/actionCreators/modal';
 import ContextPickerModal from 'app/components/contextPickerModal';
 import NavigationActions from 'app/actions/navigationActions';
 
-export function navigateTo(to: string, router: InjectedRouter) {
+// TODO(ts): figure out better typing for react-router here
+export function navigateTo(to: string, router: InjectedRouter & {location?: Location}) {
   // Check for placeholder params
   const needOrg = to.indexOf(':orgId') > -1;
   const needProject = to.indexOf(':projectId') > -1;
-  const comingFromProjectId = get(router, 'location.query.project');
+  const comingFromProjectId = router?.location?.query?.project;
 
   if (needOrg || needProject) {
     openModal(
@@ -20,7 +21,9 @@ export function navigateTo(to: string, router: InjectedRouter) {
           nextPath={to}
           needOrg={needOrg}
           needProject={needProject}
-          comingFromProjectId={comingFromProjectId}
+          comingFromProjectId={
+            Array.isArray(comingFromProjectId) ? '' : comingFromProjectId || ''
+          }
           onFinish={path => {
             modalProps.closeModal();
             setTimeout(() => router.push(path), 0);

+ 3 - 4
src/sentry/static/sentry/app/api.tsx

@@ -1,6 +1,5 @@
 import isUndefined from 'lodash/isUndefined';
 import isNil from 'lodash/isNil';
-import get from 'lodash/get';
 import $ from 'jquery';
 import {Severity} from '@sentry/browser';
 
@@ -124,7 +123,7 @@ export class Client {
    */
   // TODO: refine this type later
   hasProjectBeenRenamed(response: JQueryXHR) {
-    const code = get(response, 'responseJSON.detail.code');
+    const code = response?.responseJSON?.detail?.code;
 
     // XXX(billy): This actually will never happen because we can't intercept the 302
     // jQuery ajax will follow the redirect by default...
@@ -132,7 +131,7 @@ export class Client {
       return false;
     }
 
-    const slug = get(response, 'responseJSON.detail.extra.slug');
+    const slug = response?.responseJSON?.detail?.extra?.slug;
 
     redirectToProject(slug);
     return true;
@@ -186,7 +185,7 @@ export class Client {
     textStatus: string,
     errorThrown: string
   ) {
-    const code = get(response, 'responseJSON.detail.code');
+    const code = response?.responseJSON?.detail?.code;
     const isSudoRequired = code === SUDO_REQUIRED || code === SUPERUSER_REQUIRED;
 
     if (isSudoRequired) {

+ 1 - 2
src/sentry/static/sentry/app/components/events/contexts.jsx

@@ -1,6 +1,5 @@
 import PropTypes from 'prop-types';
 import React from 'react';
-import get from 'lodash/get';
 
 import {objectIsEmpty, toTitleCase, defined} from 'app/utils';
 import EventDataSection from 'app/components/events/eventDataSection';
@@ -55,7 +54,7 @@ class ContextChunk extends React.Component {
   componentDidUpdate(prevProps) {
     if (
       prevProps.type !== this.props.type ||
-      get(prevProps, 'group.id') !== get(this.props, 'group.id')
+      prevProps?.group?.id !== this.props?.group?.id
     ) {
       this.syncPlugin();
     }

+ 2 - 5
src/sentry/static/sentry/app/components/events/interfaces/debugmeta.jsx

@@ -2,7 +2,6 @@ import isNil from 'lodash/isNil';
 import PropTypes from 'prop-types';
 import React from 'react';
 import styled from '@emotion/styled';
-import get from 'lodash/get';
 
 import Access from 'app/components/acl/access';
 import GuideAnchor from 'app/components/assistant/guideAnchor';
@@ -451,10 +450,8 @@ class DebugMetaInterface extends React.PureComponent {
       </GuideAnchor>
     );
 
-    const frames = get(
-      this.props.event.entries.find(({type}) => type === 'exception'),
-      'data.values[0].stacktrace.frames'
-    );
+    const frames = this.props.event.entries.find(({type}) => type === 'exception')?.data
+      ?.values?.[0]?.stacktrace?.frames;
     const foundFrame = frames
       ? frames.find(frame => frame.instructionAddr === this.state.filter)
       : null;

+ 1 - 2
src/sentry/static/sentry/app/components/events/interfaces/spans/header.tsx

@@ -1,6 +1,5 @@
 import React from 'react';
 import styled from '@emotion/styled';
-import get from 'lodash/get';
 
 import space from 'app/styles/space';
 
@@ -412,7 +411,7 @@ class ActualMinimap extends React.PureComponent<{trace: ParsedTraceType}> {
 
     const {left: spanLeft, width: spanWidth} = this.getBounds(bounds);
 
-    const spanChildren: Array<RawSpanType> = get(childSpans, getSpanID(span), []);
+    const spanChildren: Array<RawSpanType> = childSpans?.[getSpanID(span)] ?? [];
 
     type AccType = {
       nextSpanNumber: number;

+ 1 - 2
src/sentry/static/sentry/app/components/events/interfaces/spans/spanBar.tsx

@@ -1,6 +1,5 @@
 import React from 'react';
 import styled from '@emotion/styled';
-import get from 'lodash/get';
 import 'intersection-observer'; // this is a polyfill
 
 import {t} from 'app/locale';
@@ -382,7 +381,7 @@ class SpanBar extends React.Component<SpanBarProps, SpanBarState> {
     ) : (
       ''
     );
-    const description = get(span, 'description', getSpanID(span));
+    const description = span?.description ?? getSpanID(span);
 
     const left = treeDepth * (TOGGLE_BORDER_BOX / 2) + MARGIN_LEFT;
 

+ 3 - 4
src/sentry/static/sentry/app/components/events/interfaces/spans/spanDetail.tsx

@@ -1,6 +1,5 @@
 import React from 'react';
 import styled from '@emotion/styled';
-import get from 'lodash/get';
 import map from 'lodash/map';
 
 import {t} from 'app/locale';
@@ -231,7 +230,7 @@ class SpanDetail extends React.Component<Props, State> {
               {span.trace_id}
             </Row>
             <Row title="Parent Span ID">{span.parent_span_id || ''}</Row>
-            <Row title="Description">{get(span, 'description', '')}</Row>
+            <Row title="Description">{span?.description ?? ''}</Row>
             <Row title="Start Date">
               {getDynamicText({
                 fixed: 'Mar 16, 2020 9:10:12 AM UTC',
@@ -260,7 +259,7 @@ class SpanDetail extends React.Component<Props, State> {
               {String(!!span.same_process_as_parent)}
             </Row>
             <Tags span={span} />
-            {map(get(span, 'data', {}), (value, key) => (
+            {map(span?.data ?? {}, (value, key) => (
               <Row title={key} key={key}>
                 {JSON.stringify(value, null, 4) || ''}
               </Row>
@@ -317,7 +316,7 @@ const Row = ({
 };
 
 const Tags = ({span}: {span: RawSpanType}) => {
-  const tags: {[tag_name: string]: string} | undefined = get(span, 'tags');
+  const tags: {[tag_name: string]: string} | undefined = span?.tags;
 
   if (!tags) {
     return null;

+ 1 - 2
src/sentry/static/sentry/app/components/events/interfaces/spans/spanTree.tsx

@@ -1,6 +1,5 @@
 import React from 'react';
 import styled from '@emotion/styled';
-import get from 'lodash/get';
 
 import {t} from 'app/locale';
 import EventView from 'app/utils/discover/eventView';
@@ -140,7 +139,7 @@ class SpanTree extends React.Component<PropType> {
     const {orgId, eventView, event} = this.props;
 
     const spanBarColour: string = pickSpanBarColour(getSpanOperation(span));
-    const spanChildren: Array<RawSpanType> = get(childSpans, getSpanID(span), []);
+    const spanChildren: Array<RawSpanType> = childSpans?.[getSpanID(span)] ?? [];
 
     const bounds = generateBounds({
       startTimestamp: span.start_timestamp,

+ 5 - 10
src/sentry/static/sentry/app/components/events/interfaces/spans/traceView.tsx

@@ -1,5 +1,4 @@
 import React from 'react';
-import get from 'lodash/get';
 import set from 'lodash/set';
 import pick from 'lodash/pick';
 import isNumber from 'lodash/isNumber';
@@ -123,14 +122,14 @@ class TraceView extends React.PureComponent<Props, State> {
 
         let tagKeys: string[] = [];
         let tagValues: string[] = [];
-        const tags: {[tag_name: string]: string} | undefined = get(span, 'tags');
+        const tags: {[tag_name: string]: string} | undefined = span?.tags;
 
         if (tags) {
           tagKeys = Object.keys(tags);
           tagValues = Object.values(tags);
         }
 
-        const data: {[data_name: string]: any} | undefined = get(span, 'data', {});
+        const data: {[data_name: string]: any} | undefined = span?.data ?? {};
 
         let dataKeys: string[] = [];
         let dataValues: string[] = [];
@@ -230,7 +229,7 @@ class TraceView extends React.PureComponent<Props, State> {
 function getTraceContext(
   event: Readonly<SentryTransactionEvent>
 ): TraceContextType | undefined {
-  const traceContext: TraceContextType | undefined = get(event, 'contexts.trace');
+  const traceContext: TraceContextType | undefined = event?.contexts?.trace;
 
   return traceContext;
 }
@@ -240,7 +239,7 @@ function parseTrace(event: Readonly<SentryTransactionEvent>): ParsedTraceType {
     (entry: {type: string}) => entry.type === 'spans'
   );
 
-  const spans: Array<RawSpanType> = get(spanEntry, 'data', []);
+  const spans: Array<RawSpanType> = spanEntry?.data ?? [];
 
   const traceContext = getTraceContext(event);
   const traceID = (traceContext && traceContext.trace_id) || '';
@@ -281,11 +280,7 @@ function parseTrace(event: Readonly<SentryTransactionEvent>): ParsedTraceType {
       return acc;
     }
 
-    const spanChildren: Array<RawSpanType> = get(
-      acc.childSpans,
-      span.parent_span_id!,
-      []
-    );
+    const spanChildren: Array<RawSpanType> = acc.childSpans?.[span.parent_span_id!] ?? [];
 
     spanChildren.push(span);
 

Некоторые файлы не были показаны из-за большого количества измененных файлов