aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Davis <jeremy.davis@sonarsource.com>2019-11-04 09:35:56 +0900
committerSonarTech <sonartech@sonarsource.com>2019-11-07 11:45:17 +0100
commitf1d6dd1b1b818717baf0f2cf8f3248f0aad3731b (patch)
tree15a52eeefd79a479f2c81475f315df6e9a865e21
parent35f2d76d8dba2fed8cc7476dc2e3c90227667bd7 (diff)
downloadsonarqube-f1d6dd1b1b818717baf0f2cf8f3248f0aad3731b.tar.gz
sonarqube-f1d6dd1b1b818717baf0f2cf8f3248f0aad3731b.zip
SONAR-12050 show issues' locations marker in CodeViewer
-rw-r--r--server/sonar-web/src/main/js/apps/issues/components/IssuesSourceViewer.tsx2
-rw-r--r--server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/IssuesSourceViewer-test.tsx.snap2
-rw-r--r--server/sonar-web/src/main/js/components/SourceViewer/SourceViewerBase.tsx6
-rw-r--r--server/sonar-web/src/main/js/components/SourceViewer/SourceViewerCode.tsx4
-rw-r--r--server/sonar-web/src/main/js/components/SourceViewer/__tests__/__snapshots__/SourceViewerBase-test.tsx.snap2
-rw-r--r--server/sonar-web/src/main/js/components/SourceViewer/components/Line.tsx4
-rw-r--r--server/sonar-web/src/main/js/components/SourceViewer/components/LineCode.tsx4
-rw-r--r--server/sonar-web/src/main/js/components/SourceViewer/components/LineIssuesList.tsx4
-rw-r--r--server/sonar-web/src/main/js/components/issue/Issue.css2
-rw-r--r--server/sonar-web/src/main/js/components/issue/Issue.tsx4
-rw-r--r--server/sonar-web/src/main/js/components/issue/IssueView.tsx4
-rw-r--r--server/sonar-web/src/main/js/components/issue/components/IssueTitleBar.tsx34
-rw-r--r--server/sonar-web/src/main/js/components/issue/components/__tests__/IssueTitleBar-test.tsx12
-rw-r--r--server/sonar-web/src/main/js/components/issue/components/__tests__/__snapshots__/IssueTitleBar-test.tsx.snap6
14 files changed, 88 insertions, 2 deletions
diff --git a/server/sonar-web/src/main/js/apps/issues/components/IssuesSourceViewer.tsx b/server/sonar-web/src/main/js/apps/issues/components/IssuesSourceViewer.tsx
index 81f3f2621bc..91786a16985 100644
--- a/server/sonar-web/src/main/js/apps/issues/components/IssuesSourceViewer.tsx
+++ b/server/sonar-web/src/main/js/apps/issues/components/IssuesSourceViewer.tsx
@@ -134,6 +134,8 @@ export default class IssuesSourceViewer extends React.PureComponent<Props> {
branchLike={this.props.branchLike}
component={component}
displayAllIssues={true}
+ displayIssueLocationsCount={true}
+ displayIssueLocationsLink={false}
displayLocationMarkers={!allMessagesEmpty}
highlightedLocationMessage={highlightedLocationMessage}
highlightedLocations={highlightedLocations}
diff --git a/server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/IssuesSourceViewer-test.tsx.snap b/server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/IssuesSourceViewer-test.tsx.snap
index 416ec4a47fd..723c6c1aa3c 100644
--- a/server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/IssuesSourceViewer-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/IssuesSourceViewer-test.tsx.snap
@@ -279,6 +279,8 @@ exports[`should render SourceViewer correctly 1`] = `
}
component="main.js"
displayAllIssues={true}
+ displayIssueLocationsCount={true}
+ displayIssueLocationsLink={false}
displayLocationMarkers={false}
highlightedLocations={Array []}
loadIssues={[MockFunction]}
diff --git a/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerBase.tsx b/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerBase.tsx
index da2db7965d4..22b82d5f11a 100644
--- a/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerBase.tsx
+++ b/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerBase.tsx
@@ -57,6 +57,8 @@ export interface Props {
branchLike: T.BranchLike | undefined;
component: string;
displayAllIssues?: boolean;
+ displayIssueLocationsCount?: boolean;
+ displayIssueLocationsLink?: boolean;
displayLocationMarkers?: boolean;
highlightedLine?: number;
// `undefined` elements mean they are located in a different file,
@@ -123,6 +125,8 @@ export default class SourceViewerBase extends React.PureComponent<Props, State>
static defaultProps = {
displayAllIssues: false,
+ displayIssueLocationsCount: true,
+ displayIssueLocationsLink: true,
displayLocationMarkers: true,
loadComponent: defaultLoadComponent,
loadIssues: defaultLoadIssues,
@@ -612,6 +616,8 @@ export default class SourceViewerBase extends React.PureComponent<Props, State>
branchLike={this.props.branchLike}
componentKey={this.props.component}
displayAllIssues={this.props.displayAllIssues}
+ displayIssueLocationsCount={this.props.displayIssueLocationsCount}
+ displayIssueLocationsLink={this.props.displayIssueLocationsLink}
displayLocationMarkers={this.props.displayLocationMarkers}
duplications={this.state.duplications}
duplicationsByLine={this.state.duplicationsByLine}
diff --git a/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerCode.tsx b/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerCode.tsx
index 075a44be474..d6c8104533e 100644
--- a/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerCode.tsx
+++ b/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerCode.tsx
@@ -41,6 +41,8 @@ interface Props {
branchLike: T.BranchLike | undefined;
componentKey: string;
displayAllIssues?: boolean;
+ displayIssueLocationsCount?: boolean;
+ displayIssueLocationsLink?: boolean;
displayLocationMarkers?: boolean;
duplications: T.Duplication[] | undefined;
duplicationsByLine: { [line: number]: number[] };
@@ -119,6 +121,8 @@ export default class SourceViewerCode extends React.PureComponent<Props> {
displayAllIssues={this.props.displayAllIssues}
displayCoverage={displayCoverage}
displayDuplications={displayDuplications}
+ displayIssueLocationsCount={this.props.displayIssueLocationsCount}
+ displayIssueLocationsLink={this.props.displayIssueLocationsLink}
displayIssues={displayIssues}
displayLocationMarkers={this.props.displayLocationMarkers}
duplications={this.getDuplicationsForLine(line)}
diff --git a/server/sonar-web/src/main/js/components/SourceViewer/__tests__/__snapshots__/SourceViewerBase-test.tsx.snap b/server/sonar-web/src/main/js/components/SourceViewer/__tests__/__snapshots__/SourceViewerBase-test.tsx.snap
index 66538d4b69b..91750341a24 100644
--- a/server/sonar-web/src/main/js/components/SourceViewer/__tests__/__snapshots__/SourceViewerBase-test.tsx.snap
+++ b/server/sonar-web/src/main/js/components/SourceViewer/__tests__/__snapshots__/SourceViewerBase-test.tsx.snap
@@ -11,6 +11,8 @@ exports[`should render correctly 1`] = `
}
component="my-component"
displayAllIssues={false}
+ displayIssueLocationsCount={true}
+ displayIssueLocationsLink={true}
displayLocationMarkers={true}
loadComponent={[Function]}
loadIssues={[Function]}
diff --git a/server/sonar-web/src/main/js/components/SourceViewer/components/Line.tsx b/server/sonar-web/src/main/js/components/SourceViewer/components/Line.tsx
index cc86553eeb5..793c1384180 100644
--- a/server/sonar-web/src/main/js/components/SourceViewer/components/Line.tsx
+++ b/server/sonar-web/src/main/js/components/SourceViewer/components/Line.tsx
@@ -34,6 +34,8 @@ interface Props {
displayAllIssues?: boolean;
displayCoverage: boolean;
displayDuplications: boolean;
+ displayIssueLocationsCount?: boolean;
+ displayIssueLocationsLink?: boolean;
displayIssues: boolean;
displayLocationMarkers?: boolean;
duplications: number[];
@@ -153,6 +155,8 @@ export default class Line extends React.PureComponent<Props> {
<LineCode
branchLike={this.props.branchLike}
+ displayIssueLocationsCount={this.props.displayIssueLocationsCount}
+ displayIssueLocationsLink={this.props.displayIssueLocationsLink}
displayLocationMarkers={this.props.displayLocationMarkers}
highlightedLocationMessage={this.props.highlightedLocationMessage}
highlightedSymbols={this.props.highlightedSymbols}
diff --git a/server/sonar-web/src/main/js/components/SourceViewer/components/LineCode.tsx b/server/sonar-web/src/main/js/components/SourceViewer/components/LineCode.tsx
index 14ea6fc4f78..d80f2e8706b 100644
--- a/server/sonar-web/src/main/js/components/SourceViewer/components/LineCode.tsx
+++ b/server/sonar-web/src/main/js/components/SourceViewer/components/LineCode.tsx
@@ -31,6 +31,8 @@ import LineIssuesList from './LineIssuesList';
interface Props {
branchLike: T.BranchLike | undefined;
+ displayIssueLocationsCount?: boolean;
+ displayIssueLocationsLink?: boolean;
displayLocationMarkers?: boolean;
highlightedLocationMessage: { index: number; text: string | undefined } | undefined;
highlightedSymbols: string[] | undefined;
@@ -228,6 +230,8 @@ export default class LineCode extends React.PureComponent<Props, State> {
{showIssues && issues.length > 0 && (
<LineIssuesList
branchLike={this.props.branchLike}
+ displayIssueLocationsCount={this.props.displayIssueLocationsCount}
+ displayIssueLocationsLink={this.props.displayIssueLocationsLink}
issuePopup={this.props.issuePopup}
issues={issues}
onIssueChange={this.props.onIssueChange}
diff --git a/server/sonar-web/src/main/js/components/SourceViewer/components/LineIssuesList.tsx b/server/sonar-web/src/main/js/components/SourceViewer/components/LineIssuesList.tsx
index bd9df8ed497..f64da90def8 100644
--- a/server/sonar-web/src/main/js/components/SourceViewer/components/LineIssuesList.tsx
+++ b/server/sonar-web/src/main/js/components/SourceViewer/components/LineIssuesList.tsx
@@ -22,6 +22,8 @@ import Issue from '../../issue/Issue';
interface Props {
branchLike: T.BranchLike | undefined;
+ displayIssueLocationsCount?: boolean;
+ displayIssueLocationsLink?: boolean;
issuePopup: { issue: string; name: string } | undefined;
issues: T.Issue[];
onIssueChange: (issue: T.Issue) => void;
@@ -38,6 +40,8 @@ export default function LineIssuesList(props: Props) {
{props.issues.map(issue => (
<Issue
branchLike={props.branchLike}
+ displayLocationsCount={props.displayIssueLocationsCount}
+ displayLocationsLink={props.displayIssueLocationsLink}
issue={issue}
key={issue.key}
onChange={props.onIssueChange}
diff --git a/server/sonar-web/src/main/js/components/issue/Issue.css b/server/sonar-web/src/main/js/components/issue/Issue.css
index 06861fd5599..fa3824fa2df 100644
--- a/server/sonar-web/src/main/js/components/issue/Issue.css
+++ b/server/sonar-web/src/main/js/components/issue/Issue.css
@@ -214,7 +214,7 @@
}
.issue:not(.selected) .location-index {
- background-color: var(--gray80);
+ background-color: var(--gray60);
}
.issue .menu:not(.issues-similar-issues-menu):not(.issue-changelog) {
diff --git a/server/sonar-web/src/main/js/components/issue/Issue.tsx b/server/sonar-web/src/main/js/components/issue/Issue.tsx
index 54721655405..6bfaffd7c17 100644
--- a/server/sonar-web/src/main/js/components/issue/Issue.tsx
+++ b/server/sonar-web/src/main/js/components/issue/Issue.tsx
@@ -27,6 +27,8 @@ import IssueView from './IssueView';
interface Props {
branchLike?: T.BranchLike;
checked?: boolean;
+ displayLocationsCount?: boolean;
+ displayLocationsLink?: boolean;
issue: T.Issue;
onChange: (issue: T.Issue) => void;
onCheck?: (issue: string) => void;
@@ -130,6 +132,8 @@ export default class Issue extends React.PureComponent<Props> {
branchLike={this.props.branchLike}
checked={this.props.checked}
currentPopup={this.props.openPopup}
+ displayLocationsCount={this.props.displayLocationsCount}
+ displayLocationsLink={this.props.displayLocationsLink}
issue={this.props.issue}
onAssign={this.handleAssignement}
onChange={this.props.onChange}
diff --git a/server/sonar-web/src/main/js/components/issue/IssueView.tsx b/server/sonar-web/src/main/js/components/issue/IssueView.tsx
index d78f5df9e1c..19fd1bea80a 100644
--- a/server/sonar-web/src/main/js/components/issue/IssueView.tsx
+++ b/server/sonar-web/src/main/js/components/issue/IssueView.tsx
@@ -30,6 +30,8 @@ interface Props {
branchLike?: T.BranchLike;
checked?: boolean;
currentPopup?: string;
+ displayLocationsCount?: boolean;
+ displayLocationsLink?: boolean;
issue: T.Issue;
onAssign: (login: string) => void;
onChange: (issue: T.Issue) => void;
@@ -83,6 +85,8 @@ export default class IssueView extends React.PureComponent<Props> {
<IssueTitleBar
branchLike={this.props.branchLike}
currentPopup={this.props.currentPopup}
+ displayLocationsCount={this.props.displayLocationsCount}
+ displayLocationsLink={this.props.displayLocationsLink}
issue={issue}
onFilter={this.props.onFilter}
togglePopup={this.props.togglePopup}
diff --git a/server/sonar-web/src/main/js/components/issue/components/IssueTitleBar.tsx b/server/sonar-web/src/main/js/components/issue/components/IssueTitleBar.tsx
index 2345b65c512..7b52bd5979c 100644
--- a/server/sonar-web/src/main/js/components/issue/components/IssueTitleBar.tsx
+++ b/server/sonar-web/src/main/js/components/issue/components/IssueTitleBar.tsx
@@ -19,10 +19,13 @@
*/
import * as React from 'react';
import { Link } from 'react-router';
+import Tooltip from 'sonar-ui-common/components/controls/Tooltip';
import LinkIcon from 'sonar-ui-common/components/icons/LinkIcon';
-import { translate } from 'sonar-ui-common/helpers/l10n';
+import { translate, translateWithParameters } from 'sonar-ui-common/helpers/l10n';
+import { formatMeasure } from 'sonar-ui-common/helpers/measures';
import { getBranchLikeQuery } from '../../../helpers/branches';
import { getComponentIssuesUrl } from '../../../helpers/urls';
+import LocationIndex from '../../common/LocationIndex';
import { WorkspaceContext } from '../../workspace/context';
import IssueChangelog from './IssueChangelog';
import IssueMessage from './IssueMessage';
@@ -31,6 +34,8 @@ import SimilarIssuesFilter from './SimilarIssuesFilter';
interface Props {
branchLike?: T.BranchLike;
currentPopup?: string;
+ displayLocationsCount?: boolean;
+ displayLocationsLink?: boolean;
issue: T.Issue;
onFilter?: (property: string, issue: T.Issue) => void;
togglePopup: (popup: string, show?: boolean) => void;
@@ -40,6 +45,22 @@ export default function IssueTitleBar(props: Props) {
const { issue } = props;
const hasSimilarIssuesFilter = props.onFilter != null;
+ const locationsCount =
+ issue.secondaryLocations.length +
+ issue.flows.reduce((sum, locations) => sum + locations.length, 0);
+
+ const locationsBadge = (
+ <Tooltip
+ overlay={translateWithParameters(
+ 'issue.this_issue_involves_x_code_locations',
+ formatMeasure(locationsCount, 'INT')
+ )}>
+ <LocationIndex>{locationsCount}</LocationIndex>
+ </Tooltip>
+ );
+
+ const displayLocations = props.displayLocationsCount && locationsCount > 0;
+
const issueUrl = getComponentIssuesUrl(issue.project, {
...getBranchLikeQuery(props.branchLike),
issues: issue.key,
@@ -79,6 +100,17 @@ export default function IssueTitleBar(props: Props) {
</span>
</li>
)}
+ {displayLocations && (
+ <li className="issue-meta">
+ {props.displayLocationsLink ? (
+ <Link target="_blank" to={issueUrl}>
+ {locationsBadge}
+ </Link>
+ ) : (
+ locationsBadge
+ )}
+ </li>
+ )}
<li className="issue-meta">
<Link
className="js-issue-permalink link-no-underline"
diff --git a/server/sonar-web/src/main/js/components/issue/components/__tests__/IssueTitleBar-test.tsx b/server/sonar-web/src/main/js/components/issue/components/__tests__/IssueTitleBar-test.tsx
index 0f7dcd76eb4..665a17f8a5e 100644
--- a/server/sonar-web/src/main/js/components/issue/components/__tests__/IssueTitleBar-test.tsx
+++ b/server/sonar-web/src/main/js/components/issue/components/__tests__/IssueTitleBar-test.tsx
@@ -23,6 +23,7 @@ import { mockIssue } from '../../../../helpers/testMocks';
import IssueTitleBar from '../IssueTitleBar';
const issue: T.Issue = mockIssue();
+const issueWithLocations: T.Issue = mockIssue(true);
it('should render the titlebar correctly', () => {
const branch: T.ShortLivingBranch = {
@@ -44,6 +45,17 @@ it('should render the titlebar with the filter', () => {
expect(element).toMatchSnapshot();
});
+it('should count all code locations', () => {
+ const element = shallow(
+ <IssueTitleBar
+ displayLocationsCount={true}
+ issue={issueWithLocations}
+ togglePopup={jest.fn()}
+ />
+ );
+ expect(element.find('LocationIndex')).toMatchSnapshot();
+});
+
it('should have a correct permalink for security hotspots', () => {
const wrapper = shallow(
<IssueTitleBar issue={{ ...issue, type: 'SECURITY_HOTSPOT' }} togglePopup={jest.fn()} />
diff --git a/server/sonar-web/src/main/js/components/issue/components/__tests__/__snapshots__/IssueTitleBar-test.tsx.snap b/server/sonar-web/src/main/js/components/issue/components/__tests__/__snapshots__/IssueTitleBar-test.tsx.snap
index 812027acb3b..3fc0b16bfe3 100644
--- a/server/sonar-web/src/main/js/components/issue/components/__tests__/__snapshots__/IssueTitleBar-test.tsx.snap
+++ b/server/sonar-web/src/main/js/components/issue/components/__tests__/__snapshots__/IssueTitleBar-test.tsx.snap
@@ -1,5 +1,11 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
+exports[`should count all code locations 1`] = `
+<LocationIndex>
+ 7
+</LocationIndex>
+`;
+
exports[`should render the titlebar correctly 1`] = `
<div
className="issue-row"