mirror of
https://github.com/sourcegraph/sourcegraph.git
synced 2026-02-06 20:31:48 +00:00
[hackaton] Go code checkers as template insights, linking to suggested batch changes (#33289)
Co-authored-by: Justin Boyson <justin.boyson@sourcegraph.com> Co-authored-by: Erik Seliger <erikseliger@me.com>
This commit is contained in:
parent
f5eb9b40fd
commit
762a0a2cdd
@ -0,0 +1,3 @@
|
||||
.icon {
|
||||
min-width: 4rem;
|
||||
}
|
||||
@ -0,0 +1,104 @@
|
||||
import React from 'react'
|
||||
|
||||
import classNames from 'classnames'
|
||||
|
||||
import styles from './CodeInsightsBatchesIcon.module.scss'
|
||||
|
||||
export const CodeInsightsBatchesIcon: React.FunctionComponent<{ className?: string }> = ({ className }) => (
|
||||
<svg
|
||||
width="40"
|
||||
height="40"
|
||||
viewBox="0 0 40 40"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className={classNames(styles.icon, className)}
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M19.1005 17.9954C19.9724 17.9954 20.6792 17.2678 20.6792 16.3703C20.6792 15.4728 19.9724 14.7453 19.1005 14.7453C18.2287 14.7453 17.5219 15.4728 17.5219 16.3703C17.5219 17.2678 18.2287 17.9954 19.1005 17.9954ZM19.1005 20.433C21.2802 20.433 23.0471 18.6141 23.0471 16.3703C23.0471 14.1266 21.2802 12.3077 19.1005 12.3077C16.9209 12.3077 15.154 14.1266 15.154 16.3703C15.154 18.6141 16.9209 20.433 19.1005 20.433ZM39.0185 13.8785L32.7039 13.8785L32.7039 20.3788L39.0185 20.3788L39.0185 13.8785ZM32.7039 23.3048L39.0185 23.3048L39.0185 29.8051L32.7039 29.8051L32.7039 23.3048ZM39.0185 32.7306L32.7039 32.7306L32.7039 39.2309L39.0185 39.2309L39.0185 32.7306ZM24.1554 17.1826C24.1554 16.5095 24.6855 15.9638 25.3394 15.9638L30.0753 15.9638C30.7292 15.9638 31.2593 16.5095 31.2593 17.1826C31.2593 17.8557 30.7292 18.4014 30.0753 18.4014L25.3394 18.4014C24.6855 18.4014 24.1554 17.8557 24.1554 17.1826ZM30.3763 34.7096C31.0235 34.6126 31.6243 35.0723 31.7185 35.7385C31.8126 36.4031 31.3646 37.0232 30.7175 37.1217L30.716 37.1218L30.7129 37.1218L30.7069 37.1235L30.6887 37.1255L30.6265 37.1331C30.575 37.1405 30.5021 37.1483 30.4111 37.1581C30.2291 37.1761 29.9726 37.1973 29.6566 37.2104C29.0277 37.2366 28.155 37.2304 27.1763 37.1014C25.2509 36.8457 22.7406 36.0862 20.9985 33.9376C19.3032 31.8475 18.6822 28.986 18.4521 26.8015C18.3336 25.6851 18.3148 24.6917 18.323 23.9763C18.3263 23.6178 18.3386 23.3265 18.3496 23.1228C18.3532 23.0559 18.3571 22.9985 18.3602 22.951L18.3602 22.951L18.3602 22.951L18.3645 22.8846L18.3692 22.8172L18.3703 22.8095C18.3721 22.3791 18.5957 21.9629 18.9889 21.7428C19.5617 21.4223 20.278 21.6387 20.5918 22.2261L20.5959 22.2334C20.6012 22.2429 20.6114 22.2608 20.6265 22.2864C20.6569 22.3375 20.7069 22.4186 20.7773 22.5229C20.9184 22.732 21.139 23.0311 21.4438 23.3661C22.0551 24.0379 22.9877 24.8362 24.2801 25.361C25.595 25.8949 27.0508 26.0689 28.2146 26.0994C28.7894 26.1145 29.2766 26.0942 29.617 26.0706C29.7868 26.0587 29.9191 26.0461 30.0065 26.0368C30.0501 26.0322 30.0824 26.0283 30.1025 26.0259L30.1248 26.0231L30.1264 26.0228C30.7738 25.9342 31.3689 26.4021 31.4559 27.0687C31.5429 27.7358 31.0876 28.3494 30.4395 28.439C30.4398 28.439 30.4401 28.4389 30.2824 27.231L30.4395 28.439L30.4374 28.4393L30.4334 28.4399L30.4217 28.4414L30.3835 28.4462C30.3515 28.4502 30.3068 28.4554 30.2503 28.4614C30.1374 28.4735 29.9769 28.4887 29.7767 28.5026C29.3771 28.5304 28.8152 28.5536 28.1543 28.5362C26.8466 28.502 25.0841 28.3078 23.4112 27.6285C22.3385 27.1929 21.4589 26.6156 20.758 26.0311C20.7712 26.1969 20.7867 26.3665 20.8048 26.5393C21.0198 28.5801 21.5754 30.8483 22.8153 32.3755C24.0068 33.8459 25.8165 34.4656 27.4781 34.6847C28.2937 34.7922 29.0296 34.7982 29.5613 34.7757C29.8271 34.7653 30.038 34.7466 30.1791 34.7326C30.2329 34.7279 30.2763 34.7226 30.3087 34.7186L30.3369 34.7151L30.3763 34.7096Z"
|
||||
fill="url(#paint0_linear_49_2895)"
|
||||
/>
|
||||
<rect x="1.22595" y="4.08643" width="2.45192" height="8.99039" fill="url(#paint1_linear_49_2895)" />
|
||||
<rect x="5.3125" width="2.45192" height="13.0769" fill="url(#paint2_linear_49_2895)" />
|
||||
<rect x="9.39905" y="8.17285" width="2.45192" height="4.90385" fill="url(#paint3_linear_49_2895)" />
|
||||
<path
|
||||
d="M31.7341 11.0773C31.9973 11.1606 32.2783 11.0148 32.3617 10.7515L33.7202 6.46151C33.8036 6.19825 33.6578 5.91725 33.3945 5.83389C33.1312 5.75052 32.8502 5.89636 32.7669 6.15961L31.5593 9.97298L27.7459 8.76541C27.4827 8.68205 27.2017 8.82788 27.1183 9.09114C27.035 9.3544 27.1808 9.63539 27.444 9.71875L31.7341 11.0773ZM14.0966 4.6638C16.8438 3.07469 19.2778 2.68254 21.3805 2.95685C23.4907 3.23214 25.3098 4.18448 26.8074 5.35216C28.3058 6.52036 29.467 7.89232 30.2554 8.9775C30.6488 9.51896 30.9473 9.98611 31.1466 10.3164C31.2462 10.4815 31.3209 10.6122 31.3702 10.7006C31.3949 10.7448 31.4132 10.7784 31.425 10.8005C31.431 10.8115 31.4353 10.8196 31.438 10.8247C31.4393 10.8273 31.4403 10.8291 31.4408 10.8301C31.4411 10.8307 31.4413 10.831 31.4413 10.8311C31.4414 10.8312 31.4413 10.8311 31.4414 10.8312C31.4413 10.8311 31.4412 10.8309 31.885 10.6006C32.3288 10.3703 32.3287 10.37 32.3285 10.3697C32.3285 10.3696 32.3283 10.3692 32.3281 10.3689C32.3278 10.3683 32.3273 10.3674 32.3268 10.3664C32.3257 10.3643 32.3242 10.3614 32.3223 10.3578C32.3184 10.3505 32.313 10.3402 32.3059 10.327C32.2916 10.3005 32.2709 10.2624 32.2436 10.2135C32.1891 10.1158 32.1087 9.97525 32.0028 9.79973C31.791 9.44884 31.4769 8.9575 31.0644 8.38973C30.2411 7.25647 29.0173 5.80705 27.4223 4.56353C25.8267 3.31949 23.8442 2.26978 21.5099 1.96525C19.168 1.65974 16.5143 2.11003 13.5958 3.79819L14.0966 4.6638Z"
|
||||
fill="url(#paint4_linear_49_2895)"
|
||||
/>
|
||||
<path
|
||||
opacity="0.2"
|
||||
d="M15.8934 30.6996C16.0887 30.5043 16.0887 30.1877 15.8934 29.9924L12.7114 26.8105C12.5162 26.6152 12.1996 26.6152 12.0043 26.8105C11.8091 27.0057 11.8091 27.3223 12.0043 27.5176L14.8328 30.346L12.0043 33.1744C11.8091 33.3697 11.8091 33.6863 12.0043 33.8815C12.1996 34.0768 12.5162 34.0768 12.7114 33.8815L15.8934 30.6996ZM4.3252 16.1533C4.3252 23.3967 7.07156 27.1112 9.90644 28.9888C11.3091 29.9178 12.7095 30.381 13.7579 30.6125C14.2828 30.7284 14.7218 30.7867 15.0324 30.8161C15.1877 30.8308 15.3112 30.8382 15.3975 30.8421C15.4406 30.844 15.4745 30.8449 15.4984 30.8455C15.5104 30.8457 15.5199 30.8458 15.5268 30.8459C15.5303 30.846 15.5331 30.846 15.5353 30.846C15.5364 30.846 15.5373 30.846 15.5381 30.846C15.5385 30.846 15.5389 30.846 15.5391 30.846C15.5395 30.846 15.5399 30.846 15.5399 30.346C15.5399 29.846 15.5401 29.846 15.5404 29.846C15.5404 29.846 15.5406 29.846 15.5407 29.846C15.5408 29.846 15.5407 29.846 15.5405 29.846C15.5401 29.846 15.539 29.846 15.5373 29.846C15.534 29.8459 15.5281 29.8459 15.5198 29.8457C15.5032 29.8453 15.4769 29.8446 15.4416 29.843C15.3709 29.8399 15.2642 29.8335 15.1266 29.8205C14.8511 29.7944 14.4531 29.7419 13.9735 29.636C13.0129 29.4239 11.7346 29.0001 10.4586 28.1551C7.93616 26.4844 5.3252 23.1026 5.3252 16.1533H4.3252Z"
|
||||
fill="url(#paint5_linear_49_2895)"
|
||||
/>
|
||||
<defs>
|
||||
<linearGradient
|
||||
id="paint0_linear_49_2895"
|
||||
x1="17"
|
||||
y1="14.6152"
|
||||
x2="36"
|
||||
y2="38.6152"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stopColor="#1C7CD6" />
|
||||
<stop offset="0.73817" stopColor="#2490FF" />
|
||||
<stop offset="1" stopColor="#0C7BF0" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="paint1_linear_49_2895"
|
||||
x1="2.45191"
|
||||
y1="4.08643"
|
||||
x2="2.45191"
|
||||
y2="13.0768"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stopColor="#A6B6D9" />
|
||||
<stop offset="1" stopColor="#D1D9E9" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="paint2_linear_49_2895"
|
||||
x1="6.53846"
|
||||
y1="0"
|
||||
x2="6.53846"
|
||||
y2="13.0769"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stopColor="#A6B6D9" />
|
||||
<stop offset="1" stopColor="#D1D9E9" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="paint3_linear_49_2895"
|
||||
x1="10.625"
|
||||
y1="8.17285"
|
||||
x2="10.625"
|
||||
y2="13.0767"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stopColor="#A6B6D9" />
|
||||
<stop offset="1" stopColor="#D1D9E9" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="paint4_linear_49_2895"
|
||||
x1="30.7272"
|
||||
y1="7.49289"
|
||||
x2="16.9919"
|
||||
y2="3.70685"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop offset="0.578957" stopColor="#A6B6D9" />
|
||||
<stop offset="1" stopColor="white" stopOpacity="0" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="paint5_linear_49_2895"
|
||||
x1="17.3263"
|
||||
y1="25.6272"
|
||||
x2="6.50285"
|
||||
y2="16.362"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop offset="0.578957" stopColor="#A6B6D9" />
|
||||
<stop offset="1" stopColor="white" stopOpacity="0" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
)
|
||||
@ -66,3 +66,7 @@
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.code-insights-banner {
|
||||
box-shadow: var(--box-shadow);
|
||||
}
|
||||
|
||||
@ -6,10 +6,11 @@ import { noop } from 'lodash'
|
||||
import AlertCircleIcon from 'mdi-react/AlertCircleIcon'
|
||||
import InfoCircleOutlineIcon from 'mdi-react/InfoCircleOutlineIcon'
|
||||
import LockIcon from 'mdi-react/LockIcon'
|
||||
import { useHistory } from 'react-router'
|
||||
import { useHistory, useLocation } from 'react-router'
|
||||
|
||||
import { ErrorAlert } from '@sourcegraph/branded/src/components/alerts'
|
||||
import { Form } from '@sourcegraph/branded/src/components/Form'
|
||||
import { isErrorLike } from '@sourcegraph/common'
|
||||
import { useMutation, useQuery } from '@sourcegraph/http-client'
|
||||
import { Settings } from '@sourcegraph/shared/src/schema/settings.schema'
|
||||
import {
|
||||
@ -34,6 +35,9 @@ import {
|
||||
TabPanel,
|
||||
TabPanels,
|
||||
RadioButton,
|
||||
Card,
|
||||
CardBody,
|
||||
H4,
|
||||
} from '@sourcegraph/wildcard'
|
||||
|
||||
import { BatchChangesIcon } from '../../../batches/icons'
|
||||
@ -48,14 +52,18 @@ import {
|
||||
CreateEmptyBatchChangeResult,
|
||||
Scalars,
|
||||
BatchSpecWorkspaceResolutionState,
|
||||
CreateBatchSpecFromRawVariables,
|
||||
CreateBatchSpecFromRawResult,
|
||||
} from '../../../graphql-operations'
|
||||
import { BatchSpecDownloadLink } from '../BatchSpec'
|
||||
|
||||
import { GET_BATCH_CHANGE_TO_EDIT, CREATE_EMPTY_BATCH_CHANGE } from './backend'
|
||||
import { GET_BATCH_CHANGE_TO_EDIT, CREATE_EMPTY_BATCH_CHANGE, CREATE_BATCH_SPEC_FROM_RAW } from './backend'
|
||||
import { CodeInsightsBatchesIcon } from './CodeInsightsBatchesIcon'
|
||||
import { DownloadSpecModal } from './DownloadSpecModal'
|
||||
import { EditorFeedbackPanel } from './editor/EditorFeedbackPanel'
|
||||
import { MonacoBatchSpecEditor } from './editor/MonacoBatchSpecEditor'
|
||||
import { ExecutionOptions, ExecutionOptionsDropdown } from './ExecutionOptions'
|
||||
import { getTemplateRenderer } from './go-checker-templates'
|
||||
import { LibraryPane } from './library/LibraryPane'
|
||||
import { NamespaceSelector } from './NamespaceSelector'
|
||||
import { useBatchSpecCode } from './useBatchSpecCode'
|
||||
@ -160,9 +168,38 @@ interface CreatePageProps extends SettingsCascadeProps<Settings> {
|
||||
const CreatePage: React.FunctionComponent<CreatePageProps> = props => {
|
||||
const isNewBatchChange = props.batchChangeName === undefined && !props.isReadOnly
|
||||
|
||||
const location = useLocation()
|
||||
const parameters = new URLSearchParams(location.search)
|
||||
const templateRenderer = getTemplateRenderer(parameters.get('kind'))
|
||||
const codeInsightTitle = parameters.get('title') ?? undefined
|
||||
|
||||
const enableInsightsTemplates =
|
||||
(codeInsightTitle &&
|
||||
templateRenderer &&
|
||||
props.settingsCascade.final !== null &&
|
||||
!isErrorLike(props.settingsCascade.final) &&
|
||||
props.settingsCascade.final.experimentalFeatures?.goCodeCheckerTemplates) ??
|
||||
false
|
||||
|
||||
return (
|
||||
<div className="w-100 p-4">
|
||||
<PageTitle title="Create new batch change" />
|
||||
{enableInsightsTemplates && (
|
||||
<Card className={classNames('mb-5', styles.codeInsightsBanner)}>
|
||||
<CardBody>
|
||||
<div className="d-flex justify-content-between align-items-center">
|
||||
<CodeInsightsBatchesIcon className="mr-4" />
|
||||
<div className="flex-grow-1">
|
||||
<H4>You are creating a batch change from a code insight</H4>
|
||||
<p className="mb-0">
|
||||
Let Sourcegraph help you with <strong>{codeInsightTitle}</strong> by preparing a
|
||||
relevant <strong>batch change</strong>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</CardBody>
|
||||
</Card>
|
||||
)}
|
||||
<PageHeader
|
||||
path={[{ icon: BatchChangesIcon, to: '.' }, { text: 'Create batch change' }]}
|
||||
className="flex-1 pb-2"
|
||||
@ -184,7 +221,11 @@ const CreatePage: React.FunctionComponent<CreatePageProps> = props => {
|
||||
</TabList>
|
||||
<TabPanels>
|
||||
<TabPanel>
|
||||
<BatchConfigurationPage {...props} />
|
||||
<BatchConfigurationPage
|
||||
{...props}
|
||||
renderTemplate={templateRenderer}
|
||||
insightName={codeInsightTitle}
|
||||
/>
|
||||
</TabPanel>
|
||||
|
||||
<TabPanel>
|
||||
@ -214,6 +255,14 @@ interface BatchConfigurationPageProps extends SettingsCascadeProps<Settings> {
|
||||
isReadOnly?: boolean
|
||||
/** Batch change when in read-only mode */
|
||||
batchChangeName?: string
|
||||
|
||||
/**
|
||||
* When set, apply a template to the batch spec before redirecting to the edit page.
|
||||
*/
|
||||
renderTemplate?: (name: string) => string
|
||||
|
||||
/** The name of the insight this was created from, if any. */
|
||||
insightName?: string
|
||||
}
|
||||
|
||||
const BatchConfigurationPage: React.FunctionComponent<BatchConfigurationPageProps> = ({
|
||||
@ -221,11 +270,20 @@ const BatchConfigurationPage: React.FunctionComponent<BatchConfigurationPageProp
|
||||
settingsCascade,
|
||||
isReadOnly,
|
||||
batchChangeName,
|
||||
renderTemplate,
|
||||
insightName,
|
||||
}) => {
|
||||
const [createEmptyBatchChange, { loading, error }] = useMutation<
|
||||
const [createEmptyBatchChange, { loading: batchChangeLoading, error: batchChangeError }] = useMutation<
|
||||
CreateEmptyBatchChangeResult,
|
||||
CreateEmptyBatchChangeVariables
|
||||
>(CREATE_EMPTY_BATCH_CHANGE)
|
||||
const [createBatchSpecFromRaw, { loading: batchSpecLoading, error: batchSpecError }] = useMutation<
|
||||
CreateBatchSpecFromRawResult,
|
||||
CreateBatchSpecFromRawVariables
|
||||
>(CREATE_BATCH_SPEC_FROM_RAW)
|
||||
|
||||
const loading = batchChangeLoading || batchSpecLoading
|
||||
const error = batchChangeError || batchSpecError
|
||||
|
||||
const { namespaces, defaultSelectedNamespace } = useNamespaces(settingsCascade, namespaceID)
|
||||
|
||||
@ -245,10 +303,35 @@ const BatchConfigurationPage: React.FunctionComponent<BatchConfigurationPageProp
|
||||
const history = useHistory()
|
||||
const handleCancel = (): void => history.goBack()
|
||||
const handleCreate = (): void => {
|
||||
const redirectSearchParameters = new URLSearchParams()
|
||||
if (insightName) {
|
||||
redirectSearchParameters.set('title', insightName)
|
||||
}
|
||||
let serializedRedirectSearchParameters = redirectSearchParameters.toString()
|
||||
if (serializedRedirectSearchParameters.length > 0) {
|
||||
serializedRedirectSearchParameters = '?' + serializedRedirectSearchParameters
|
||||
}
|
||||
createEmptyBatchChange({
|
||||
variables: { namespace: selectedNamespace.id, name: nameInput },
|
||||
})
|
||||
.then(({ data }) => (data ? history.push(`${data.createEmptyBatchChange.url}/edit`) : noop()))
|
||||
.then(args => {
|
||||
if (!renderTemplate) {
|
||||
return Promise.resolve(args)
|
||||
}
|
||||
|
||||
const template = renderTemplate(nameInput)
|
||||
|
||||
return args.data?.createEmptyBatchChange.id && template
|
||||
? createBatchSpecFromRaw({
|
||||
variables: { namespace: selectedNamespace.id, spec: template, noCache: false },
|
||||
}).then(() => Promise.resolve(args))
|
||||
: Promise.resolve(args)
|
||||
})
|
||||
.then(({ data }) =>
|
||||
data
|
||||
? history.push(`${data.createEmptyBatchChange.url}/edit${serializedRedirectSearchParameters}`)
|
||||
: noop()
|
||||
)
|
||||
// We destructure and surface the error from `useMutation` instead.
|
||||
.catch(noop)
|
||||
}
|
||||
@ -339,6 +422,10 @@ interface EditPageProps extends ThemeProps {
|
||||
}
|
||||
|
||||
const EditPage: React.FunctionComponent<EditPageProps> = ({ batchChange, refetchBatchChange, isLightTheme }) => {
|
||||
const location = useLocation()
|
||||
const parameters = new URLSearchParams(location.search)
|
||||
const codeInsightTitle = parameters.get('title')
|
||||
|
||||
// Get the latest batch spec for the batch change.
|
||||
const { batchSpec, isApplied: isLatestBatchSpecApplied, initialCode: initialBatchSpecCode } = useInitialBatchSpec(
|
||||
batchChange
|
||||
@ -490,6 +577,22 @@ const EditPage: React.FunctionComponent<EditPageProps> = ({ batchChange, refetch
|
||||
<LibraryPane name={batchChange.name} onReplaceItem={clearErrorsAndHandleCodeChange} />
|
||||
<div className={styles.editorContainer}>
|
||||
<h4 className={styles.header}>Batch spec</h4>
|
||||
{codeInsightTitle && (
|
||||
<Card className={classNames('mb-3', styles.codeInsightsBanner)}>
|
||||
<CardBody>
|
||||
<div className="d-flex justify-content-between align-items-center">
|
||||
<CodeInsightsBatchesIcon className="mr-4" />
|
||||
<div className="flex-grow-1">
|
||||
<H4>Start from template for the {codeInsightTitle}</H4>
|
||||
<p className="mb-0">
|
||||
Sourcegraph pre-selected a Batch Specification for the batch change started
|
||||
from {codeInsightTitle}.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</CardBody>
|
||||
</Card>
|
||||
)}
|
||||
<MonacoBatchSpecEditor
|
||||
batchChangeName={batchChange.name}
|
||||
className={styles.editor}
|
||||
|
||||
692
client/web/src/enterprise/batches/create/go-checker-templates.ts
Normal file
692
client/web/src/enterprise/batches/create/go-checker-templates.ts
Normal file
@ -0,0 +1,692 @@
|
||||
import { quoteYAMLString } from './yaml-util'
|
||||
|
||||
export function goCheckerSA6005Template(name: string): string {
|
||||
return `name: ${quoteYAMLString(name)}
|
||||
description: |
|
||||
This batch change uses [Comby](https://comby.dev) to improve inefficient string comparison with strings.ToLower or strings.ToUpper
|
||||
on:
|
||||
- repositoriesMatchingQuery: |
|
||||
if strings.ToLower(:[1]) == strings.ToLower(:[2]) or if strings.ToUpper(:[1]) == strings.ToUpper(:[2]) or if strings.ToLower(:[1]) != strings.ToLower(:[2]) or if strings.ToUpper(:[1]) != strings.ToUpper(:[2]) patternType:structural archived:no
|
||||
|
||||
steps:
|
||||
- run: comby -config /tmp/rule.toml -f .go -i -exclude-dir vendor,.
|
||||
container: comby/comby
|
||||
files:
|
||||
/tmp/rule.toml: |
|
||||
[SA6005_01]
|
||||
match='if strings.ToLower(:[1]) == strings.ToLower(:[2])'
|
||||
rewrite='if strings.EqualFold(:[1], :[2])'
|
||||
|
||||
[SA6005_02]
|
||||
match='if strings.ToLower(:[1]) != strings.ToLower(:[2])'
|
||||
rewrite='if !strings.EqualFold(:[1], :[2])'
|
||||
|
||||
[SA6005_03]
|
||||
match='if strings.ToUpper(:[1]) == strings.ToUpper(:[2])'
|
||||
rewrite='if strings.EqualFold(:[1], :[2])'
|
||||
|
||||
[SA6005_04]
|
||||
match='if strings.ToUpper(:[1]) != strings.ToUpper(:[2])'
|
||||
rewrite='if !strings.EqualFold(:[1], :[2])'
|
||||
|
||||
changesetTemplate:
|
||||
title: Improve inefficient string comparison with strings.ToLower or strings.ToUpper
|
||||
body: This batch change uses [Comby](https://comby.dev) to improve inefficient string comparison with strings.ToLower or strings.ToUpper
|
||||
branch: batches/\${{batch_change.name}}
|
||||
commit:
|
||||
message: Improve inefficient string comparison with strings.ToLower or strings.ToUpper
|
||||
`
|
||||
}
|
||||
|
||||
export function goCheckerS1002Template(name: string): string {
|
||||
return `name: ${quoteYAMLString(name)}
|
||||
description: |
|
||||
This batch change uses [Comby](https://comby.dev) to omit comparison with boolean constant
|
||||
on:
|
||||
- repositoriesMatchingQuery: |
|
||||
if :[1:e] == false or if :[1:e] == true patternType:structural archived:no
|
||||
|
||||
steps:
|
||||
- run: comby -config /tmp/rule.toml -f .go -i -exclude-dir vendor,.
|
||||
container: comby/comby
|
||||
files:
|
||||
/tmp/rule.toml: |
|
||||
[S1002_01]
|
||||
match='if :[1:e] == true '
|
||||
rewrite='if :[1]'
|
||||
|
||||
[S1002_02]
|
||||
match='if :[1:e] == false '
|
||||
rewrite='if !:[1]'
|
||||
|
||||
changesetTemplate:
|
||||
title: Omit comparison with boolean constant
|
||||
body: This batch change uses [Comby](https://comby.dev) to omit comparison with boolean constant
|
||||
branch: batches/\${{batch_change.name}}
|
||||
commit:
|
||||
message: Omit comparison with boolean constant
|
||||
`
|
||||
}
|
||||
|
||||
export function goCheckerS1003Template(name: string): string {
|
||||
return `name: ${quoteYAMLString(name)}
|
||||
description: |
|
||||
This batch change uses [Comby](https://comby.dev) to replace calls to strings.Index with strings.Contains.
|
||||
on:
|
||||
- repositoriesMatchingQuery: |
|
||||
strings.Index(:[1], :[2]) < 0 or strings.Index(:[1], :[2]) == -1 or strings.Index(:[1], :[2]) != -1 or strings.Index(:[1], :[2]) >= 0 or strings.Index(:[1], :[2]) > -1 or strings.IndexAny(:[1], :[2]) < 0 or strings.IndexAny(:[1], :[2]) == -1 or strings.IndexAny(:[1], :[2]) != -1 or strings.IndexAny(:[1], :[2]) >= 0 or strings.IndexAny(:[1], :[2]) > -1 or strings.IndexRune(:[1], :[2]) < 0 or strings.IndexRune(:[1], :[2]) == -1 or strings.IndexRune(:[1], :[2]) != -1 or strings.IndexRune(:[1], :[2]) >= 0 or strings.IndexRune(:[1], :[2]) > -1 patternType:structural archived:no
|
||||
|
||||
steps:
|
||||
- run: comby -config /tmp/rule.toml -f .go -i -exclude-dir vendor,.
|
||||
container: comby/comby
|
||||
files:
|
||||
/tmp/rule.toml: |
|
||||
[S1003_01]
|
||||
match='strings.IndexRune(:[1], :[2]) > -1'
|
||||
rewrite='strings.ContainsRune(:[1], :[2])'
|
||||
|
||||
[S1003_02]
|
||||
match='strings.IndexRune(:[1], :[2]) >= 0'
|
||||
rewrite='strings.ContainsRune(:[1], :[2])'
|
||||
|
||||
[S1003_03]
|
||||
match='strings.IndexRune(:[1], :[2]) != -1'
|
||||
rewrite='strings.ContainsRune(:[1], :[2])'
|
||||
|
||||
[S1003_04]
|
||||
match='strings.IndexRune(:[1], :[2]) == -1'
|
||||
rewrite='!strings.ContainsRune(:[1], :[2])'
|
||||
|
||||
[S1003_05]
|
||||
match='strings.IndexRune(:[1], :[2]) < 0'
|
||||
rewrite='!strings.ContainsRune(:[1], :[2])'
|
||||
|
||||
[S1003_06]
|
||||
match='strings.IndexAny(:[1], :[2]) > -1'
|
||||
rewrite='strings.ContainsAny(:[1], :[2])'
|
||||
|
||||
[S1003_07]
|
||||
match='strings.IndexAny(:[1], :[2]) >= 0'
|
||||
rewrite='strings.ContainsAny(:[1], :[2])'
|
||||
|
||||
[S1003_08]
|
||||
match='strings.IndexAny(:[1], :[2]) != -1'
|
||||
rewrite='strings.ContainsAny(:[1], :[2])'
|
||||
|
||||
[S1003_09]
|
||||
match='strings.IndexAny(:[1], :[2]) == -1'
|
||||
rewrite='!strings.ContainsAny(:[1], :[2])'
|
||||
|
||||
[S1003_10]
|
||||
match='strings.IndexAny(:[1], :[2]) < 0'
|
||||
rewrite='!strings.ContainsAny(:[1], :[2])'
|
||||
|
||||
[S1003_11]
|
||||
match='strings.Index(:[1], :[2]) > -1'
|
||||
rewrite='strings.Contains(:[1], :[2])'
|
||||
|
||||
[S1003_12]
|
||||
match='strings.Index(:[1], :[2]) >= 0'
|
||||
rewrite='strings.Contains(:[1], :[2])'
|
||||
|
||||
[S1003_13]
|
||||
match='strings.Index(:[1], :[2]) != -1'
|
||||
rewrite='strings.Contains(:[1], :[2])'
|
||||
|
||||
[S1003_14]
|
||||
match='strings.Index(:[1], :[2]) == -1'
|
||||
rewrite='!strings.Contains(:[1], :[2])'
|
||||
|
||||
[S1003_15]
|
||||
match='strings.Index(:[1], :[2]) < 0'
|
||||
rewrite='!strings.Contains(:[1], :[2])'
|
||||
changesetTemplate:
|
||||
title: Replace calls to strings.Index with strings.Contains.
|
||||
body: This batch change uses [Comby](https://comby.dev) to replace calls to strings.Index with strings.Contains.
|
||||
branch: batches/\${{batch_change.name}}
|
||||
commit:
|
||||
message: Replace calls to strings.Index with strings.Contains.
|
||||
`
|
||||
}
|
||||
|
||||
export function goCheckerS1004Template(name: string): string {
|
||||
return `name: ${quoteYAMLString(name)}
|
||||
description: |
|
||||
This batch change uses [Comby](https://comby.dev) to replace call to bytes.Compare with bytes.Equal
|
||||
on:
|
||||
- repositoriesMatchingQuery: |
|
||||
bytes.Compare(:[1], :[2]) != 0 or bytes.Compare(:[1], :[2]) == 0 patternType:structural archived:no
|
||||
|
||||
steps:
|
||||
- run: comby -config /tmp/rule.toml -f .go -i -exclude-dir vendor,.
|
||||
container: comby/comby
|
||||
files:
|
||||
/tmp/rule.toml: |
|
||||
[S1004_01]
|
||||
match='bytes.Compare(:[1], :[2]) == 0'
|
||||
rewrite='bytes.Equal(:[1], :[2])'
|
||||
|
||||
[S1004_02]
|
||||
match='bytes.Compare(:[1], :[2]) != 0'
|
||||
rewrite='!bytes.Equal(:[1], :[2])'
|
||||
|
||||
changesetTemplate:
|
||||
title: Replace call to bytes.Compare with bytes.Equal
|
||||
body: This batch change uses [Comby](https://comby.dev) to replace call to bytes.Compare with bytes.Equal
|
||||
branch: batches/\${{batch_change.name}}
|
||||
commit:
|
||||
message: Replace call to bytes.Compare with bytes.Equal
|
||||
`
|
||||
}
|
||||
|
||||
export function goCheckerS1005Template(name: string): string {
|
||||
return `name: ${quoteYAMLString(name)}
|
||||
description: |
|
||||
This batch change uses [Comby](https://comby.dev) to drop unnecessary use of the blank identifier
|
||||
on:
|
||||
- repositoriesMatchingQuery: |
|
||||
for :[1:e], :[~_] := range or for :[1:e], :[~_] = range or for :[~_] = range or for :[~_], :[~_] = range patternType:structural archived:no
|
||||
|
||||
steps:
|
||||
- run: comby -config /tmp/rule.toml -f .go -i -exclude-dir vendor,.
|
||||
container: comby/comby
|
||||
files:
|
||||
/tmp/rule.toml: |
|
||||
[S1005_01]
|
||||
match='for :[~_], :[~_] = range'
|
||||
rewrite='for range'
|
||||
|
||||
[S1005_02]
|
||||
match='for :[~_] = range'
|
||||
rewrite='for range'
|
||||
|
||||
[S1005_03]
|
||||
match='for :[1:e], :[~_] = range'
|
||||
rewrite='for :[1] = range'
|
||||
|
||||
[S1005_04]
|
||||
match='for :[1:e], :[~_] := range'
|
||||
rewrite='for :[1] := range'
|
||||
changesetTemplate:
|
||||
title: Drop unnecessary use of the blank identifier
|
||||
body: This batch change uses [Comby](https://comby.dev) to drop unnecessary use of the blank identifier
|
||||
branch: batches/\${{batch_change.name}}
|
||||
commit:
|
||||
message: Drop unnecessary use of the blank identifier
|
||||
`
|
||||
}
|
||||
|
||||
export function goCheckerS1006Template(name: string): string {
|
||||
return `name: ${quoteYAMLString(name)}
|
||||
description: |
|
||||
This batch change uses [Comby](https://comby.dev) to use for { ... } for infinite loops
|
||||
on:
|
||||
- repositoriesMatchingQuery: |
|
||||
for true {:[x]} patternType:structural archived:no
|
||||
|
||||
steps:
|
||||
- run: comby -config /tmp/rule.toml -f .go -i -exclude-dir vendor,.
|
||||
container: comby/comby
|
||||
files:
|
||||
/tmp/rule.toml: |
|
||||
match='for true {:[x]}'
|
||||
rewrite='for {:[x]}'
|
||||
changesetTemplate:
|
||||
title: Use for { ... } for infinite loops
|
||||
body: This batch change uses [Comby](https://comby.dev) to use for { ... } for infinite loops
|
||||
branch: batches/\${{batch_change.name}}
|
||||
commit:
|
||||
message: Use for { ... } for infinite loops
|
||||
`
|
||||
}
|
||||
|
||||
export function goCheckerS1010Template(name: string): string {
|
||||
return `name: ${quoteYAMLString(name)}
|
||||
description: |
|
||||
This batch change uses [Comby](https://comby.dev) to omit default slice index
|
||||
on:
|
||||
- repositoriesMatchingQuery: |
|
||||
:[s.][:len(:[s])] patternType:structural archived:no
|
||||
|
||||
steps:
|
||||
- run: comby -config /tmp/rule.toml -f .go -i -exclude-dir vendor,.
|
||||
container: comby/comby
|
||||
files:
|
||||
/tmp/rule.toml: |
|
||||
match=':[s.][:len(:[s])]'
|
||||
rewrite=':[s.][:]'
|
||||
changesetTemplate:
|
||||
title: Omit default slice index
|
||||
body: This batch change uses [Comby](https://comby.dev) to omit default slice index
|
||||
branch: batches/\${{batch_change.name}}
|
||||
commit:
|
||||
message: omit default slice index
|
||||
`
|
||||
}
|
||||
|
||||
export function goCheckerS1012Template(name: string): string {
|
||||
return `name: ${quoteYAMLString(name)}
|
||||
description: |
|
||||
This batch change uses [Comby](https://comby.dev) to replace time.Now().Sub(x) with time.Since(x)
|
||||
on:
|
||||
- repositoriesMatchingQuery: |
|
||||
time.Now().Sub(:[x]) patternType:structural archived:no
|
||||
|
||||
steps:
|
||||
- run: comby -config /tmp/rule.toml -f .go -i -exclude-dir vendor,.
|
||||
container: comby/comby
|
||||
files:
|
||||
/tmp/rule.toml: |
|
||||
match='time.Now().Sub(:[x])'
|
||||
rewrite='time.Since(:[x])'
|
||||
changesetTemplate:
|
||||
title: Replace time.Now().Sub(x) with time.Since(x)
|
||||
body: This batch change uses [Comby](https://comby.dev) to replace time.Now().Sub(x) with time.Since(x)
|
||||
branch: batches/\${{batch_change.name}}
|
||||
commit:
|
||||
message: replace time.Now().Sub(x) with time.Since(x)
|
||||
`
|
||||
}
|
||||
|
||||
export function goCheckerS1019Template(name: string): string {
|
||||
return `name: ${quoteYAMLString(name)}
|
||||
description: |
|
||||
This batch change uses [Comby](https://comby.dev) to simplify make call by omitting redundant arguments
|
||||
on:
|
||||
- repositoriesMatchingQuery: |
|
||||
make(chan int, 0) or make(map[:[[1]]]:[[1]], 0) or make(:[1], :[2], :[2]) patternType:structural archived:no
|
||||
|
||||
steps:
|
||||
- run: comby -config /tmp/rule.toml -f .go -i -exclude-dir vendor,.
|
||||
container: comby/comby
|
||||
files:
|
||||
/tmp/rule.toml: |
|
||||
[S1019_01]
|
||||
match='make(:[1], :[2], :[2])'
|
||||
rewrite='make(:[1], :[2])'
|
||||
|
||||
[S1019_02]
|
||||
match='make(map[:[[1]]]:[[1]], 0)'
|
||||
rewrite='make(map[:[[1]]]:[[1]])'
|
||||
|
||||
[S1019_03]
|
||||
match='make(chan int, 0)'
|
||||
rewrite='make(chan int)'
|
||||
changesetTemplate:
|
||||
title: Simplify make call by omitting redundant arguments
|
||||
body: This batch change uses [Comby](https://comby.dev) to simplify make call by omitting redundant arguments
|
||||
branch: batches/\${{batch_change.name}}
|
||||
commit:
|
||||
message: simplify make call by omitting redundant arguments
|
||||
`
|
||||
}
|
||||
|
||||
export function goCheckerS1020Template(name: string): string {
|
||||
return `name: ${quoteYAMLString(name)}
|
||||
description: |
|
||||
This batch change uses [Comby](https://comby.dev) to omit redundant nil check in type assertion
|
||||
on:
|
||||
- repositoriesMatchingQuery: |
|
||||
if :[_.], ok := :[i.].(:[T]); :[i.] != nil && ok {:[body]} or if :[_.], ok := :[i.].(:[T]); ok && :[i.] != nil {:[body]} or if :[i.] != nil { if :[_.], ok := :[i.].(:[T]); ok {:[body]}} patternType:structural archived:no
|
||||
|
||||
steps:
|
||||
- run: comby -config /tmp/rule.toml -f .go -i -exclude-dir vendor,.
|
||||
container: comby/comby
|
||||
files:
|
||||
/tmp/rule.toml: |
|
||||
[S1020_01]
|
||||
match='if :[_.], ok := :[i.].(:[T]); ok && :[i.] != nil {:[body]}'
|
||||
rewrite='if :[_.], ok := :[i.].(:[T]); ok {:[body]}'
|
||||
|
||||
[S1020_02]
|
||||
match='if :[_.], ok := :[i.].(:[T]); :[i.] != nil && ok {:[body]}'
|
||||
rewrite='if :[_.], ok := :[i.].(:[T]); ok {:[body]}'
|
||||
|
||||
[S1020_03]
|
||||
match='''
|
||||
if :[i.] != nil {
|
||||
if :[_.], ok := :[i.].(:[T]); ok {:[body]}
|
||||
}'''
|
||||
rewrite='if :[_.], ok := :[i.].(:[T]); ok {:[body]}'
|
||||
changesetTemplate:
|
||||
title: Omit redundant nil check in type assertion
|
||||
body: This batch change uses [Comby](https://comby.dev) to omit redundant nil check in type assertion
|
||||
branch: batches/\${{batch_change.name}}
|
||||
commit:
|
||||
message: omit redundant nil check in type assertion
|
||||
`
|
||||
}
|
||||
|
||||
export function goCheckerS1023Template(name: string): string {
|
||||
return `name: ${quoteYAMLString(name)}
|
||||
description: |
|
||||
This batch change uses [Comby](https://comby.dev) to omit redundant control flow
|
||||
on:
|
||||
- repositoriesMatchingQuery: |
|
||||
func() {:[body] return } or func :[fn.](:[args]) {:[body] return } patternType:structural archived:no
|
||||
|
||||
steps:
|
||||
- run: comby -config /tmp/rule.toml -f .go -i -exclude-dir vendor,.
|
||||
container: comby/comby
|
||||
files:
|
||||
/tmp/rule.toml: |
|
||||
[S1023_01]
|
||||
match='func :[fn.](:[args]) {:[body] return }'
|
||||
rewrite='func :[fn.](:[args]) {:[body]}'
|
||||
|
||||
[S1023_02]
|
||||
match='func() {:[body] return }'
|
||||
rewrite='func() {:[body]}'
|
||||
|
||||
changesetTemplate:
|
||||
title: Omit redundant control flow
|
||||
body: This batch change uses [Comby](https://comby.dev) to omit redundant control flow
|
||||
branch: batches/\${{batch_change.name}}
|
||||
commit:
|
||||
message: omit redundant control flow
|
||||
`
|
||||
}
|
||||
|
||||
export function goCheckerS1024Template(name: string): string {
|
||||
return `name: ${quoteYAMLString(name)}
|
||||
description: |
|
||||
This batch change uses [Comby](https://comby.dev) to replace x.Sub(time.Now()) with time.Until(x)
|
||||
on:
|
||||
- repositoriesMatchingQuery: |
|
||||
:[x.].Sub(time.Now()) patternType:structural archived:no
|
||||
steps:
|
||||
- run: comby -config /tmp/rule.toml -f .go -i -exclude-dir vendor,.
|
||||
container: comby/comby
|
||||
files:
|
||||
/tmp/rule.toml: |
|
||||
[S1023_01]
|
||||
match='func :[fn.](:[args]) {:[body] return }'
|
||||
rewrite='func :[fn.](:[args]) {:[body]}'
|
||||
|
||||
[S1023_02]
|
||||
match='func() {:[body] return }'
|
||||
rewrite='func() {:[body]}'
|
||||
|
||||
changesetTemplate:
|
||||
title: Replace x.Sub(time.Now()) with time.Until(x)
|
||||
body: This batch change uses [Comby](https://comby.dev) to replace x.Sub(time.Now()) with time.Until(x)
|
||||
branch: batches/\${{batch_change.name}}
|
||||
commit:
|
||||
message: replace x.Sub(time.Now()) with time.Until(x)
|
||||
`
|
||||
}
|
||||
|
||||
export function goCheckerS1025Template(name: string): string {
|
||||
return `name: ${quoteYAMLString(name)}
|
||||
description: |
|
||||
This batch change uses [Comby](https://comby.dev) to enforce don’t use fmt.Sprintf("%s", x) unnecessarily
|
||||
on:
|
||||
- repositoriesMatchingQuery: |
|
||||
fmt.Println("%s", ":[s]") patternType:structural archived:no
|
||||
steps:
|
||||
- run: comby -config /tmp/rule.toml -f .go -i -exclude-dir vendor,.
|
||||
container: comby/comby
|
||||
files:
|
||||
/tmp/rule.toml: |
|
||||
match='fmt.Println("%s", ":[s]")'
|
||||
rewrite='fmt.Println(":[s]")'
|
||||
|
||||
changesetTemplate:
|
||||
title: Don’t use fmt.Sprintf("%s", x) unnecessarily
|
||||
body: This batch change uses [Comby](https://comby.dev) to enforce don’t use fmt.Sprintf("%s", x) unnecessarily
|
||||
branch: batches/\${{batch_change.name}}
|
||||
commit:
|
||||
message: don’t use fmt.Sprintf("%s", x) unnecessarily
|
||||
`
|
||||
}
|
||||
|
||||
export function goCheckerS1028Template(name: string): string {
|
||||
return `name: ${quoteYAMLString(name)}
|
||||
description: |
|
||||
This batch change uses [Comby](https://comby.dev) to simplify error construction with fmt.Errorf
|
||||
on:
|
||||
- repositoriesMatchingQuery: |
|
||||
errors.New(fmt.Sprintf(:[1])) patternType:structural archived:no
|
||||
steps:
|
||||
- run: comby -config /tmp/rule.toml -f .go -i -exclude-dir vendor,.
|
||||
container: comby/comby
|
||||
files:
|
||||
/tmp/rule.toml: |
|
||||
[S1028_01]
|
||||
match='errors.New(fmt.Sprintf(:[1]))'
|
||||
rewrite='fmt.Errorf(:[1])'
|
||||
|
||||
changesetTemplate:
|
||||
title: Simplify error construction with fmt.Errorf
|
||||
body: This batch change uses [Comby](https://comby.dev) to simplify error construction with fmt.Errorf
|
||||
branch: batches/\${{batch_change.name}}
|
||||
commit:
|
||||
message: simplify error construction with fmt.Errorf
|
||||
`
|
||||
}
|
||||
|
||||
export function goCheckerS1029Template(name: string): string {
|
||||
return `name: ${quoteYAMLString(name)}
|
||||
description: |
|
||||
This batch change uses [Comby](https://comby.dev) to range over the string directly
|
||||
on:
|
||||
- repositoriesMatchingQuery: |
|
||||
for :[~_], :[r.] := range []rune(:[s.]) patternType:structural archived:no
|
||||
steps:
|
||||
- run: comby -config /tmp/rule.toml -f .go -i -exclude-dir vendor,.
|
||||
container: comby/comby
|
||||
files:
|
||||
/tmp/rule.toml: |
|
||||
[S1029_01]
|
||||
match='for :[~_], :[r.] := range []rune(:[s.])'
|
||||
rewrite='for _, :[r] := range :[s]'
|
||||
|
||||
changesetTemplate:
|
||||
title: Range over the string directly
|
||||
body: This batch change uses [Comby](https://comby.dev) to range over the string directly
|
||||
branch: batches/\${{batch_change.name}}
|
||||
commit:
|
||||
message: range over the string directly
|
||||
`
|
||||
}
|
||||
|
||||
export function goCheckerS1032Template(name: string): string {
|
||||
return `name: ${quoteYAMLString(name)}
|
||||
description: |
|
||||
This batch change uses [Comby](https://comby.dev) to use sort.Ints(x), sort.Float64s(x), and sort.Strings(x)
|
||||
on:
|
||||
- repositoriesMatchingQuery: |
|
||||
sort.Sort(sort.Float64Slice(:[1])) or sort.Sort(sort.StringSlice(:[1])) or sort.Sort(sort.IntSlice(:[1])) patternType:structural archived:no
|
||||
steps:
|
||||
- run: comby -config /tmp/rule.toml -f .go -i -exclude-dir vendor,.
|
||||
container: comby/comby
|
||||
files:
|
||||
/tmp/rule.toml: |
|
||||
[S1032_01]
|
||||
match='sort.Sort(sort.IntSlice(:[1]))'
|
||||
rewrite='sort.Ints(:[1])'
|
||||
|
||||
[S1032_02]
|
||||
match='sort.Sort(sort.StringSlice(:[1]))'
|
||||
rewrite='sort.Strings(:[1])'
|
||||
|
||||
[S1032_03]
|
||||
match='sort.Sort(sort.Float64Slice(:[1]))'
|
||||
rewrite='sort.Float64s(:[1])'
|
||||
|
||||
changesetTemplate:
|
||||
title: Use sort.Ints(x), sort.Float64s(x), and sort.Strings(x)
|
||||
body: This batch change uses [Comby](https://comby.dev) to use sort.Ints(x), sort.Float64s(x), and sort.Strings(x)
|
||||
branch: batches/\${{batch_change.name}}
|
||||
commit:
|
||||
message: use sort.Ints(x), sort.Float64s(x), and sort.Strings(x)
|
||||
`
|
||||
}
|
||||
|
||||
export function goCheckerS1035Template(name: string): string {
|
||||
return `name: ${quoteYAMLString(name)}
|
||||
description: |
|
||||
This batch change uses [Comby](https://comby.dev) to remove redundant call to net/http.CanonicalHeaderKey in method call on net/http.Header
|
||||
on:
|
||||
- repositoriesMatchingQuery: |
|
||||
headers.Set(http.CanonicalHeaderKey(:[1])) or headers.Get(http.CanonicalHeaderKey(:[1])) or headers.Del(http.CanonicalHeaderKey(:[1])) or headers.Add(http.CanonicalHeaderKey(:[1]), :[1]) patternType:structural archived:no
|
||||
steps:
|
||||
- run: comby -config /tmp/rule.toml -f .go -i -exclude-dir vendor,.
|
||||
container: comby/comby
|
||||
files:
|
||||
/tmp/rule.toml: |
|
||||
[S1035_01]
|
||||
match='headers.Add(http.CanonicalHeaderKey(:[1]), :[1])'
|
||||
rewrite='headers.Add(:[1], :[1])'
|
||||
|
||||
[S1035_02]
|
||||
match='headers.Del(http.CanonicalHeaderKey(:[1]))'
|
||||
rewrite='headers.Del(:[1])'
|
||||
|
||||
[S1035_03]
|
||||
match='headers.Get(http.CanonicalHeaderKey(:[1]))'
|
||||
rewrite='headers.Get(:[1])'
|
||||
|
||||
[S1035_04]
|
||||
match='headers.Set(http.CanonicalHeaderKey(:[1]))'
|
||||
rewrite='headers.Set(:[1])'
|
||||
|
||||
changesetTemplate:
|
||||
title: Remove redundant call to net/http.CanonicalHeaderKey in method call on net/http.Header
|
||||
body: This batch change uses [Comby](https://comby.dev) to remove redundant call to net/http.CanonicalHeaderKey in method call on net/http.Header
|
||||
branch: batches/\${{batch_change.name}}
|
||||
commit:
|
||||
message: remove redundant call to net/http.CanonicalHeaderKey in method call on net/http.Header
|
||||
`
|
||||
}
|
||||
|
||||
export function goCheckerS1037Template(name: string): string {
|
||||
return `name: ${quoteYAMLString(name)}
|
||||
description: |
|
||||
This batch change uses [Comby](https://comby.dev) to remove redundant call to net/http.CanonicalHeaderKey in method call on net/http.Header
|
||||
on:
|
||||
- repositoriesMatchingQuery: |
|
||||
headers.Set(http.CanonicalHeaderKey(:[1])) or headers.Get(http.CanonicalHeaderKey(:[1])) or headers.Del(http.CanonicalHeaderKey(:[1])) or headers.Add(http.CanonicalHeaderKey(:[1]), :[1]) patternType:structural archived:no
|
||||
steps:
|
||||
- run: comby -config /tmp/rule.toml -f .go -i -exclude-dir vendor,.
|
||||
container: comby/comby
|
||||
files:
|
||||
/tmp/rule.toml: |
|
||||
[S1037_01]
|
||||
match='''
|
||||
select {
|
||||
case <-time.After(:[t]):
|
||||
}'''
|
||||
rewrite='time.Sleep(:[t])'
|
||||
|
||||
changesetTemplate:
|
||||
title: Redundant call to net/http.CanonicalHeaderKey in method call on net/http.Header
|
||||
body: This batch change uses [Comby](https://comby.dev) to remove redundant call to net/http.CanonicalHeaderKey in method call on net/http.Header
|
||||
branch: batches/\${{batch_change.name}}
|
||||
commit:
|
||||
message: remove redundant call to net/http.CanonicalHeaderKey in method call on net/http.Header
|
||||
`
|
||||
}
|
||||
|
||||
export function goCheckerS1038Template(name: string): string {
|
||||
return `name: ${quoteYAMLString(name)}
|
||||
description: |
|
||||
This batch change uses [Comby](https://comby.dev) to remove redundant call to net/http.CanonicalHeaderKey in method call on net/http.Header
|
||||
on:
|
||||
- repositoriesMatchingQuery: |
|
||||
headers.Set(http.CanonicalHeaderKey(:[1])) or headers.Get(http.CanonicalHeaderKey(:[1])) or headers.Del(http.CanonicalHeaderKey(:[1])) or headers.Add(http.CanonicalHeaderKey(:[1]), :[1]) patternType:structural archived:no
|
||||
steps:
|
||||
- run: comby -config /tmp/rule.toml -f .go -i -exclude-dir vendor,.
|
||||
container: comby/comby
|
||||
files:
|
||||
/tmp/rule.toml: |
|
||||
[S1037_01]
|
||||
match='''
|
||||
select {
|
||||
case <-time.After(:[t]):
|
||||
}'''
|
||||
rewrite='time.Sleep(:[t])'
|
||||
|
||||
changesetTemplate:
|
||||
title: Redundant call to net/http.CanonicalHeaderKey in method call on net/http.Header
|
||||
body: This batch change uses [Comby](https://comby.dev) to remove redundant call to net/http.CanonicalHeaderKey in method call on net/http.Header
|
||||
branch: batches/\${{batch_change.name}}
|
||||
commit:
|
||||
message: remove redundant call to net/http.CanonicalHeaderKey in method call on net/http.Header
|
||||
`
|
||||
}
|
||||
|
||||
export function goCheckerS1039Template(name: string): string {
|
||||
return `name: ${quoteYAMLString(name)}
|
||||
description: |
|
||||
This batch change uses [Comby](https://comby.dev) to improve unnecessary use of fmt.Sprint
|
||||
on:
|
||||
- repositoriesMatchingQuery: |
|
||||
fmt.Sprintf("%s", ":[s]") patternType:structural archived:no
|
||||
steps:
|
||||
- run: comby -config /tmp/rule.toml -f .go -i -exclude-dir vendor,.
|
||||
container: comby/comby
|
||||
files:
|
||||
/tmp/rule.toml: |
|
||||
[S1039]
|
||||
match='fmt.Sprintf("%s", ":[s]")'
|
||||
rewrite='":[s]"'
|
||||
changesetTemplate:
|
||||
title: Improve unnecessary use of fmt.Sprint
|
||||
body: This batch change uses [Comby](https://comby.dev) to improve unnecessary use of fmt.Sprint
|
||||
branch: batches/\${{batch_change.name}}
|
||||
commit:
|
||||
message: unnecessary use of fmt.Sprint
|
||||
`
|
||||
}
|
||||
|
||||
export function getTemplateRenderer(kind: string | null): ((name: string) => string) | undefined {
|
||||
if (!kind) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
switch (kind) {
|
||||
case 'goCheckerSA6005':
|
||||
return goCheckerSA6005Template
|
||||
case 'goCheckerS1002':
|
||||
return goCheckerS1002Template
|
||||
case 'goCheckerS1003':
|
||||
return goCheckerS1003Template
|
||||
case 'goCheckerS1004':
|
||||
return goCheckerS1004Template
|
||||
case 'goCheckerS1005':
|
||||
return goCheckerS1005Template
|
||||
case 'goCheckerS1006':
|
||||
return goCheckerS1006Template
|
||||
case 'goCheckerS1010':
|
||||
return goCheckerS1010Template
|
||||
case 'goCheckerS1012':
|
||||
return goCheckerS1012Template
|
||||
case 'goCheckerS1019':
|
||||
return goCheckerS1019Template
|
||||
case 'goCheckerS1020':
|
||||
return goCheckerS1020Template
|
||||
case 'goCheckerS1023':
|
||||
return goCheckerS1023Template
|
||||
case 'goCheckerS1024':
|
||||
return goCheckerS1024Template
|
||||
case 'goCheckerS1025':
|
||||
return goCheckerS1025Template
|
||||
case 'goCheckerS1028':
|
||||
return goCheckerS1028Template
|
||||
case 'goCheckerS1029':
|
||||
return goCheckerS1029Template
|
||||
case 'goCheckerS1032':
|
||||
return goCheckerS1032Template
|
||||
case 'goCheckerS1035':
|
||||
return goCheckerS1035Template
|
||||
case 'goCheckerS1037':
|
||||
return goCheckerS1037Template
|
||||
case 'goCheckerS1038':
|
||||
return goCheckerS1038Template
|
||||
case 'goCheckerS1039':
|
||||
return goCheckerS1039Template
|
||||
default:
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
@ -349,7 +349,7 @@ export const isMinimalBatchSpec = (spec: string): boolean => {
|
||||
*
|
||||
* @param value the string value to inspect
|
||||
*/
|
||||
function quoteYAMLString(value: string): string {
|
||||
export function quoteYAMLString(value: string): string {
|
||||
let needsQuotes = false
|
||||
// First we need to craft an AST where the value is the value to a key in an object.
|
||||
let ast = load('name: ' + value + '\n')
|
||||
|
||||
@ -49,7 +49,7 @@ export interface CodeInsightsAppRouter extends SettingsCascadeProps<Settings>, T
|
||||
* Main Insight routing component. Main entry point to code insights UI.
|
||||
*/
|
||||
export const CodeInsightsAppRouter = withAuthenticatedUser<CodeInsightsAppRouter>(props => {
|
||||
const { telemetryService, authenticatedUser } = props
|
||||
const { telemetryService, authenticatedUser, settingsCascade } = props
|
||||
|
||||
const match = useRouteMatch()
|
||||
return (
|
||||
@ -98,6 +98,7 @@ export const CodeInsightsAppRouter = withAuthenticatedUser<CodeInsightsAppRouter
|
||||
? CodeInsightsRootPageTab.CodeInsights
|
||||
: CodeInsightsRootPageTab.GettingStarted
|
||||
}
|
||||
settingsCascade={settingsCascade}
|
||||
telemetryService={telemetryService}
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -41,7 +41,10 @@ export const CodeInsightsRouter: React.FunctionComponent<CodeInsightsRouterProps
|
||||
return (
|
||||
<CodeInsightsBackendContext.Provider value={api}>
|
||||
{props.isSourcegraphDotCom ? (
|
||||
<CodeInsightsDotComGetStartedLazy telemetryService={props.telemetryService} />
|
||||
<CodeInsightsDotComGetStartedLazy
|
||||
settingsCascade={props.settingsCascade}
|
||||
telemetryService={props.telemetryService}
|
||||
/>
|
||||
) : (
|
||||
<CodeInsightsAppLazyRouter {...props} />
|
||||
)}
|
||||
|
||||
@ -573,6 +573,10 @@ const codeInsightsApiWithManyLines = {
|
||||
|
||||
export const SmartInsightsViewGridExample = (): JSX.Element => (
|
||||
<CodeInsightsBackendStoryMock mocks={codeInsightsApiWithManyLines}>
|
||||
<SmartInsightsViewGrid insights={insightsWithManyLines} telemetryService={NOOP_TELEMETRY_SERVICE} />
|
||||
<SmartInsightsViewGrid
|
||||
settingsCascade={{ final: null, subjects: null }}
|
||||
insights={insightsWithManyLines}
|
||||
telemetryService={NOOP_TELEMETRY_SERVICE}
|
||||
/>
|
||||
</CodeInsightsBackendStoryMock>
|
||||
)
|
||||
|
||||
@ -3,6 +3,8 @@ import React, { memo, useCallback, useEffect, useState } from 'react'
|
||||
import { isEqual } from 'lodash'
|
||||
import { Layout, Layouts } from 'react-grid-layout'
|
||||
|
||||
import { Settings } from '@sourcegraph/shared/src/schema/settings.schema'
|
||||
import { SettingsCascadeProps } from '@sourcegraph/shared/src/settings/settings'
|
||||
import { TelemetryProps } from '@sourcegraph/shared/src/telemetry/telemetryService'
|
||||
|
||||
import { ViewGrid } from '../../../../views'
|
||||
@ -12,7 +14,7 @@ import { getTrackingTypeByInsightType } from '../../pings'
|
||||
import { SmartInsight } from './components/SmartInsight'
|
||||
import { insightLayoutGenerator, recalculateGridLayout } from './utils/grid-layout-generator'
|
||||
|
||||
interface SmartInsightsViewGridProps extends TelemetryProps {
|
||||
interface SmartInsightsViewGridProps extends TelemetryProps, SettingsCascadeProps<Settings> {
|
||||
/**
|
||||
* List of built-in insights such as backend insight, FE search and code-stats
|
||||
* insights.
|
||||
@ -82,6 +84,7 @@ export const SmartInsightsViewGrid: React.FunctionComponent<SmartInsightsViewGri
|
||||
>
|
||||
{insights.map(insight => (
|
||||
<SmartInsight
|
||||
settingsCascade={props.settingsCascade}
|
||||
key={insight.id}
|
||||
insight={insight}
|
||||
telemetryService={telemetryService}
|
||||
|
||||
@ -3,6 +3,8 @@ import React, { Ref, useContext, useMemo, useRef, useState } from 'react'
|
||||
import { useMergeRefs } from 'use-callback-ref'
|
||||
|
||||
import { ErrorAlert } from '@sourcegraph/branded/src/components/alerts'
|
||||
import { Settings } from '@sourcegraph/shared/src/schema/settings.schema'
|
||||
import { SettingsCascadeProps } from '@sourcegraph/shared/src/settings/settings'
|
||||
import { TelemetryProps } from '@sourcegraph/shared/src/telemetry/telemetryService'
|
||||
import { useDeepMemo } from '@sourcegraph/wildcard'
|
||||
|
||||
@ -29,7 +31,10 @@ import { useInsightData } from '../hooks/use-insight-data'
|
||||
import { InsightContextMenu } from './insight-context-menu/InsightContextMenu'
|
||||
import { InsightContext } from './InsightContext'
|
||||
|
||||
interface BuiltInInsightProps extends TelemetryProps, React.HTMLAttributes<HTMLElement> {
|
||||
interface BuiltInInsightProps
|
||||
extends TelemetryProps,
|
||||
SettingsCascadeProps<Settings>,
|
||||
React.HTMLAttributes<HTMLElement> {
|
||||
insight: SearchRuntimeBasedInsight | LangStatsInsight
|
||||
innerRef: Ref<HTMLElement>
|
||||
resizing: boolean
|
||||
@ -79,6 +84,7 @@ export function BuiltInInsight(props: BuiltInInsightProps): React.ReactElement {
|
||||
<InsightCardHeader title={insight.title}>
|
||||
{isVisible && (
|
||||
<InsightContextMenu
|
||||
settingsCascade={props.settingsCascade}
|
||||
insight={insight}
|
||||
dashboard={dashboard}
|
||||
menuButtonClassName="ml-1 d-inline-flex"
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
import React, { forwardRef } from 'react'
|
||||
|
||||
import { Settings } from '@sourcegraph/shared/src/schema/settings.schema'
|
||||
import { SettingsCascadeProps } from '@sourcegraph/shared/src/settings/settings'
|
||||
import { TelemetryProps } from '@sourcegraph/shared/src/telemetry/telemetryService'
|
||||
|
||||
import { Insight, isBackendInsight } from '../../../core'
|
||||
@ -7,7 +9,10 @@ import { Insight, isBackendInsight } from '../../../core'
|
||||
import { BackendInsightView } from './backend-insight/BackendInsight'
|
||||
import { BuiltInInsight } from './BuiltInInsight'
|
||||
|
||||
export interface SmartInsightProps extends TelemetryProps, React.HTMLAttributes<HTMLElement> {
|
||||
export interface SmartInsightProps
|
||||
extends TelemetryProps,
|
||||
SettingsCascadeProps<Settings>,
|
||||
React.HTMLAttributes<HTMLElement> {
|
||||
insight: Insight
|
||||
resizing?: boolean
|
||||
}
|
||||
|
||||
@ -132,6 +132,7 @@ const TestBackendInsight: React.FunctionComponent = () => (
|
||||
insight={INSIGHT_CONFIGURATION_MOCK}
|
||||
telemetryService={NOOP_TELEMETRY_SERVICE}
|
||||
innerRef={() => {}}
|
||||
settingsCascade={{ final: null, subjects: null }}
|
||||
/>
|
||||
)
|
||||
|
||||
@ -171,6 +172,7 @@ export const BackendInsight: Story = () => (
|
||||
<h2>Locked Card insight</h2>
|
||||
<CodeInsightsBackendStoryMock mocks={mockInsightAPI()}>
|
||||
<BackendInsightView
|
||||
settingsCascade={{ final: null, subjects: null }}
|
||||
style={{ width: 400, height: 400 }}
|
||||
insight={{ ...INSIGHT_CONFIGURATION_MOCK, isFrozen: true }}
|
||||
telemetryService={NOOP_TELEMETRY_SERVICE}
|
||||
|
||||
@ -4,6 +4,8 @@ import classNames from 'classnames'
|
||||
import { useMergeRefs } from 'use-callback-ref'
|
||||
|
||||
import { asError } from '@sourcegraph/common'
|
||||
import { Settings } from '@sourcegraph/shared/src/schema/settings.schema'
|
||||
import { SettingsCascadeProps } from '@sourcegraph/shared/src/settings/settings'
|
||||
import { TelemetryProps } from '@sourcegraph/shared/src/telemetry/telemetryService'
|
||||
import { useDebounce, useDeepMemo } from '@sourcegraph/wildcard'
|
||||
|
||||
@ -27,6 +29,7 @@ import styles from './BackendInsight.module.scss'
|
||||
|
||||
interface BackendInsightProps
|
||||
extends TelemetryProps,
|
||||
SettingsCascadeProps<Settings>,
|
||||
React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement> {
|
||||
insight: BackendInsight
|
||||
|
||||
@ -152,6 +155,7 @@ export const BackendInsightView: React.FunctionComponent<BackendInsightProps> =
|
||||
onVisibilityChange={setIsFiltersOpen}
|
||||
/>
|
||||
<InsightContextMenu
|
||||
settingsCascade={props.settingsCascade}
|
||||
insight={insight}
|
||||
dashboard={dashboard}
|
||||
menuButtonClassName="ml-1 d-inline-flex"
|
||||
|
||||
@ -4,9 +4,12 @@ import classNames from 'classnames'
|
||||
import { noop } from 'lodash'
|
||||
import DotsVerticalIcon from 'mdi-react/DotsVerticalIcon'
|
||||
|
||||
import { isErrorLike } from '@sourcegraph/common'
|
||||
import { Settings } from '@sourcegraph/shared/src/schema/settings.schema'
|
||||
import { SettingsCascadeProps } from '@sourcegraph/shared/src/settings/settings'
|
||||
import { Link, Menu, MenuButton, MenuDivider, MenuItem, MenuLink, MenuList, Position } from '@sourcegraph/wildcard'
|
||||
|
||||
import { Insight, InsightDashboard, isVirtualDashboard } from '../../../../core'
|
||||
import { Insight, InsightDashboard, InsightType, isVirtualDashboard } from '../../../../core'
|
||||
import { useUiFeatures } from '../../../../hooks/use-ui-features'
|
||||
|
||||
import { ConfirmDeleteModal } from './ConfirmDeleteModal'
|
||||
@ -14,7 +17,7 @@ import { ConfirmRemoveModal } from './ConfirmRemoveModal'
|
||||
|
||||
import styles from './InsightContextMenu.module.scss'
|
||||
|
||||
export interface InsightCardMenuProps {
|
||||
export interface InsightCardMenuProps extends SettingsCascadeProps<Settings> {
|
||||
insight: Insight
|
||||
dashboard: InsightDashboard | null
|
||||
zeroYAxisMin: boolean
|
||||
@ -38,6 +41,15 @@ export const InsightContextMenu: React.FunctionComponent<InsightCardMenuProps> =
|
||||
const editUrl = dashboard?.id
|
||||
? `/insights/edit/${insightID}?dashboardId=${dashboard.id}`
|
||||
: `/insights/edit/${insightID}`
|
||||
const showQuickFix =
|
||||
insight.title.includes('[quickfix]') &&
|
||||
props.settingsCascade.final !== null &&
|
||||
!isErrorLike(props.settingsCascade.final) &&
|
||||
props.settingsCascade.final.experimentalFeatures?.goCodeCheckerTemplates
|
||||
const quickFixUrl =
|
||||
insight.type === InsightType.SearchBased
|
||||
? `/batch-changes/create?kind=goChecker${insight.series[0]?.name}&title=${insight.title}`
|
||||
: undefined
|
||||
|
||||
const withinVirtualDashboard = !!dashboard && isVirtualDashboard(dashboard)
|
||||
|
||||
@ -89,6 +101,12 @@ export const InsightContextMenu: React.FunctionComponent<InsightCardMenuProps> =
|
||||
</MenuItem>
|
||||
)}
|
||||
|
||||
{quickFixUrl && showQuickFix && (
|
||||
<MenuLink as={Link} className={styles.item} to={quickFixUrl}>
|
||||
Golang quick fixes
|
||||
</MenuLink>
|
||||
)}
|
||||
|
||||
{dashboard && (
|
||||
<MenuItem
|
||||
data-testid="insight-context-remove-from-dashboard-button"
|
||||
|
||||
@ -9,6 +9,8 @@ import { Route } from 'react-router-dom'
|
||||
import { of } from 'rxjs'
|
||||
import sinon from 'sinon'
|
||||
|
||||
import { Settings } from '@sourcegraph/shared/src/schema/settings.schema'
|
||||
import { SettingsCascadeOrError } from '@sourcegraph/shared/src/settings/settings'
|
||||
import { MockedTestProvider } from '@sourcegraph/shared/src/testing/apollo'
|
||||
import { MockIntersectionObserver } from '@sourcegraph/shared/src/testing/MockIntersectionObserver'
|
||||
|
||||
@ -21,6 +23,11 @@ import {
|
||||
|
||||
import { CodeInsightsRootPage, CodeInsightsRootPageTab } from './CodeInsightsRootPage'
|
||||
|
||||
const mockSettingsCascade: SettingsCascadeOrError<Settings> = {
|
||||
final: null,
|
||||
subjects: null,
|
||||
}
|
||||
|
||||
interface ReactRouterMock {
|
||||
useHistory: () => unknown
|
||||
useRouteMatch: () => unknown
|
||||
@ -89,6 +96,7 @@ describe('CodeInsightsRootPage', () => {
|
||||
it('should redirect to "All insights" page if no dashboardId is provided', () => {
|
||||
const { testLocation } = renderWithBrandedContext(
|
||||
<CodeInsightsRootPage
|
||||
settingsCascade={mockSettingsCascade}
|
||||
activeView={CodeInsightsRootPageTab.CodeInsights}
|
||||
telemetryService={mockTelemetryService}
|
||||
/>,
|
||||
@ -107,6 +115,7 @@ describe('CodeInsightsRootPage', () => {
|
||||
it('should render dashboard not found page when id is not found', () => {
|
||||
renderWithBrandedContext(
|
||||
<CodeInsightsRootPage
|
||||
settingsCascade={mockSettingsCascade}
|
||||
activeView={CodeInsightsRootPageTab.CodeInsights}
|
||||
telemetryService={mockTelemetryService}
|
||||
/>,
|
||||
@ -126,6 +135,7 @@ describe('CodeInsightsRootPage', () => {
|
||||
it('should log events', () => {
|
||||
renderWithBrandedContext(
|
||||
<CodeInsightsRootPage
|
||||
settingsCascade={mockSettingsCascade}
|
||||
activeView={CodeInsightsRootPageTab.CodeInsights}
|
||||
telemetryService={mockTelemetryService}
|
||||
/>,
|
||||
|
||||
@ -4,6 +4,8 @@ import PlusIcon from 'mdi-react/PlusIcon'
|
||||
import { matchPath, useHistory } from 'react-router'
|
||||
import { useLocation } from 'react-router-dom'
|
||||
|
||||
import { Settings } from '@sourcegraph/shared/src/schema/settings.schema'
|
||||
import { SettingsCascadeProps } from '@sourcegraph/shared/src/settings/settings'
|
||||
import { useTemporarySetting } from '@sourcegraph/shared/src/settings/temporary/useTemporarySetting'
|
||||
import { TelemetryProps } from '@sourcegraph/shared/src/telemetry/telemetryService'
|
||||
import { lazyComponent } from '@sourcegraph/shared/src/util/lazyComponent'
|
||||
@ -36,7 +38,7 @@ function useQuery(): URLSearchParams {
|
||||
return React.useMemo(() => new URLSearchParams(search), [search])
|
||||
}
|
||||
|
||||
interface CodeInsightsRootPageProps extends TelemetryProps {
|
||||
interface CodeInsightsRootPageProps extends TelemetryProps, SettingsCascadeProps<Settings> {
|
||||
activeView: CodeInsightsRootPageTab
|
||||
}
|
||||
|
||||
@ -101,10 +103,17 @@ export const CodeInsightsRootPage: React.FunctionComponent<CodeInsightsRootPageP
|
||||
</TabList>
|
||||
<TabPanels className="mt-3">
|
||||
<TabPanel>
|
||||
<DashboardsContentPage telemetryService={telemetryService} dashboardID={params?.dashboardId} />
|
||||
<DashboardsContentPage
|
||||
settingsCascade={props.settingsCascade}
|
||||
telemetryService={telemetryService}
|
||||
dashboardID={params?.dashboardId}
|
||||
/>
|
||||
</TabPanel>
|
||||
<TabPanel>
|
||||
<LazyCodeInsightsGettingStartedPage telemetryService={telemetryService} />
|
||||
<LazyCodeInsightsGettingStartedPage
|
||||
settingsCascade={props.settingsCascade}
|
||||
telemetryService={telemetryService}
|
||||
/>
|
||||
</TabPanel>
|
||||
</TabPanels>
|
||||
</Tabs>
|
||||
|
||||
@ -157,7 +157,11 @@ const renderDashboardsContent = (
|
||||
...renderWithBrandedContext(
|
||||
<MockedTestProvider mocks={mocks}>
|
||||
<Wrapper>
|
||||
<DashboardsContentPage dashboardID={dashboardID} telemetryService={mockTelemetryService} />
|
||||
<DashboardsContentPage
|
||||
settingsCascade={{ final: null, subjects: null }}
|
||||
dashboardID={dashboardID}
|
||||
telemetryService={mockTelemetryService}
|
||||
/>
|
||||
</Wrapper>
|
||||
</MockedTestProvider>
|
||||
),
|
||||
|
||||
@ -3,6 +3,8 @@ import React, { useContext, useMemo } from 'react'
|
||||
import { useRouteMatch } from 'react-router'
|
||||
import { Redirect } from 'react-router-dom'
|
||||
|
||||
import { Settings } from '@sourcegraph/shared/src/schema/settings.schema'
|
||||
import { SettingsCascadeProps } from '@sourcegraph/shared/src/settings/settings'
|
||||
import { TelemetryProps } from '@sourcegraph/shared/src/telemetry/telemetryService'
|
||||
import { LoadingSpinner, useObservable } from '@sourcegraph/wildcard'
|
||||
|
||||
@ -11,7 +13,7 @@ import { CodeInsightsBackendContext, ALL_INSIGHTS_DASHBOARD } from '../../../cor
|
||||
|
||||
import { DashboardsContent } from './components/dashboards-content/DashboardsContent'
|
||||
|
||||
export interface DashboardsContentPageProps extends TelemetryProps {
|
||||
export interface DashboardsContentPageProps extends TelemetryProps, SettingsCascadeProps<Settings> {
|
||||
/**
|
||||
* Possible dashboard id. All insights on the page will be get from
|
||||
* dashboard's info from the user or org settings by the dashboard id.
|
||||
@ -22,7 +24,7 @@ export interface DashboardsContentPageProps extends TelemetryProps {
|
||||
}
|
||||
|
||||
export const DashboardsContentPage: React.FunctionComponent<DashboardsContentPageProps> = props => {
|
||||
const { dashboardID, telemetryService } = props
|
||||
const { dashboardID, telemetryService, settingsCascade } = props
|
||||
const { url } = useRouteMatch()
|
||||
|
||||
const { getDashboards } = useContext(CodeInsightsBackendContext)
|
||||
@ -47,7 +49,12 @@ export const DashboardsContentPage: React.FunctionComponent<DashboardsContentPag
|
||||
return (
|
||||
<>
|
||||
<PageTitle title={`${currentDashboard?.title || ''} - Code Insights`} />
|
||||
<DashboardsContent telemetryService={telemetryService} dashboardID={dashboardID} dashboards={dashboards} />
|
||||
<DashboardsContent
|
||||
settingsCascade={settingsCascade}
|
||||
telemetryService={telemetryService}
|
||||
dashboardID={dashboardID}
|
||||
dashboards={dashboards}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@ -4,6 +4,8 @@ import classNames from 'classnames'
|
||||
import MapSearchIcon from 'mdi-react/MapSearchIcon'
|
||||
import { useHistory } from 'react-router-dom'
|
||||
|
||||
import { Settings } from '@sourcegraph/shared/src/schema/settings.schema'
|
||||
import { SettingsCascadeProps } from '@sourcegraph/shared/src/settings/settings'
|
||||
import { TelemetryProps } from '@sourcegraph/shared/src/telemetry/telemetryService'
|
||||
import { Button } from '@sourcegraph/wildcard'
|
||||
|
||||
@ -23,7 +25,7 @@ import { isDashboardConfigurable } from './utils/is-dashboard-configurable'
|
||||
|
||||
import styles from './DashboardsContent.module.scss'
|
||||
|
||||
export interface DashboardsContentProps extends TelemetryProps {
|
||||
export interface DashboardsContentProps extends TelemetryProps, SettingsCascadeProps<Settings> {
|
||||
/**
|
||||
* Possible dashboard id. All insights on the page will be get from
|
||||
* dashboard's info from the user or org settings by the dashboard id.
|
||||
@ -137,6 +139,7 @@ export const DashboardsContent: React.FunctionComponent<DashboardsContentProps>
|
||||
|
||||
{currentDashboard ? (
|
||||
<DashboardInsights
|
||||
settingsCascade={props.settingsCascade}
|
||||
dashboard={currentDashboard}
|
||||
telemetryService={telemetryService}
|
||||
className={styles.insights}
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
import React, { useContext, useMemo } from 'react'
|
||||
|
||||
import { Settings } from '@sourcegraph/shared/src/schema/settings.schema'
|
||||
import { SettingsCascadeProps } from '@sourcegraph/shared/src/settings/settings'
|
||||
import { TelemetryProps } from '@sourcegraph/shared/src/telemetry/telemetryService'
|
||||
import { LoadingSpinner, useObservable } from '@sourcegraph/wildcard'
|
||||
|
||||
@ -7,7 +9,7 @@ import { SmartInsightsViewGrid, InsightContext } from '../../../../../../../comp
|
||||
import { CodeInsightsBackendContext, InsightDashboard } from '../../../../../../../core'
|
||||
import { EmptyInsightDashboard } from '../empty-insight-dashboard/EmptyInsightDashboard'
|
||||
|
||||
interface DashboardInsightsProps extends TelemetryProps {
|
||||
interface DashboardInsightsProps extends TelemetryProps, SettingsCascadeProps<Settings> {
|
||||
dashboard: InsightDashboard
|
||||
className?: string
|
||||
onAddInsightRequest: () => void
|
||||
@ -29,7 +31,12 @@ export const DashboardInsights: React.FunctionComponent<DashboardInsightsProps>
|
||||
return (
|
||||
<InsightContext.Provider value={{ dashboard }}>
|
||||
{insights.length > 0 ? (
|
||||
<SmartInsightsViewGrid insights={insights} telemetryService={telemetryService} className={className} />
|
||||
<SmartInsightsViewGrid
|
||||
settingsCascade={props.settingsCascade}
|
||||
insights={insights}
|
||||
telemetryService={telemetryService}
|
||||
className={className}
|
||||
/>
|
||||
) : (
|
||||
<EmptyInsightDashboard dashboard={dashboard} onAddInsight={onAddInsightRequest} />
|
||||
)}
|
||||
|
||||
@ -12,5 +12,8 @@ export default {
|
||||
} as Meta
|
||||
|
||||
export const CodeInsightsDotComGetStartedStory = () => (
|
||||
<CodeInsightsDotComGetStarted telemetryService={NOOP_TELEMETRY_SERVICE} />
|
||||
<CodeInsightsDotComGetStarted
|
||||
telemetryService={NOOP_TELEMETRY_SERVICE}
|
||||
settingsCascade={{ subjects: null, final: null }}
|
||||
/>
|
||||
)
|
||||
|
||||
@ -2,6 +2,8 @@ import React, { useEffect } from 'react'
|
||||
|
||||
import classNames from 'classnames'
|
||||
|
||||
import { Settings } from '@sourcegraph/shared/src/schema/settings.schema'
|
||||
import { SettingsCascadeProps } from '@sourcegraph/shared/src/settings/settings'
|
||||
import { TelemetryProps } from '@sourcegraph/shared/src/telemetry/telemetryService'
|
||||
import { Button, Card, CardBody, Link, PageHeader } from '@sourcegraph/wildcard'
|
||||
|
||||
@ -19,7 +21,7 @@ import styles from './CodeInsightsDotComGetStarted.module.scss'
|
||||
|
||||
const DOT_COM_CONTEXT = { mode: CodeInsightsLandingPageType.Cloud }
|
||||
|
||||
export interface CodeInsightsDotComGetStartedProps extends TelemetryProps {}
|
||||
export interface CodeInsightsDotComGetStartedProps extends TelemetryProps, SettingsCascadeProps<Settings> {}
|
||||
|
||||
export const CodeInsightsDotComGetStarted: React.FunctionComponent<CodeInsightsDotComGetStartedProps> = props => {
|
||||
const { telemetryService } = props
|
||||
@ -169,7 +171,11 @@ export const CodeInsightsDotComGetStarted: React.FunctionComponent<CodeInsightsD
|
||||
</Card>
|
||||
</section>
|
||||
|
||||
<CodeInsightsTemplates className={styles.templateSection} telemetryService={telemetryService} />
|
||||
<CodeInsightsTemplates
|
||||
className={styles.templateSection}
|
||||
settingsCascade={props.settingsCascade}
|
||||
telemetryService={telemetryService}
|
||||
/>
|
||||
|
||||
<iframe
|
||||
src="https://www.youtube.com/embed/fMCUJQHfbUA"
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
import React, { useEffect } from 'react'
|
||||
|
||||
import { Settings } from '@sourcegraph/shared/src/schema/settings.schema'
|
||||
import { SettingsCascadeProps } from '@sourcegraph/shared/src/settings/settings'
|
||||
import { TelemetryProps } from '@sourcegraph/shared/src/telemetry/telemetryService'
|
||||
|
||||
import { PageTitle } from '../../../../../components/PageTitle'
|
||||
@ -11,7 +13,7 @@ import { DynamicCodeInsightExample } from './components/dynamic-code-insight-exa
|
||||
|
||||
import styles from './CodeInsightsGettingStartedPage.module.scss'
|
||||
|
||||
interface CodeInsightsGettingStartedPageProps extends TelemetryProps {}
|
||||
interface CodeInsightsGettingStartedPageProps extends TelemetryProps, SettingsCascadeProps<Settings> {}
|
||||
|
||||
export const CodeInsightsGettingStartedPage: React.FunctionComponent<CodeInsightsGettingStartedPageProps> = props => {
|
||||
const { telemetryService } = props
|
||||
@ -25,7 +27,11 @@ export const CodeInsightsGettingStartedPage: React.FunctionComponent<CodeInsight
|
||||
<PageTitle title="Code Insights" />
|
||||
<DynamicCodeInsightExample telemetryService={telemetryService} />
|
||||
<CodeInsightsExamples telemetryService={telemetryService} className={styles.section} />
|
||||
<CodeInsightsTemplates telemetryService={telemetryService} className={styles.section} />
|
||||
<CodeInsightsTemplates
|
||||
telemetryService={telemetryService}
|
||||
settingsCascade={props.settingsCascade}
|
||||
className={styles.section}
|
||||
/>
|
||||
<CodeInsightsLearnMore telemetryService={telemetryService} className={styles.section} />
|
||||
</main>
|
||||
)
|
||||
|
||||
@ -4,6 +4,8 @@ import copy from 'copy-to-clipboard'
|
||||
import ContentCopyIcon from 'mdi-react/ContentCopyIcon'
|
||||
|
||||
import { SyntaxHighlightedSearchQuery } from '@sourcegraph/search-ui'
|
||||
import { Settings } from '@sourcegraph/shared/src/schema/settings.schema'
|
||||
import { SettingsCascadeProps } from '@sourcegraph/shared/src/settings/settings'
|
||||
import { TelemetryProps } from '@sourcegraph/shared/src/telemetry/telemetryService'
|
||||
import {
|
||||
Button,
|
||||
@ -19,6 +21,7 @@ import {
|
||||
TooltipController,
|
||||
Icon,
|
||||
Link,
|
||||
ProductStatusBadge,
|
||||
} from '@sourcegraph/wildcard'
|
||||
|
||||
import { CodeInsightsBackendContext, InsightType } from '../../../../../core'
|
||||
@ -31,7 +34,7 @@ import {
|
||||
} from '../../../CodeInsightsLandingPageContext'
|
||||
import { CodeInsightsQueryBlock } from '../code-insights-query-block/CodeInsightsQueryBlock'
|
||||
|
||||
import { Template, TEMPLATE_SECTIONS } from './constants'
|
||||
import { Template, getTemplateSections } from './constants'
|
||||
|
||||
import styles from './CodeInsightsTemplates.module.scss'
|
||||
|
||||
@ -44,14 +47,19 @@ function getTemplateURL(template: Template): string {
|
||||
}
|
||||
}
|
||||
|
||||
interface CodeInsightsTemplates extends TelemetryProps, React.HTMLAttributes<HTMLElement> {}
|
||||
interface CodeInsightsTemplates
|
||||
extends TelemetryProps,
|
||||
React.HTMLAttributes<HTMLElement>,
|
||||
SettingsCascadeProps<Settings> {}
|
||||
|
||||
export const CodeInsightsTemplates: React.FunctionComponent<CodeInsightsTemplates> = props => {
|
||||
const { telemetryService, ...otherProps } = props
|
||||
const tabChangePingName = useLogEventName('InsightsGetStartedTabClick')
|
||||
|
||||
const templateSections = getTemplateSections(props)
|
||||
|
||||
const handleTabChange = (index: number): void => {
|
||||
const template = TEMPLATE_SECTIONS[index]
|
||||
const template = templateSections[index]
|
||||
|
||||
telemetryService.log(tabChangePingName, { tabName: template.title }, { tabName: template.title })
|
||||
}
|
||||
@ -69,12 +77,15 @@ export const CodeInsightsTemplates: React.FunctionComponent<CodeInsightsTemplate
|
||||
|
||||
<Tabs size="medium" className="mt-3" onChange={handleTabChange}>
|
||||
<TabList wrapperClassName={styles.tabList}>
|
||||
{TEMPLATE_SECTIONS.map(section => (
|
||||
<Tab key={section.title}>{section.title}</Tab>
|
||||
{templateSections.map(section => (
|
||||
<Tab key={section.title}>
|
||||
{section.title}
|
||||
{section.experimental && <ProductStatusBadge className="ml-1" status="experimental" />}
|
||||
</Tab>
|
||||
))}
|
||||
</TabList>
|
||||
<TabPanels>
|
||||
{TEMPLATE_SECTIONS.map(section => (
|
||||
{templateSections.map(section => (
|
||||
<TemplatesPanel
|
||||
key={section.title}
|
||||
sectionTitle={section.title}
|
||||
|
||||
@ -1,3 +1,7 @@
|
||||
import { isErrorLike } from '@sourcegraph/common'
|
||||
import { Settings } from '@sourcegraph/shared/src/schema/settings.schema'
|
||||
import { SettingsCascadeProps } from '@sourcegraph/shared/src/settings/settings'
|
||||
|
||||
import { InsightType } from '../../../../../core/types'
|
||||
import { CaptureInsightUrlValues } from '../../../../insights/creation/capture-group'
|
||||
import { DATA_SERIES_COLORS, SearchInsightURLValues } from '../../../../insights/creation/search-insight'
|
||||
@ -5,6 +9,7 @@ import { DATA_SERIES_COLORS, SearchInsightURLValues } from '../../../../insights
|
||||
export interface TemplateSection {
|
||||
title: string
|
||||
templates: Template[]
|
||||
experimental?: boolean
|
||||
}
|
||||
|
||||
export type Template = SearchTemplate | CaptureGroupTemplate
|
||||
@ -809,88 +814,574 @@ const DATA_FETCHING_GQL: Template = {
|
||||
},
|
||||
}
|
||||
|
||||
export const TEMPLATE_SECTIONS: TemplateSection[] = [
|
||||
{
|
||||
title: 'Popular',
|
||||
templates: [
|
||||
TERRAFORM_VERSIONS,
|
||||
CSS_MODULES_MIGRATION,
|
||||
LOG4J_FIXED_VERSIONS,
|
||||
YARN_ADOPTION,
|
||||
JAVA_VERSIONS,
|
||||
LINTER_OVERRIDE_RULES,
|
||||
TS_JS_USAGE,
|
||||
const GO_STATIC_CHECK_SA6005: Template = {
|
||||
type: InsightType.SearchBased,
|
||||
title: '[quickfix] - Inefficient string comparison with strings.ToLower or strings.ToUpper',
|
||||
description: 'Code search turned code checker',
|
||||
templateValues: {
|
||||
title: '[quickfix] - Inefficient string comparison with strings.ToLower or strings.ToUpper',
|
||||
allRepos: true,
|
||||
series: [
|
||||
{
|
||||
name: 'SA6005',
|
||||
query:
|
||||
'if strings.ToLower(:[1]) == strings.ToLower(:[2]) or if strings.ToUpper(:[1]) == strings.ToUpper(:[2]) or if strings.ToLower(:[1]) != strings.ToLower(:[2]) or if strings.ToUpper(:[1]) != strings.ToUpper(:[2]) patternType:structural archived:no',
|
||||
stroke: DATA_SERIES_COLORS.GRAPE,
|
||||
},
|
||||
{
|
||||
name: 'SA6005 - fixed',
|
||||
query:
|
||||
'if strings.EqualFold(:[1], :[2]) or if !strings.EqualFold(:[1], :[2]) or if strings.EqualFold(:[1], :[2]) or if !strings.EqualFold(:[1], :[2]) patternType:structural archived:no',
|
||||
stroke: DATA_SERIES_COLORS.GREEN,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Migration',
|
||||
templates: [
|
||||
CONFIG_OR_DOC_FILE,
|
||||
ALLOW_DENY_LIST_TRACKING,
|
||||
CSS_MODULES_MIGRATION,
|
||||
PYTHON_2_3,
|
||||
REACT_FUNCTION_CLASS,
|
||||
}
|
||||
|
||||
const GO_STATIC_CHECK_S1002: Template = {
|
||||
type: InsightType.SearchBased,
|
||||
title: '[quickfix] - Omit comparison with boolean constant',
|
||||
description: 'Code search turned code checker',
|
||||
templateValues: {
|
||||
title: '[quickfix] - Omit comparison with boolean constant',
|
||||
allRepos: true,
|
||||
series: [
|
||||
{
|
||||
name: 'S1002',
|
||||
query: 'if :[1:e] == false or if :[1:e] == true patternType:structural archived:no',
|
||||
stroke: DATA_SERIES_COLORS.GRAPE,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Adoption',
|
||||
templates: [
|
||||
NEW_API_USAGE,
|
||||
YARN_ADOPTION,
|
||||
FREQUENTLY_USED_DATABASE,
|
||||
LARGE_PACKAGE_USAGE,
|
||||
REACT_COMPONENT_LIB_USAGE,
|
||||
CI_TOOLING,
|
||||
}
|
||||
|
||||
const GO_STATIC_CHECK_S1003: Template = {
|
||||
type: InsightType.SearchBased,
|
||||
title: 'Replace call to strings.Index with strings.Contains',
|
||||
description: 'Code search turned code checker',
|
||||
templateValues: {
|
||||
title: '[quickfix] - Replace call to strings.Index with strings.Contains',
|
||||
allRepos: true,
|
||||
series: [
|
||||
{
|
||||
name: 'S1003',
|
||||
query:
|
||||
'strings.Index(:[1], :[2]) < 0 or strings.Index(:[1], :[2]) == -1 or strings.Index(:[1], :[2]) != -1 or strings.Index(:[1], :[2]) >= 0 or strings.Index(:[1], :[2]) > -1 or strings.IndexAny(:[1], :[2]) < 0 or strings.IndexAny(:[1], :[2]) == -1 or strings.IndexAny(:[1], :[2]) != -1 or strings.IndexAny(:[1], :[2]) >= 0 or strings.IndexAny(:[1], :[2]) > -1 or strings.IndexRune(:[1], :[2]) < 0 or strings.IndexRune(:[1], :[2]) == -1 or strings.IndexRune(:[1], :[2]) != -1 or strings.IndexRune(:[1], :[2]) >= 0 or strings.IndexRune(:[1], :[2]) > -1 patternType:structural archived:no',
|
||||
stroke: DATA_SERIES_COLORS.GRAPE,
|
||||
},
|
||||
{
|
||||
name: 'S1003 - fixed',
|
||||
query:
|
||||
'strings.ContainsRune(:[1], :[2]) or strings.ContainsRune(:[1], :[2]) or strings.ContainsRune(:[1], :[2]) or !strings.ContainsRune(:[1], :[2]) or !strings.ContainsRune(:[1], :[2]) or strings.ContainsAny(:[1], :[2]) or strings.ContainsAny(:[1], :[2]) or strings.ContainsAny(:[1], :[2]) or !strings.ContainsAny(:[1], :[2]) or !strings.ContainsAny(:[1], :[2]) or strings.Contains(:[1], :[2]) or !strings.Contains(:[1], :[2]) or !strings.Contains(:[1], :[2]) patternType:structural archived:no',
|
||||
stroke: DATA_SERIES_COLORS.GREEN,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Deprecation',
|
||||
templates: [
|
||||
CSS_CLASS,
|
||||
ICON_OR_IMAGE,
|
||||
STRUCTURAL_CODE_PATTERN,
|
||||
TOOLING_MIGRATION,
|
||||
VAR_KEYWORDS,
|
||||
TESTING_LIBRARIES,
|
||||
}
|
||||
|
||||
const GO_STATIC_CHECK_S1004: Template = {
|
||||
type: InsightType.SearchBased,
|
||||
title: '[quickfix] - Replace call to bytes.Compare with bytes.Equal',
|
||||
description: 'Code search turned code checker',
|
||||
templateValues: {
|
||||
title: '[quickfix] - Replace call to bytes.Compare with bytes.Equal',
|
||||
allRepos: true,
|
||||
series: [
|
||||
{
|
||||
name: 'S1004',
|
||||
query:
|
||||
'bytes.Compare(:[1], :[2]) != 0 or bytes.Compare(:[1], :[2]) == 0 patternType:structural archived:no',
|
||||
stroke: DATA_SERIES_COLORS.GRAPE,
|
||||
},
|
||||
{
|
||||
name: 'S1004 - fixed',
|
||||
query: '!bytes.Equal(:[1], :[2]) or bytes.Equal(:[1], :[2]) patternType:structural archived:no',
|
||||
stroke: DATA_SERIES_COLORS.GREEN,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Versions and patterns',
|
||||
templates: [
|
||||
JAVA_VERSIONS,
|
||||
LICENSE_TYPES,
|
||||
ALL_LOG4J_VERSIONS,
|
||||
PYTHON_VERSIONS,
|
||||
NODEJS_VERSIONS,
|
||||
CSS_COLORS,
|
||||
CHECKOV_SKIP_TYPES,
|
||||
}
|
||||
|
||||
const GO_STATIC_CHECK_S1005: Template = {
|
||||
type: InsightType.SearchBased,
|
||||
title: '[quickfix] - Drop unnecessary use of the blank identifier',
|
||||
description: 'Code search turned code checker',
|
||||
templateValues: {
|
||||
title: '[quickfix] - Drop unnecessary use of the blank identifier',
|
||||
allRepos: true,
|
||||
series: [
|
||||
{
|
||||
name: 'S1005',
|
||||
query:
|
||||
'for :[1:e], :[~_] := range or for :[1:e], :[~_] = range or for :[~_] = range or for :[~_], :[~_] = range patternType:structural archived:no',
|
||||
stroke: DATA_SERIES_COLORS.GRAPE,
|
||||
},
|
||||
{
|
||||
name: 'S1005 - fixed',
|
||||
query: 'for range or for :[1] := range or for :[1] = range patternType:structural archived:no',
|
||||
stroke: DATA_SERIES_COLORS.GREEN,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Code health',
|
||||
templates: [
|
||||
TODOS,
|
||||
LINTER_OVERRIDE_RULES,
|
||||
REVERT_COMMITS,
|
||||
DEPRECATED_CALLS,
|
||||
STORYBOOK_TESTS,
|
||||
REPOS_WITH_README,
|
||||
OWNERSHIP_TRACKING,
|
||||
CI_TOOLING,
|
||||
}
|
||||
|
||||
const GO_STATIC_CHECK_S1006: Template = {
|
||||
type: InsightType.SearchBased,
|
||||
title: '[quickfix] - Use for { ... } for infinite loops',
|
||||
description: 'Code search turned code checker',
|
||||
templateValues: {
|
||||
title: '[quickfix] - Use for { ... } for infinite loops',
|
||||
allRepos: true,
|
||||
series: [
|
||||
{
|
||||
name: 'S1006',
|
||||
query: 'for true {:[x]} patternType:structural archived:no',
|
||||
stroke: DATA_SERIES_COLORS.GRAPE,
|
||||
},
|
||||
{
|
||||
name: 'S1006 - fixed',
|
||||
query: 'for {:[x]} patternType:structural archived:no',
|
||||
stroke: DATA_SERIES_COLORS.GREEN,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Security',
|
||||
templates: [
|
||||
VULNERABLE_OPEN_SOURCE,
|
||||
API_KEYS_DETECTION,
|
||||
LOG4J_FIXED_VERSIONS,
|
||||
SKIPPED_TESTS,
|
||||
TEST_AMOUNT_AND_TYPES,
|
||||
}
|
||||
|
||||
const GO_STATIC_CHECK_S1010: Template = {
|
||||
type: InsightType.SearchBased,
|
||||
title: '[quickfix] - Omit default slice index',
|
||||
description: 'Code search turned code checker',
|
||||
templateValues: {
|
||||
title: '[quickfix] - Omit default slice index',
|
||||
allRepos: true,
|
||||
series: [
|
||||
{
|
||||
name: 'S10010',
|
||||
query: ':[s.][:len(:[s])] patternType:structural archived:no',
|
||||
stroke: DATA_SERIES_COLORS.GRAPE,
|
||||
},
|
||||
{
|
||||
name: 'S1010 - fixed',
|
||||
query: ':[s.][:] patternType:structural archived:no',
|
||||
stroke: DATA_SERIES_COLORS.GREEN,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Other',
|
||||
templates: [TS_VS_GO, IOS_APP_SCREENS, ADOPTING_NEW_API, PROBLEMATIC_API_BY_TEAM, DATA_FETCHING_GQL],
|
||||
}
|
||||
|
||||
const GO_STATIC_CHECK_S1012: Template = {
|
||||
type: InsightType.SearchBased,
|
||||
title: '[quickfix] - Replace time.Now().Sub(x) with time.Since(x)',
|
||||
description: 'Code search turned code checker',
|
||||
templateValues: {
|
||||
title: '[quickfix] - Replace time.Now().Sub(x) with time.Since(x)',
|
||||
allRepos: true,
|
||||
series: [
|
||||
{
|
||||
name: 'S10012',
|
||||
query: 'time.Now().Sub(:[x]) patternType:structural archived:no',
|
||||
stroke: DATA_SERIES_COLORS.GRAPE,
|
||||
},
|
||||
{
|
||||
name: 'S1012 - fixed',
|
||||
query: 'time.Since(:[x]) patternType:structural archived:no',
|
||||
stroke: DATA_SERIES_COLORS.GREEN,
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
// const GO_STATIC_CHECK_S1017: skipped
|
||||
// const GO_STATIC_CHECK_S1018: skipped
|
||||
|
||||
const GO_STATIC_CHECK_S1019: Template = {
|
||||
type: InsightType.SearchBased,
|
||||
title: '[quickfix] - Simplify make call by omitting redundant arguments',
|
||||
description: 'Code search turned code checker',
|
||||
templateValues: {
|
||||
title: '[quickfix] - Simplify make call by omitting redundant arguments',
|
||||
allRepos: true,
|
||||
series: [
|
||||
{
|
||||
name: 'S10019',
|
||||
query:
|
||||
'make(chan int, 0) or make(map[:[[1]]]:[[1]], 0) or make(:[1], :[2], :[2]) patternType:structural archived:no',
|
||||
stroke: DATA_SERIES_COLORS.GRAPE,
|
||||
},
|
||||
{
|
||||
name: 'S1019 - fixed',
|
||||
query:
|
||||
'make(chan int) or make(map[:[[1]]]:[[1]]) or make(:[1], :[2]) patternType:structural archived:no',
|
||||
stroke: DATA_SERIES_COLORS.GREEN,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
const GO_STATIC_CHECK_S1020: Template = {
|
||||
type: InsightType.SearchBased,
|
||||
title: '[quickfix] - Omit redundant nil check in type assertion',
|
||||
description: 'Code search turned code checker',
|
||||
templateValues: {
|
||||
title: '[quickfix] - Omit redundant nil check in type assertion',
|
||||
allRepos: true,
|
||||
series: [
|
||||
{
|
||||
name: 'S1020',
|
||||
query:
|
||||
'if :[_.], ok := :[i.].(:[T]); :[i.] != nil && ok {:[body]} or if :[_.], ok := :[i.].(:[T]); ok && :[i.] != nil {:[body]} or if :[i.] != nil { if :[_.], ok := :[i.].(:[T]); ok {:[body]}} patternType:structural archived:no',
|
||||
stroke: DATA_SERIES_COLORS.GRAPE,
|
||||
},
|
||||
{
|
||||
name: 'S1020 - fixed',
|
||||
query: 'if :[_.], ok := :[i.].(:[T]); ok {:[body]} patternType:structural archived:no',
|
||||
stroke: DATA_SERIES_COLORS.GREEN,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
const GO_STATIC_CHECK_S1023: Template = {
|
||||
type: InsightType.SearchBased,
|
||||
title: '[quickfix] - Omit redundant control flow',
|
||||
description: 'Code search turned code checker',
|
||||
templateValues: {
|
||||
title: '[quickfix] - Omit redundant control flow',
|
||||
allRepos: true,
|
||||
series: [
|
||||
{
|
||||
name: 'S1023',
|
||||
query:
|
||||
'func() {:[body] return } or func :[fn.](:[args]) {:[body] return } patternType:structural archived:no',
|
||||
stroke: DATA_SERIES_COLORS.GRAPE,
|
||||
},
|
||||
{
|
||||
name: 'S1023 - fixed',
|
||||
query: 'func() {:[body]} or func :[fn.](:[args]) {:[body]} patternType:structural archived:no',
|
||||
stroke: DATA_SERIES_COLORS.GREEN,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
const GO_STATIC_CHECK_S1024: Template = {
|
||||
type: InsightType.SearchBased,
|
||||
title: '[quickfix] - Replace x.Sub(time.Now()) with time.Until(x)',
|
||||
description: 'Code search turned code checker',
|
||||
templateValues: {
|
||||
title: '[quickfix] - Replace x.Sub(time.Now()) with time.Until(x)',
|
||||
allRepos: true,
|
||||
series: [
|
||||
{
|
||||
name: 'S1024',
|
||||
query: ':[x.].Sub(time.Now()) patternType:structural archived:no',
|
||||
stroke: DATA_SERIES_COLORS.GRAPE,
|
||||
},
|
||||
{
|
||||
name: 'S1024 - fixed',
|
||||
query: 'func() {:[body]} or func :[fn.](:[args]) {:[body]} patternType:structural archived:no',
|
||||
stroke: DATA_SERIES_COLORS.GREEN,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
const GO_STATIC_CHECK_S1025: Template = {
|
||||
type: InsightType.SearchBased,
|
||||
title: '[quickfix] - Don’t use fmt.Sprintf("%s", x) unnecessarily',
|
||||
description: 'Code search turned code checker',
|
||||
templateValues: {
|
||||
title: '[quickfix] - Don’t use fmt.Sprintf("%s", x) unnecessarily',
|
||||
allRepos: true,
|
||||
series: [
|
||||
{
|
||||
name: 'S1025',
|
||||
query: 'fmt.Println("%s", ":[s]") patternType:structural archived:no',
|
||||
stroke: DATA_SERIES_COLORS.GRAPE,
|
||||
},
|
||||
{
|
||||
name: 'S1025 - fixed',
|
||||
query: 'fmt.Println(":[s]") patternType:structural archived:no',
|
||||
stroke: DATA_SERIES_COLORS.GREEN,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
const GO_STATIC_CHECK_S1028: Template = {
|
||||
type: InsightType.SearchBased,
|
||||
title: '[quickfix] - Simplify error construction with fmt.Errorf',
|
||||
description: 'Code search turned code checker',
|
||||
templateValues: {
|
||||
title: '[quickfix] - Simplify error construction with fmt.Errorf',
|
||||
allRepos: true,
|
||||
series: [
|
||||
{
|
||||
name: 'S1028',
|
||||
query: 'errors.New(fmt.Sprintf(:[1])) patternType:structural archived:no',
|
||||
stroke: DATA_SERIES_COLORS.GRAPE,
|
||||
},
|
||||
{
|
||||
name: 'S1028 - fixed',
|
||||
query: 'fmt.Errorf(:[1]) patternType:structural archived:no',
|
||||
stroke: DATA_SERIES_COLORS.GREEN,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
const GO_STATIC_CHECK_S1029: Template = {
|
||||
type: InsightType.SearchBased,
|
||||
title: '[quickfix] - Range over the string directly',
|
||||
description: 'Code search turned code checker',
|
||||
templateValues: {
|
||||
title: '[quickfix] - Range over the string directly',
|
||||
allRepos: true,
|
||||
series: [
|
||||
{
|
||||
name: 'S1029',
|
||||
query: 'for :[~_], :[r.] := range []rune(:[s.]) patternType:structural archived:no',
|
||||
stroke: DATA_SERIES_COLORS.GRAPE,
|
||||
},
|
||||
{
|
||||
name: 'S1029 - fixed',
|
||||
query: 'for _, :[r] := range :[s] patternType:structural archived:no',
|
||||
stroke: DATA_SERIES_COLORS.GREEN,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
const GO_STATIC_CHECK_S1032: Template = {
|
||||
type: InsightType.SearchBased,
|
||||
title: '[quickfix] - Use sort.Ints(x), sort.Float64s(x), and sort.Strings(x)',
|
||||
description: 'Code search turned code checker',
|
||||
templateValues: {
|
||||
title: '[quickfix] - Use sort.Ints(x), sort.Float64s(x), and sort.Strings(x)',
|
||||
allRepos: true,
|
||||
series: [
|
||||
{
|
||||
name: 'S1032',
|
||||
query:
|
||||
'sort.Float64s(:[1]) or sort.Strings(:[1]) or sort.Ints(:[1]) patternType:structural archived:no',
|
||||
stroke: DATA_SERIES_COLORS.GRAPE,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
const GO_STATIC_CHECK_S1035: Template = {
|
||||
type: InsightType.SearchBased,
|
||||
title: '[quickfix] - Redundant call to net/http.CanonicalHeaderKey in method call on net/http.Header',
|
||||
description: 'Code search turned code checker',
|
||||
templateValues: {
|
||||
title: '[quickfix] - Redundant call to net/http.CanonicalHeaderKey in method call on net/http.Header',
|
||||
allRepos: true,
|
||||
series: [
|
||||
{
|
||||
name: 'S1035',
|
||||
query:
|
||||
'headers.Set(http.CanonicalHeaderKey(:[1])) or headers.Get(http.CanonicalHeaderKey(:[1])) or headers.Del(http.CanonicalHeaderKey(:[1])) or headers.Add(http.CanonicalHeaderKey(:[1]), :[1]) patternType:structural archived:no',
|
||||
stroke: DATA_SERIES_COLORS.GRAPE,
|
||||
},
|
||||
{
|
||||
name: 'S1035 - fixed',
|
||||
query:
|
||||
'headers.Set(:[1]) or headers.Get(:[1]) or headers.Del(:[1]) or headers.Add(:[1], :[1]) patternType:structural archived:no',
|
||||
stroke: DATA_SERIES_COLORS.GREEN,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
// const GO_STATIC_CHECK_S1036: skipped
|
||||
|
||||
const GO_STATIC_CHECK_S1037: Template = {
|
||||
type: InsightType.SearchBased,
|
||||
title: '[quickfix] - Redundant call to net/http.CanonicalHeaderKey in method call on net/http.Header',
|
||||
description: 'Code search turned code checker',
|
||||
templateValues: {
|
||||
title: '[quickfix] - Redundant call to net/http.CanonicalHeaderKey in method call on net/http.Header',
|
||||
allRepos: true,
|
||||
series: [
|
||||
{
|
||||
name: 'S1035',
|
||||
query:
|
||||
'headers.Set(http.CanonicalHeaderKey(:[1])) or headers.Get(http.CanonicalHeaderKey(:[1])) or headers.Del(http.CanonicalHeaderKey(:[1])) or headers.Add(http.CanonicalHeaderKey(:[1]), :[1]) patternType:structural archived:no',
|
||||
stroke: DATA_SERIES_COLORS.GRAPE,
|
||||
},
|
||||
{
|
||||
name: 'S1037 - fixed',
|
||||
query: 'time.Sleep(:[t]) patternType:structural archived:no',
|
||||
stroke: DATA_SERIES_COLORS.GREEN,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
const GO_STATIC_CHECK_S1038: Template = {
|
||||
type: InsightType.SearchBased,
|
||||
title: '[quickfix] - Unnecessarily complex way of printing formatted string',
|
||||
description: 'Code search turned code checker',
|
||||
templateValues: {
|
||||
title: '[quickfix] - Unnecessarily complex way of printing formatted string',
|
||||
allRepos: true,
|
||||
series: [
|
||||
{
|
||||
name: 'S1038',
|
||||
query: 'select { case <-time.After(:[t]):} patternType:structural archived:no',
|
||||
stroke: DATA_SERIES_COLORS.GRAPE,
|
||||
},
|
||||
{
|
||||
name: 'S1038 - fixed',
|
||||
query: 'time.Sleep(:[t]) patternType:structural archived:no',
|
||||
stroke: DATA_SERIES_COLORS.GREEN,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
const GO_STATIC_CHECK_S1039: Template = {
|
||||
type: InsightType.SearchBased,
|
||||
title: '[quickfix] - Unnecessary use of fmt.Sprint',
|
||||
description: 'Code search turned code checker',
|
||||
templateValues: {
|
||||
title: '[quickfix] Unnecessary use of fmt.Sprint',
|
||||
allRepos: true,
|
||||
series: [
|
||||
{
|
||||
name: 'S1039',
|
||||
query: 'fmt.Sprintf("%s", ":[s]") patternType:structural archived:no',
|
||||
stroke: DATA_SERIES_COLORS.GRAPE,
|
||||
},
|
||||
{
|
||||
name: 'S1025 - fixed',
|
||||
query: '":[s]" patternType:structural archived:no',
|
||||
stroke: DATA_SERIES_COLORS.GREEN,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
export const getTemplateSections = (props: SettingsCascadeProps<Settings>): TemplateSection[] => {
|
||||
const allButGoChecker: TemplateSection[] = [
|
||||
{
|
||||
title: 'Popular',
|
||||
templates: [
|
||||
TERRAFORM_VERSIONS,
|
||||
CSS_MODULES_MIGRATION,
|
||||
LOG4J_FIXED_VERSIONS,
|
||||
YARN_ADOPTION,
|
||||
JAVA_VERSIONS,
|
||||
LINTER_OVERRIDE_RULES,
|
||||
TS_JS_USAGE,
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Migration',
|
||||
templates: [
|
||||
CONFIG_OR_DOC_FILE,
|
||||
ALLOW_DENY_LIST_TRACKING,
|
||||
CSS_MODULES_MIGRATION,
|
||||
PYTHON_2_3,
|
||||
REACT_FUNCTION_CLASS,
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Adoption',
|
||||
templates: [
|
||||
NEW_API_USAGE,
|
||||
YARN_ADOPTION,
|
||||
FREQUENTLY_USED_DATABASE,
|
||||
LARGE_PACKAGE_USAGE,
|
||||
REACT_COMPONENT_LIB_USAGE,
|
||||
CI_TOOLING,
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Deprecation',
|
||||
templates: [
|
||||
CSS_CLASS,
|
||||
ICON_OR_IMAGE,
|
||||
STRUCTURAL_CODE_PATTERN,
|
||||
TOOLING_MIGRATION,
|
||||
VAR_KEYWORDS,
|
||||
TESTING_LIBRARIES,
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Versions and patterns',
|
||||
templates: [
|
||||
JAVA_VERSIONS,
|
||||
LICENSE_TYPES,
|
||||
ALL_LOG4J_VERSIONS,
|
||||
PYTHON_VERSIONS,
|
||||
NODEJS_VERSIONS,
|
||||
CSS_COLORS,
|
||||
CHECKOV_SKIP_TYPES,
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Code health',
|
||||
templates: [
|
||||
TODOS,
|
||||
LINTER_OVERRIDE_RULES,
|
||||
REVERT_COMMITS,
|
||||
DEPRECATED_CALLS,
|
||||
STORYBOOK_TESTS,
|
||||
REPOS_WITH_README,
|
||||
OWNERSHIP_TRACKING,
|
||||
CI_TOOLING,
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Security',
|
||||
templates: [
|
||||
VULNERABLE_OPEN_SOURCE,
|
||||
API_KEYS_DETECTION,
|
||||
LOG4J_FIXED_VERSIONS,
|
||||
SKIPPED_TESTS,
|
||||
TEST_AMOUNT_AND_TYPES,
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Other',
|
||||
templates: [TS_VS_GO, IOS_APP_SCREENS, ADOPTING_NEW_API, PROBLEMATIC_API_BY_TEAM, DATA_FETCHING_GQL],
|
||||
},
|
||||
]
|
||||
if (
|
||||
props.settingsCascade.final !== null &&
|
||||
!isErrorLike(props.settingsCascade.final) &&
|
||||
!props.settingsCascade.final.experimentalFeatures?.goCodeCheckerTemplates
|
||||
) {
|
||||
return allButGoChecker
|
||||
}
|
||||
const all = [...allButGoChecker]
|
||||
all.splice(-1, 0, {
|
||||
title: 'Go code checker',
|
||||
experimental: true,
|
||||
templates: [
|
||||
GO_STATIC_CHECK_SA6005,
|
||||
GO_STATIC_CHECK_S1002,
|
||||
GO_STATIC_CHECK_S1003,
|
||||
GO_STATIC_CHECK_S1004,
|
||||
GO_STATIC_CHECK_S1005,
|
||||
GO_STATIC_CHECK_S1006,
|
||||
GO_STATIC_CHECK_S1010,
|
||||
GO_STATIC_CHECK_S1012,
|
||||
GO_STATIC_CHECK_S1019,
|
||||
GO_STATIC_CHECK_S1020,
|
||||
GO_STATIC_CHECK_S1023,
|
||||
GO_STATIC_CHECK_S1024,
|
||||
GO_STATIC_CHECK_S1025,
|
||||
GO_STATIC_CHECK_S1028,
|
||||
GO_STATIC_CHECK_S1029,
|
||||
GO_STATIC_CHECK_S1032,
|
||||
GO_STATIC_CHECK_S1035,
|
||||
GO_STATIC_CHECK_S1037,
|
||||
GO_STATIC_CHECK_S1038,
|
||||
GO_STATIC_CHECK_S1039,
|
||||
],
|
||||
})
|
||||
return all
|
||||
}
|
||||
|
||||
@ -1693,6 +1693,8 @@ type SettingsExperimentalFeatures struct {
|
||||
FuzzyFinder *bool `json:"fuzzyFinder,omitempty"`
|
||||
// FuzzyFinderCaseInsensitiveFileCountThreshold description: The maximum number of files a repo can have to use case-insensitive fuzzy finding
|
||||
FuzzyFinderCaseInsensitiveFileCountThreshold *float64 `json:"fuzzyFinderCaseInsensitiveFileCountThreshold,omitempty"`
|
||||
// GoCodeCheckerTemplates description: Shows a panel with code insights templates for go code checker results.
|
||||
GoCodeCheckerTemplates *bool `json:"goCodeCheckerTemplates,omitempty"`
|
||||
// HomepageUserInvitation description: Shows a panel to invite collaborators to Sourcegraph on home page.
|
||||
HomepageUserInvitation *bool `json:"homepageUserInvitation,omitempty"`
|
||||
// SearchContextsQuery description: DEPRECATED: This feature is now permanently enabled. Enables query based search contexts
|
||||
|
||||
@ -302,6 +302,14 @@
|
||||
"!go": {
|
||||
"pointer": true
|
||||
}
|
||||
},
|
||||
"goCodeCheckerTemplates": {
|
||||
"description": "Shows a panel with code insights templates for go code checker results.",
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"!go": {
|
||||
"pointer": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"group": "Experimental"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user