aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js/helpers/issues.js
blob: 3a1e509f790d98387249433890dd959cfded1c4a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/*
 * SonarQube
 * Copyright (C) 2009-2017 SonarSource SA
 * mailto:info AT sonarsource DOT com
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
// @flow
import sortBy from 'lodash/sortBy';
import { SEVERITIES } from './constants';

type TextRange = {
  startLine: number,
  endLine: number,
  startOffset: number,
  endOffset: number
};

type Comment = {
  login: string
};

type User = {
  login: string
};

type RawIssue = {
  assignee?: string,
  author: string,
  comments?: Array<Comment>,
  component: string,
  line?: number,
  project: string,
  rule: string,
  status: string,
  subProject?: string,
  textRange?: TextRange
};

export const sortBySeverity = (issues: Array<*>) => (
  sortBy(issues, issue => SEVERITIES.indexOf(issue.severity))
);

const injectRelational = (
  issue: RawIssue | Comment,
  source?: Array<*>,
  baseField: string,
  lookupField: string
) => {
  const newFields = {};
  const baseValue = issue[baseField];
  if (baseValue != null && source != null) {
    const lookupValue = source.find(candidate => candidate[lookupField] === baseValue);
    if (lookupValue != null) {
      Object.keys(lookupValue).forEach(key => {
        const newKey = baseField + key.charAt(0).toUpperCase() + key.slice(1);
        newFields[newKey] = lookupValue[key];
      });
    }
  }
  return newFields;
};

const injectCommentsRelational = (issue: RawIssue, users?: Array<User>) => {
  if (!issue.comments) {
    return {};
  }
  const comments = issue.comments.map(comment => ({
    ...comment,
    author: comment.login,
    login: undefined,
    ...injectRelational(comment, users, 'author', 'login')
  }));
  return { comments };
};

const prepareClosed = (issue: RawIssue) => {
  return issue.status === 'CLOSED' ? { flows: undefined } : {};
};

const ensureTextRange = (issue: RawIssue) => {
  return issue.line && !issue.textRange ? {
    textRange: {
      startLine: issue.line,
      endLine: issue.line,
      startOffset: 0,
      endOffset: 999999
    }
  } : {};
};

export const parseIssueFromResponse = (
  issue: RawIssue,
  components?: Array<*>,
  users?: Array<*>,
  rules?: Array<*>
) => {
  return {
    ...issue,
    ...injectRelational(issue, components, 'component', 'key'),
    ...injectRelational(issue, components, 'project', 'key'),
    ...injectRelational(issue, components, 'subProject', 'key'),
    ...injectRelational(issue, rules, 'rule', 'key'),
    ...injectRelational(issue, users, 'assignee', 'login'),
    ...injectCommentsRelational(issue, users),
    ...prepareClosed(issue),
    ...ensureTextRange(issue)
  };
};