test(lint): separate multiline comments (#6476)

This commit is contained in:
Zach Pomerantz 2023-05-02 08:26:07 -07:00 committed by GitHub
parent 607d0d443e
commit 00ecb933ac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 90 additions and 118 deletions

@ -5,6 +5,12 @@ require('@uniswap/eslint-config/load')
module.exports = { module.exports = {
extends: '@uniswap/eslint-config/react', extends: '@uniswap/eslint-config/react',
overrides: [ overrides: [
{
files: ['**/*'],
rules: {
'multiline-comment-style': ['error', 'separate-lines'],
},
},
{ {
// Configuration/typings typically export objects/definitions that are used outside of the transpiled package // Configuration/typings typically export objects/definitions that are used outside of the transpiled package
// (eg not captured by the tsconfig). Because it's typical and not exceptional, this is turned off entirely. // (eg not captured by the tsconfig). Because it's typical and not exceptional, this is turned off entirely.

@ -22,12 +22,12 @@ import { PositionInfo } from './cache'
import { useFeeValues } from './hooks' import { useFeeValues } from './hooks'
import useMultiChainPositions from './useMultiChainPositions' import useMultiChainPositions from './useMultiChainPositions'
/* /**
This hook takes an array of PositionInfo objects (format used by the Uniswap Labs gql API). * Takes an array of PositionInfo objects (format used by the Uniswap Labs gql API).
The hook access PositionInfo.details (format used by the NFT position contract), * The hook access PositionInfo.details (format used by the NFT position contract),
filters the PositionDetails data for malicious content, * filters the PositionDetails data for malicious content,
and then returns the original data in its original format. * and then returns the original data in its original format.
*/ */
function useFilterPossiblyMaliciousPositionInfo(positions: PositionInfo[] | undefined): PositionInfo[] { function useFilterPossiblyMaliciousPositionInfo(positions: PositionInfo[] | undefined): PositionInfo[] {
const tokenIdsToPositionInfo: Record<string, PositionInfo> = useMemo( const tokenIdsToPositionInfo: Record<string, PositionInfo> = useMemo(
() => () =>

@ -1,4 +1,4 @@
/* /**
* Generates an SVG path for the east brush handle. * Generates an SVG path for the east brush handle.
* Apply `scale(-1, 1)` to generate west brush handle. * Apply `scale(-1, 1)` to generate west brush handle.
* *

@ -262,11 +262,9 @@ export function PriceChart({ width, height, prices: originalPrices, timePeriod }
const crosshairEdgeMax = width * 0.85 const crosshairEdgeMax = width * 0.85
const crosshairAtEdge = !!crosshair && crosshair > crosshairEdgeMax const crosshairAtEdge = !!crosshair && crosshair > crosshairEdgeMax
/* // Default curve doesn't look good for the HOUR chart.
* Default curve doesn't look good for the HOUR chart. // Higher values make the curve more rigid, lower values smooth the curve but make it less "sticky" to real data points,
* Higher values make the curve more rigid, lower values smooth the curve but make it less "sticky" to real data points, // making it unacceptable for shorter durations / smaller variances.
* making it unacceptable for shorter durations / smaller variances.
*/
const curveTension = timePeriod === TimePeriod.HOUR ? 1 : 0.9 const curveTension = timePeriod === TimePeriod.HOUR ? 1 : 0.9
const getX = useMemo(() => (p: PricePoint) => timeScale(p.timestamp), [timeScale]) const getX = useMemo(() => (p: PricePoint) => timeScale(p.timestamp), [timeScale])

@ -56,16 +56,14 @@ export default function SwapBuyFiatButton() {
const [buyFiatFlowState, setBuyFiatFlowState] = useState(BuyFiatFlowState.INACTIVE) const [buyFiatFlowState, setBuyFiatFlowState] = useState(BuyFiatFlowState.INACTIVE)
const [walletDrawerOpen, toggleWalletDrawer] = useAccountDrawer() const [walletDrawerOpen, toggleWalletDrawer] = useAccountDrawer()
/* // Depending on the current state of the buy fiat flow the user is in (buyFiatFlowState),
* Depending on the current state of the buy fiat flow the user is in (buyFiatFlowState), // the desired behavior of clicking the 'Buy' button is different.
* the desired behavior of clicking the 'Buy' button is different. // 1) Initially upon first click, need to check the availability of the feature in the user's
* 1) Initially upon first click, need to check the availability of the feature in the user's // region, and continue the flow.
* region, and continue the flow. // 2) If the feature is available in the user's region, need to connect a wallet, and continue
* 2) If the feature is available in the user's region, need to connect a wallet, and continue // the flow.
* the flow. // 3) If the feature is available and a wallet account is connected, show fiat on ramp modal.
* 3) If the feature is available and a wallet account is connected, show fiat on ramp modal. // 4) If the feature is unavailable, show feature unavailable tooltip.
* 4) If the feature is unavailable, show feature unavailable tooltip.
*/
const handleBuyCrypto = useCallback(() => { const handleBuyCrypto = useCallback(() => {
if (!fiatOnrampAvailabilityChecked) { if (!fiatOnrampAvailabilityChecked) {
setCheckFiatRegionAvailability(true) setCheckFiatRegionAvailability(true)

@ -28,10 +28,8 @@ function useTryActivation() {
return useCallback( return useCallback(
async (connection: Connection, onSuccess: () => void) => { async (connection: Connection, onSuccess: () => void) => {
/* // Skips wallet connection if the connection should override the default
* Skips wallet connection if the connection should override the default // behavior, i.e. install MetaMask or launch Coinbase app
* behavior, i.e. install MetaMask or launch Coinbase app
*/
if (connection.overrideActivate?.()) return if (connection.overrideActivate?.()) return
try { try {

@ -1,4 +1,4 @@
/* /**
* SupportedChainId must be defined inline, without using @uniswap/sdk-core, so that its members are their own types * SupportedChainId must be defined inline, without using @uniswap/sdk-core, so that its members are their own types
* {@see https://www.typescriptlang.org/docs/handbook/enums.html#union-enums-and-enum-member-types}. This allows the * {@see https://www.typescriptlang.org/docs/handbook/enums.html#union-enums-and-enum-member-types}. This allows the
* derived const arrays and their types (eg {@link L1_CHAIN_IDS}, {@link SupportedL1ChainId}) to be narrowed and used * derived const arrays and their types (eg {@link L1_CHAIN_IDS}, {@link SupportedL1ChainId}) to be narrowed and used

@ -56,8 +56,7 @@ export function getWarningCopy(warning: Warning | null, plural = false) {
export type Warning = { export type Warning = {
level: WARNING_LEVEL level: WARNING_LEVEL
message: JSX.Element message: JSX.Element
/* canProceed determines whether triangle/slash alert icon is used, and /** Determines whether triangle/slash alert icon is used, and whether this token is supported/able to be traded. */
whether this token is supported/able to be traded */
canProceed: boolean canProceed: boolean
} }

@ -5,14 +5,12 @@ import { WrappedTokenInfo } from 'state/lists/wrappedTokenInfo'
import { TokenQuery } from './__generated__/types-and-hooks' import { TokenQuery } from './__generated__/types-and-hooks'
import { CHAIN_NAME_TO_CHAIN_ID } from './util' import { CHAIN_NAME_TO_CHAIN_ID } from './util'
/* // The difference between Token and TokenProject:
The difference between Token and TokenProject: // Token: an on-chain entity referring to a contract (e.g. uni token on ethereum 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984)
Token: an on-chain entity referring to a contract (e.g. uni token on ethereum 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984) // TokenProject: an off-chain, aggregated entity that consists of a token and its bridged tokens (e.g. uni token on all chains)
TokenProject: an off-chain, aggregated entity that consists of a token and its bridged tokens (e.g. uni token on all chains) // TokenMarket and TokenProjectMarket then are market data entities for the above.
TokenMarket and TokenProjectMarket then are market data entities for the above. // TokenMarket is per-chain market data for contracts pulled from the graph.
TokenMarket is per-chain market data for contracts pulled from the graph. // TokenProjectMarket is aggregated market data (aggregated over multiple dexes and centralized exchanges) that we get from coingecko.
TokenProjectMarket is aggregated market data (aggregated over multiple dexes and centralized exchanges) that we get from coingecko.
*/
gql` gql`
query Token($chain: Chain!, $address: String = null) { query Token($chain: Chain!, $address: String = null) {
token(chain: $chain, address: $address) { token(chain: $chain, address: $address) {

@ -28,10 +28,9 @@ export default function useENSName(address?: string): { ENSName: string | null;
const nameCallRes = useSingleCallResult(resolverContract, 'name', ensNodeArgument) const nameCallRes = useSingleCallResult(resolverContract, 'name', ensNodeArgument)
const name = nameCallRes.result?.[0] const name = nameCallRes.result?.[0]
/* ENS does not enforce that an address owns a .eth domain before setting it as a reverse proxy // ENS does not enforce that an address owns a .eth domain before setting it as a reverse proxy
and recommends that you perform a match on the forward resolution // and recommends that you perform a match on the forward resolution
see: https://docs.ens.domains/dapp-developer-guide/resolving-names#reverse-resolution // see: https://docs.ens.domains/dapp-developer-guide/resolving-names#reverse-resolution
*/
const fwdAddr = useENSAddress(name) const fwdAddr = useENSAddress(name)
const checkedName = address === fwdAddr?.address ? name : null const checkedName = address === fwdAddr?.address ? name : null

@ -11,7 +11,7 @@ function getUniqueAddressesFromPositions(positions: PositionDetails[]): string[]
new Set(positions.reduce<string[]>((acc, position) => acc.concat(position.token0, position.token1), [])) new Set(positions.reduce<string[]>((acc, position) => acc.concat(position.token0, position.token1), []))
) )
} }
/* /**
* This function is an attempt to filter out an observed phishing attack from LP list UIs. * This function is an attempt to filter out an observed phishing attack from LP list UIs.
* Attackers would airdrop valueless LP positions with urls in the symbol to render phishing sites into users' LP position list view. * Attackers would airdrop valueless LP positions with urls in the symbol to render phishing sites into users' LP position list view.
* *

@ -3,9 +3,7 @@ import { useWeb3React } from '@web3-react/core'
import { useMemo } from 'react' import { useMemo } from 'react'
import { useCombinedActiveList } from 'state/lists/hooks' import { useCombinedActiveList } from 'state/lists/hooks'
/** /** Returns a WrappedTokenInfo from the active token lists when possible, or the passed token otherwise. */
* Returns a WrappedTokenInfo from the active token lists when possible,
* or the passed token otherwise. */
export function useTokenInfoFromActiveList(currency: Currency) { export function useTokenInfoFromActiveList(currency: Currency) {
const { chainId } = useWeb3React() const { chainId } = useWeb3React()
const activeList = useCombinedActiveList() const activeList = useCombinedActiveList()

@ -44,11 +44,9 @@ const urlParamsUtils = {
clonedQuery[key] = [] clonedQuery[key] = []
} }
/* // query-string package treats arrays with one value as a string.
query-string package treats arrays with one value as a string. // Here we're making sure that we have an array, not a string. Example:
Here we're making sure that we have an array, not a string. Example: // const foo = 'hey' // => ['hey']
const foo = 'hey' // => ['hey']
*/
if (clonedQuery[key] && typeof clonedQuery[key] === 'string') { if (clonedQuery[key] && typeof clonedQuery[key] === 'string') {
clonedQuery[key] = [clonedQuery[key]] clonedQuery[key] = [clonedQuery[key]]
} }
@ -66,23 +64,20 @@ const urlParamsUtils = {
clonedQuery['buyNow'] = !(clonedQuery['all'] === undefined ? !initialBuyNow : clonedQuery['all']) clonedQuery['buyNow'] = !(clonedQuery['all'] === undefined ? !initialBuyNow : clonedQuery['all'])
clonedQuery['search'] = clonedQuery['search'] === undefined ? initialSearchText : String(clonedQuery['search']) clonedQuery['search'] = clonedQuery['search'] === undefined ? initialSearchText : String(clonedQuery['search'])
/* // Handling an edge case caused by query-string's bad array parsing, when user
Handling an edge case caused by query-string's bad array parsing, when user // only selects one trait and reloads the page.
only selects one trait and reloads the page. // Here's the general data-structure for our traits in URL:
Here's the general data-structure for our traits in URL: // `traits=("trait_type","trait_value"),("trait_type","trait_value")`
`traits=("trait_type","trait_value"),("trait_type","trait_value")` //
// Expected behavior: When user selects one trait, there should be an array
Expected behavior: When user selects one trait, there should be an array // containing one element.
containing one element. //
// Actual behavior: It creates an array with two elements, first element being
Actual behavior: It creates an array with two elements, first element being // trait_type & the other trait_value. This causes confusion since we don't know
trait_type & the other trait_value. This causes confusion since we don't know // whether user has selected two traits (cause we have two elements in our array)
whether user has selected two traits (cause we have two elements in our array) // or it's only one.
or it's only one. //
// Using this block of code, we'll identify if that's the case.
Using this block of code, we'll identify if that's the case.
*/
if (clonedQuery['traits'].length === 2) { if (clonedQuery['traits'].length === 2) {
const [trait_type, trait_value] = clonedQuery['traits'] as [string, string] const [trait_type, trait_value] = clonedQuery['traits'] as [string, string]
const fullTrait = `${trait_type}${trait_value}` const fullTrait = `${trait_type}${trait_value}`
@ -104,11 +99,9 @@ const urlParamsUtils = {
collectionStats.traits && collectionStats.traits &&
collectionStats.traits[trait_type].find((trait) => trait.trait_value === trait_value) collectionStats.traits[trait_type].find((trait) => trait.trait_value === trait_value)
/* // For most cases, `traitInStats` is assigned. In case the trait
For most cases, `traitInStats` is assigned. In case the trait // does not exist in our store, e.g "Number of traits", we have to
does not exist in our store, e.g "Number of traits", we have to // manually create an object for it.
manually create an object for it.
*/
const trait = traitInStats ?? { trait_type, trait_value, trait_count: 0 } const trait = traitInStats ?? { trait_type, trait_value, trait_count: 0 }
return trait as Trait return trait as Trait

@ -21,8 +21,8 @@ export default function TokenDetailsPage() {
const isNative = tokenAddress === NATIVE_CHAIN_ID const isNative = tokenAddress === NATIVE_CHAIN_ID
const [timePeriod, setTimePeriod] = useAtom(pageTimePeriodAtom) const [timePeriod, setTimePeriod] = useAtom(pageTimePeriodAtom)
const [detailedTokenAddress, duration] = useMemo( const [detailedTokenAddress, duration] = useMemo(
/* tokenAddress will always be defined in the path for for this page to render, but useParams will always // tokenAddress will always be defined in the path for for this page to render, but useParams will always
return optional arguments; nullish coalescing operator is present here to appease typechecker */ // return optional arguments; nullish coalescing operator is present here to appease typechecker
() => [isNative ? getNativeTokenDBAddress(chain) : tokenAddress ?? '', toHistoryDuration(timePeriod)], () => [isNative ? getNativeTokenDBAddress(chain) : tokenAddress ?? '', toHistoryDuration(timePeriod)],
[chain, isNative, timePeriod, tokenAddress] [chain, isNative, timePeriod, tokenAddress]
) )

@ -1,14 +1,12 @@
import { atomWithStorage, createJSONStorage } from 'jotai/utils' import { atomWithStorage, createJSONStorage } from 'jotai/utils'
/* // Note:
Note: // We should consider a generic sessionStorage abstraction if this pattern becomes common. (i.e., Future promo dismissals like the tax service discounts or Fiat Onramp launch notification may use this.)
We should consider a generic sessionStorage abstraction if this pattern becomes common. (i.e., Future promo dismissals like the tax service discounts or Fiat Onramp launch notification may use this.) // This would be something similar to the current feature flag implementation, but utilizing session instead
This would be something similar to the current feature flag implementation, but utilizing session instead //
// Motivation:
Motivation: // some dapp browsers need to be able to disable the NFT portion of the app in order to pass Apple's app store review
some dapp browsers need to be able to disable the NFT portion of the app in order to pass Apple's app store review // this atom persists the inclusion of the `disableNFTs=boolean` query parameter via the webview's session storage
this atom persists the inclusion of the `disableNFTs=boolean` query parameter via the webview's session storage
*/
const storage = createJSONStorage(() => sessionStorage) const storage = createJSONStorage(() => sessionStorage)
export const shouldDisableNFTRoutesAtom = atomWithStorage('shouldDisableNFTRoutes', false, storage) export const shouldDisableNFTRoutesAtom = atomWithStorage('shouldDisableNFTRoutes', false, storage)

@ -3,8 +3,8 @@ import { shallowEqual } from 'react-redux'
import { Wallet } from './types' import { Wallet } from './types'
/* Used to track wallets that have been connected by the user in current session, and remove them when deliberately disconnected. // Used to track wallets that have been connected by the user in current session, and remove them when deliberately disconnected.
Used to compute is_reconnect event property for analytics */ // Used to compute is_reconnect event property for analytics
interface WalletState { interface WalletState {
connectedWallets: Wallet[] connectedWallets: Wallet[]
} }

@ -1,9 +1,8 @@
import { ClientOptions, ErrorEvent, EventHint } from '@sentry/types' import { ClientOptions, ErrorEvent, EventHint } from '@sentry/types'
import { didUserReject } from 'utils/swapErrorToUserReadableMessage' import { didUserReject } from 'utils/swapErrorToUserReadableMessage'
/* `responseStatus` is only currently supported on certain browsers. // `responseStatus` is only currently supported on certain browsers.
* see: https://caniuse.com/mdn-api_performanceresourcetiming_responsestatus // see: https://caniuse.com/mdn-api_performanceresourcetiming_responsestatus
*/
declare global { declare global {
interface PerformanceEntry { interface PerformanceEntry {
responseStatus?: number responseStatus?: number
@ -16,12 +15,10 @@ function isEthersRequestError(error: Error): error is Error & { requestBody: str
} }
export function beforeSend(event: ErrorEvent, hint: EventHint) { export function beforeSend(event: ErrorEvent, hint: EventHint) {
/* // Since the interface currently uses HashRouter, URLs will have a # before the path.
* Since the interface currently uses HashRouter, URLs will have a # before the path. // This leads to issues when we send the URL into Sentry, as the path gets parsed as a "fragment".
* This leads to issues when we send the URL into Sentry, as the path gets parsed as a "fragment". // Instead, this logic removes the # part of the URL.
* Instead, this logic removes the # part of the URL. // See https://romain-clement.net/articles/sentry-url-fragments/#url-fragments
* See https://romain-clement.net/articles/sentry-url-fragments/#url-fragments
**/
if (event.request?.url) { if (event.request?.url) {
event.request.url = event.request.url.replace('/#', '') event.request.url = event.request.url.replace('/#', '')
} }
@ -34,11 +31,9 @@ function shouldFilterChunkError(asset?: string) {
const resource = entries?.find(({ name }) => name === asset) const resource = entries?.find(({ name }) => name === asset)
const status = resource?.responseStatus const status = resource?.responseStatus
/* // If the status if 499, then we ignore.
* If the status if 499, then we ignore. // If there's no status (meaning the browser doesn't support `responseStatus`) then we also ignore.
* If there's no status (meaning the browser doesn't support `responseStatus`) then we also ignore. // These errors are likely also 499 errors, and we can catch any spikes in non-499 chunk errors via other browsers.
* These errors are likely also 499 errors, and we can catch any spikes in non-499 chunk errors via other browsers.
*/
return !status || status === 499 return !status || status === 499
} }
@ -62,11 +57,9 @@ export const filterKnownErrors: Required<ClientOptions>['beforeSend'] = (event:
// If the error is based on a user rejecting, it should not be considered an exception. // If the error is based on a user rejecting, it should not be considered an exception.
if (didUserReject(error)) return null if (didUserReject(error)) return null
/* // This ignores 499 errors, which are caused by Cloudflare when a request is cancelled.
* This ignores 499 errors, which are caused by Cloudflare when a request is cancelled. // CF claims that some number of these is expected, and that they should be ignored.
* CF claims that some number of these is expected, and that they should be ignored. // See https://groups.google.com/a/uniswap.org/g/cloudflare-eng/c/t3xvAiJFujY.
* See https://groups.google.com/a/uniswap.org/g/cloudflare-eng/c/t3xvAiJFujY.
*/
if (error.message.match(/Loading chunk \d+ failed\. \(([a-zA-Z]+): .+\.chunk\.js\)/)) { if (error.message.match(/Loading chunk \d+ failed\. \(([a-zA-Z]+): .+\.chunk\.js\)/)) {
const asset = error.message.match(/https?:\/\/.+?\.chunk\.js/)?.[0] const asset = error.message.match(/https?:\/\/.+?\.chunk\.js/)?.[0]
if (shouldFilterChunkError(asset)) return null if (shouldFilterChunkError(asset)) return null
@ -78,24 +71,18 @@ export const filterKnownErrors: Required<ClientOptions>['beforeSend'] = (event:
if (shouldFilterChunkError(asset)) return null if (shouldFilterChunkError(asset)) return null
} }
/* // This is caused by HTML being returned for a chunk from Cloudflare.
* This is caused by HTML being returned for a chunk from Cloudflare. // Usually, it's the result of a 499 exception right before it, which should be handled.
* Usually, it's the result of a 499 exception right before it, which should be handled. // Therefore, this can be ignored.
* Therefore, this can be ignored.
*/
if (error.message.match(/Unexpected token '<'/)) return null if (error.message.match(/Unexpected token '<'/)) return null
/* // Errors coming from OneKey (a desktop wallet) can be ignored for now.
* Errors coming from OneKey (a desktop wallet) can be ignored for now. // These errors are either application-specific, or they will be thrown separately outside of OneKey.
* These errors are either application-specific, or they will be thrown separately outside of OneKey.
*/
if (error.stack?.match(/OneKey/i)) return null if (error.stack?.match(/OneKey/i)) return null
/* // Content security policy 'unsafe-eval' errors can be filtered out because there are expected failures.
* Content security policy 'unsafe-eval' errors can be filtered out because there are expected failures. // For example, if a user runs an eval statement in console this error would still get thrown.
* For example, if a user runs an eval statement in console this error would still get thrown. // TODO(INFRA-176): We should extend this to filter out any type of CSP error.
* TODO(INFRA-176): We should extend this to filter out any type of CSP error.
*/
if (error.message.match(/'unsafe-eval'.*content security policy/i)) { if (error.message.match(/'unsafe-eval'.*content security policy/i)) {
return null return null
} }