diff --git a/.eslintignore b/.eslintignore
index 2593400242b0a..215132a8225ed 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -21,6 +21,7 @@ packages/react-devtools-extensions/chrome/build
packages/react-devtools-extensions/firefox/build
packages/react-devtools-extensions/shared/build
packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/
+packages/react-devtools-extensions/src/__tests__/__source__/__untransformed__/
packages/react-devtools-extensions/src/ErrorTesterCompiled.js
packages/react-devtools-inline/dist
packages/react-devtools-shell/dist
diff --git a/.prettierignore b/.prettierignore
index d944a5e628fa7..adf1716fd4fa8 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -3,6 +3,7 @@ packages/react-devtools-extensions/chrome/build
packages/react-devtools-extensions/firefox/build
packages/react-devtools-extensions/shared/build
packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/
+packages/react-devtools-extensions/src/__tests__/__source__/__untransformed__/
packages/react-devtools-extensions/src/ErrorTesterCompiled.js
packages/react-devtools-inline/dist
packages/react-devtools-shell/dist
diff --git a/packages/react-devtools-extensions/src/__tests__/__source__/ComponentWithMultipleHooksPerLine.js b/packages/react-devtools-extensions/src/__tests__/__source__/ComponentWithMultipleHooksPerLine.js
new file mode 100644
index 0000000000000..ef84503918354
--- /dev/null
+++ b/packages/react-devtools-extensions/src/__tests__/__source__/ComponentWithMultipleHooksPerLine.js
@@ -0,0 +1,23 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ * @flow
+ */
+
+import {createContext, useContext} from 'react';
+
+const A = createContext(1);
+const B = createContext(2);
+
+export function Component() {
+ const a = useContext(A);
+ const b = useContext(B);
+
+ // prettier-ignore
+ const c = useContext(A), d = useContext(B); // eslint-disable-line one-var
+
+ return a + b + c + d;
+}
diff --git a/packages/react-devtools-extensions/src/__tests__/README.md b/packages/react-devtools-extensions/src/__tests__/__source__/README.md
similarity index 100%
rename from packages/react-devtools-extensions/src/__tests__/README.md
rename to packages/react-devtools-extensions/src/__tests__/__source__/README.md
diff --git a/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/bundle/index.js b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/bundle/index.js
index 6bb598647662f..0af8d182714d6 100644
--- a/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/bundle/index.js
+++ b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/bundle/index.js
@@ -71,7 +71,27 @@ function Component$1() {
*
* @flow
*/
+const A = /*#__PURE__*/React.createContext(1);
+const B = /*#__PURE__*/React.createContext(2);
function Component$2() {
+ const a = React.useContext(A);
+ const b = React.useContext(B); // prettier-ignore
+
+ const c = React.useContext(A),
+ d = React.useContext(B); // eslint-disable-line one-var
+
+ return a + b + c + d;
+}
+
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ * @flow
+ */
+function Component$3() {
const [count, setCount] = React.useState(0);
return /*#__PURE__*/React__default.createElement("div", null, /*#__PURE__*/React__default.createElement("p", null, "You clicked ", count, " times"), /*#__PURE__*/React__default.createElement("button", {
onClick: () => setCount(count + 1)
@@ -86,7 +106,7 @@ function Component$2() {
*
* @flow
*/
-function Component$3() {
+function Component$4() {
const [count] = require('react').useState(0);
return count;
@@ -191,8 +211,9 @@ var ToDoList = /*#__PURE__*/Object.freeze({
exports.ComponentWithCustomHook = Component;
exports.ComponentWithExternalCustomHooks = Component$1;
-exports.Example = Component$2;
-exports.InlineRequire = Component$3;
+exports.ComponentWithMultipleHooksPerLine = Component$2;
+exports.Example = Component$3;
+exports.InlineRequire = Component$4;
exports.ToDoList = ToDoList;
exports.useTheme = useTheme;
//# sourceMappingURL=index.js.map
diff --git a/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/bundle/index.js.map b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/bundle/index.js.map
index 1a4fb620f9286..d5cafbbb11448 100644
--- a/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/bundle/index.js.map
+++ b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/bundle/index.js.map
@@ -1 +1 @@
-{"version":3,"file":"index.js","sources":["../../ComponentWithCustomHook.js","../../useTheme.js","../../ComponentWithExternalCustomHooks.js","../../Example.js","../../InlineRequire.js","../../ToDoList.js"],"sourcesContent":["/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport React, {useEffect, useState} from 'react';\n\nexport function Component() {\n const [count, setCount] = useState(0);\n const isDarkMode = useIsDarkMode();\n\n useEffect(() => {\n // ...\n }, []);\n\n const handleClick = () => setCount(count + 1);\n\n return (\n <>\n
Dark mode? {isDarkMode}
\n
Count: {count}
\n \n >\n );\n}\n\nfunction useIsDarkMode() {\n const [isDarkMode] = useState(false);\n\n useEffect(function useEffectCreate() {\n // Here is where we may listen to a \"theme\" event...\n }, []);\n\n return isDarkMode;\n}\n","/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {createContext, useContext, useDebugValue} from 'react';\n\nexport const ThemeContext = createContext('bright');\n\nexport default function useTheme() {\n const theme = useContext(ThemeContext);\n useDebugValue(theme);\n return theme;\n}\n","/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport React from 'react';\nimport useTheme from './useTheme';\n\nexport function Component() {\n const theme = useTheme();\n\n return
theme: {theme}
;\n}\n","/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport React, {useState} from 'react';\n\nexport function Component() {\n const [count, setCount] = useState(0);\n\n return (\n
\n
You clicked {count} times
\n \n
\n );\n}\n","/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport function Component() {\n const [count] = require('react').useState(0);\n\n return count;\n}\n","/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {Fragment, useCallback, useState} from 'react';\n\nexport function ListItem({item, removeItem, toggleItem}) {\n const handleDelete = useCallback(() => {\n removeItem(item);\n }, [item, removeItem]);\n\n const handleToggle = useCallback(() => {\n toggleItem(item);\n }, [item, toggleItem]);\n\n return (\n
\n \n );\n}\n"],"names":["Component","count","setCount","useState","isDarkMode","useIsDarkMode","useEffect","handleClick","React","useEffectCreate","ThemeContext","createContext","useTheme","theme","useContext","useDebugValue","require","ListItem","item","removeItem","toggleItem","handleDelete","useCallback","handleToggle","React.createElement","isComplete","text","List","props","newItemText","setNewItemText","items","setItems","id","uid","setUID","handleKeyPress","event","key","handleChange","currentTarget","value","itemToRemove","filter","itemToToggle","index","findIndex","slice","concat","Fragment","map"],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"index.js","sources":["../../ComponentWithCustomHook.js","../../useTheme.js","../../ComponentWithExternalCustomHooks.js","../../ComponentWithMultipleHooksPerLine.js","../../Example.js","../../InlineRequire.js","../../ToDoList.js"],"sourcesContent":["/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport React, {useEffect, useState} from 'react';\n\nexport function Component() {\n const [count, setCount] = useState(0);\n const isDarkMode = useIsDarkMode();\n\n useEffect(() => {\n // ...\n }, []);\n\n const handleClick = () => setCount(count + 1);\n\n return (\n <>\n
Dark mode? {isDarkMode}
\n
Count: {count}
\n \n >\n );\n}\n\nfunction useIsDarkMode() {\n const [isDarkMode] = useState(false);\n\n useEffect(function useEffectCreate() {\n // Here is where we may listen to a \"theme\" event...\n }, []);\n\n return isDarkMode;\n}\n","/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {createContext, useContext, useDebugValue} from 'react';\n\nexport const ThemeContext = createContext('bright');\n\nexport default function useTheme() {\n const theme = useContext(ThemeContext);\n useDebugValue(theme);\n return theme;\n}\n","/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport React from 'react';\nimport useTheme from './useTheme';\n\nexport function Component() {\n const theme = useTheme();\n\n return
theme: {theme}
;\n}\n","/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {createContext, useContext} from 'react';\n\nconst A = createContext(1);\nconst B = createContext(2);\n\nexport function Component() {\n const a = useContext(A);\n const b = useContext(B);\n\n // prettier-ignore\n const c = useContext(A), d = useContext(B); // eslint-disable-line one-var\n\n return a + b + c + d;\n}\n","/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport React, {useState} from 'react';\n\nexport function Component() {\n const [count, setCount] = useState(0);\n\n return (\n
\n
You clicked {count} times
\n \n
\n );\n}\n","/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport function Component() {\n const [count] = require('react').useState(0);\n\n return count;\n}\n","/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {Fragment, useCallback, useState} from 'react';\n\nexport function ListItem({item, removeItem, toggleItem}) {\n const handleDelete = useCallback(() => {\n removeItem(item);\n }, [item, removeItem]);\n\n const handleToggle = useCallback(() => {\n toggleItem(item);\n }, [item, toggleItem]);\n\n return (\n