diff --git a/packages/babel-plugin-component-annotate/src/index.ts b/packages/babel-plugin-component-annotate/src/index.ts index 0cd087d9..b1f0af1f 100644 --- a/packages/babel-plugin-component-annotate/src/index.ts +++ b/packages/babel-plugin-component-annotate/src/index.ts @@ -533,6 +533,29 @@ function getPathName(t: typeof Babel.types, path: Babel.NodePath): string { return name.name.name; } + // Handle JSX member expressions like Tab.Group + if (t.isJSXMemberExpression(name)) { + const objectName = getJSXMemberExpressionObjectName(t, name.object); + const propertyName = name.property.name; + return `${objectName}.${propertyName}`; + } + + return UNKNOWN_ELEMENT_NAME; +} + +// Recursively handle nested member expressions (e.g. Components.UI.Header) +function getJSXMemberExpressionObjectName( + t: typeof Babel.types, + object: Babel.types.JSXMemberExpression | Babel.types.JSXIdentifier +): string { + if (t.isJSXIdentifier(object)) { + return object.name; + } + if (t.isJSXMemberExpression(object)) { + const objectName = getJSXMemberExpressionObjectName(t, object.object); + return `${objectName}.${object.property.name}`; + } + return UNKNOWN_ELEMENT_NAME; } diff --git a/packages/babel-plugin-component-annotate/test/__snapshots__/test-plugin.test.ts.snap b/packages/babel-plugin-component-annotate/test/__snapshots__/test-plugin.test.ts.snap index adb23ee5..af43b6c0 100644 --- a/packages/babel-plugin-component-annotate/test/__snapshots__/test-plugin.test.ts.snap +++ b/packages/babel-plugin-component-annotate/test/__snapshots__/test-plugin.test.ts.snap @@ -223,6 +223,20 @@ class componentName extends Component { export default componentName;" `; +exports[`handles nested member expressions in component names 1`] = ` +"import React from 'react'; +import { Components } from 'my-ui-library'; +export default function TestComponent() { + return /*#__PURE__*/React.createElement(\\"div\\", { + \\"data-sentry-component\\": \\"TestComponent\\", + \\"data-sentry-source-file\\": \\"filename-test.js\\" + }, /*#__PURE__*/React.createElement(Components.UI.Button, null, \\"Click me\\"), /*#__PURE__*/React.createElement(Components.UI.Card.Header, { + \\"data-sentry-element\\": \\"Components.UI.Card.Header\\", + \\"data-sentry-source-file\\": \\"filename-test.js\\" + }, \\"Title\\")); +}" +`; + exports[`handles ternary operation returned by function body 1`] = ` "const maybeTrue = Math.random() > 0.5; export default function componentName() { @@ -233,6 +247,30 @@ export default function componentName() { }" `; +exports[`ignores React.Fragment with member expression handling 1`] = ` +"import React from 'react'; +export default function TestComponent() { + return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(\\"div\\", null, \\"Content\\")); +}" +`; + +exports[`ignores components with member expressions when in ignoredComponents 1`] = ` +"import React from 'react'; +import { Tab } from '@headlessui/react'; +export default function TestComponent() { + return /*#__PURE__*/React.createElement(\\"div\\", { + \\"data-sentry-component\\": \\"TestComponent\\", + \\"data-sentry-source-file\\": \\"filename-test.js\\" + }, /*#__PURE__*/React.createElement(Tab.Group, null, /*#__PURE__*/React.createElement(Tab.List, null, /*#__PURE__*/React.createElement(Tab, { + \\"data-sentry-element\\": \\"Tab\\", + \\"data-sentry-source-file\\": \\"filename-test.js\\" + }, \\"Tab 1\\"), /*#__PURE__*/React.createElement(Tab, { + \\"data-sentry-element\\": \\"Tab\\", + \\"data-sentry-source-file\\": \\"filename-test.js\\" + }, \\"Tab 2\\")), /*#__PURE__*/React.createElement(Tab.Panels, null, /*#__PURE__*/React.createElement(Tab.Panel, null, \\"Content 1\\"), /*#__PURE__*/React.createElement(Tab.Panel, null, \\"Content 2\\")))); +}" +`; + exports[`nonJSX snapshot matches 1`] = ` "import React, { Component } from 'react'; class TestClass extends Component { diff --git a/packages/babel-plugin-component-annotate/test/test-plugin.test.ts b/packages/babel-plugin-component-annotate/test/test-plugin.test.ts index 7dce87ad..7d6a73e8 100644 --- a/packages/babel-plugin-component-annotate/test/test-plugin.test.ts +++ b/packages/babel-plugin-component-annotate/test/test-plugin.test.ts @@ -1187,3 +1187,96 @@ export default function componentName() { ); expect(result?.code).toMatchSnapshot(); }); + +it("ignores components with member expressions when in ignoredComponents", () => { + const result = transform( + `import React from 'react'; +import { Tab } from '@headlessui/react'; + +export default function TestComponent() { + return ( +