* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
+import { FormattedMessage } from 'react-intl';
import { ButtonLink } from '../../../components/controls/buttons';
import Tooltip from '../../../components/controls/Tooltip';
import { translate, translateWithParameters } from '../../../helpers/l10n';
import { RuleStatus } from '../../../types/rules';
import DocumentationTooltip from '../../common/DocumentationTooltip';
+import SonarLintIcon from '../../icons/SonarLintIcon';
import { WorkspaceContextShape } from '../../workspace/context';
export interface IssueMessageProps {
engine?: string;
engineName?: string;
+ quickFixAvailable?: boolean;
manualVulnerability: boolean;
message: string;
onOpenRule: WorkspaceContextShape['openRule'];
}
export default function IssueMessage(props: IssueMessageProps) {
- const { engine, engineName, manualVulnerability, message, ruleKey, ruleStatus } = props;
+ const {
+ engine,
+ engineName,
+ quickFixAvailable,
+ manualVulnerability,
+ message,
+ ruleKey,
+ ruleStatus
+ } = props;
const ruleEngine = engineName ? engineName : engine;
return (
- <div className="issue-message break-word">
+ <div className="display-inline-flex-center issue-message break-word">
<span className="spacer-right">{message}</span>
+ {quickFixAvailable && (
+ <Tooltip
+ overlay={
+ <FormattedMessage
+ id="issue.quick_fix_available_with_sonarlint"
+ defaultMessage={translate('issue.quick_fix_available_with_sonarlint')}
+ values={{
+ link: (
+ <a
+ href="https://www.sonarqube.org/sonarlint/?referrer=sonarqube-quick-fix"
+ rel="noopener noreferrer"
+ target="_blank">
+ SonarLint
+ </a>
+ )
+ }}
+ />
+ }
+ mouseLeaveDelay={0.5}>
+ <SonarLintIcon className="spacer-right" size={15} />
+ </Tooltip>
+ )}
<ButtonLink
aria-label={translate('issue.why_this_issue.long')}
className="issue-see-rule spacer-right text-baseline"
}>
{translate('issue.why_this_issue')}
</ButtonLink>
-
{ruleStatus && (ruleStatus === RuleStatus.Deprecated || ruleStatus === RuleStatus.Removed) && (
<DocumentationTooltip
className="spacer-left"
</span>
</DocumentationTooltip>
)}
-
{ruleEngine && (
<Tooltip overlay={translateWithParameters('issue.from_external_rule_engine', ruleEngine)}>
<div className="badge spacer-right text-baseline">{ruleEngine}</div>
externalRulesRepoNames &&
externalRulesRepoNames[issue.externalRuleEngine]
}
+ quickFixAvailable={issue.quickFixAvailable}
manualVulnerability={issue.fromHotspot && issue.type === 'VULNERABILITY'}
message={issue.message}
onOpenRule={openRule}
it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot('default');
expect(shallowRender({ engine: 'js' })).toMatchSnapshot('with engine info');
+ expect(shallowRender({ quickFixAvailable: true })).toMatchSnapshot('with quick fix');
expect(shallowRender({ engineName: 'JS' })).toMatchSnapshot('with engine name');
expect(shallowRender({ manualVulnerability: true })).toMatchSnapshot('is manual vulnerability');
expect(shallowRender({ ruleStatus: RuleStatus.Deprecated })).toMatchSnapshot(
exports[`should render correctly: default 1`] = `
<div
- className="issue-message break-word"
+ className="display-inline-flex-center issue-message break-word"
>
<span
className="spacer-right"
exports[`should render correctly: is deprecated rule 1`] = `
<div
- className="issue-message break-word"
+ className="display-inline-flex-center issue-message break-word"
>
<span
className="spacer-right"
exports[`should render correctly: is manual vulnerability 1`] = `
<div
- className="issue-message break-word"
+ className="display-inline-flex-center issue-message break-word"
>
<span
className="spacer-right"
exports[`should render correctly: is removed rule 1`] = `
<div
- className="issue-message break-word"
+ className="display-inline-flex-center issue-message break-word"
>
<span
className="spacer-right"
exports[`should render correctly: with engine info 1`] = `
<div
- className="issue-message break-word"
+ className="display-inline-flex-center issue-message break-word"
>
<span
className="spacer-right"
exports[`should render correctly: with engine name 1`] = `
<div
- className="issue-message break-word"
+ className="display-inline-flex-center issue-message break-word"
>
<span
className="spacer-right"
</Tooltip>
</div>
`;
+
+exports[`should render correctly: with quick fix 1`] = `
+<div
+ className="display-inline-flex-center issue-message break-word"
+>
+ <span
+ className="spacer-right"
+ >
+ Reduce the number of conditional operators (4) used in the expression
+ </span>
+ <Tooltip
+ mouseLeaveDelay={0.5}
+ overlay={
+ <FormattedMessage
+ defaultMessage="issue.quick_fix_available_with_sonarlint"
+ id="issue.quick_fix_available_with_sonarlint"
+ values={
+ Object {
+ "link": <a
+ href="https://www.sonarqube.org/sonarlint/?referrer=sonarqube-quick-fix"
+ rel="noopener noreferrer"
+ target="_blank"
+ >
+ SonarLint
+ </a>,
+ }
+ }
+ />
+ }
+ >
+ <SonarLintIcon
+ className="spacer-right"
+ size={15}
+ />
+ </Tooltip>
+ <ButtonLink
+ aria-label="issue.why_this_issue.long"
+ className="issue-see-rule spacer-right text-baseline"
+ onClick={[Function]}
+ >
+ issue.why_this_issue
+ </ButtonLink>
+</div>
+`;
effort?: string;
externalRuleEngine?: string;
fromExternalRule?: boolean;
+ quickFixAvailable?: boolean;
key: string;
flows: FlowLocation[][];
fromHotspot: boolean;
issue.assign.unassigned_click_to_assign=Unassigned, click to assign issue
issue.assign.formlink=Assign
issue.assign.to_me=to me
+issue.quick_fix_available_with_sonarlint=Quick fix available in {link}
issue.comment.add_comment=Add Comment
issue.comment.formlink=Comment
issue.comment.submit=Comment