-
Notifications
You must be signed in to change notification settings - Fork 16
/
ReviewResult.ts
139 lines (115 loc) · 3.61 KB
/
ReviewResult.ts
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import { HandlerResult } from "../../HandlerResult";
import { RepoRef } from "../common/RepoId";
import { SourceLocation } from "../common/SourceLocation";
export type Severity = "error" | "warn" | "info";
/**
* A single comment on a project, with optional source location.
*/
export interface ReviewComment {
readonly severity: Severity;
/**
* Name of the category to which this comment applies: E.g. "API usage".
* Should be human readable. Review comments are typically filtered by
* category when reported.
*/
readonly category: string;
/**
* Name of the more specific category to which this comment applies if available,
* E.g. "Usage of Foobar API". Review comments are typically sorted by
* subcategory when reported.
*/
readonly subcategory?: string;
/**
* Details of the problem
*/
readonly detail: string;
readonly sourceLocation?: SourceLocation;
/**
* Command invocation that will fix this problem
*/
readonly fix?: Fix;
}
/**
* Coordinates of an Atomist command handler to fix a specific problem
*/
export interface Fix {
command: string;
params: {
[propName: string]: string | number,
};
}
export class DefaultReviewComment implements ReviewComment {
constructor(public severity: Severity,
public category: string,
public detail: string,
public sourceLocation: SourceLocation,
public fix?: Fix) {
}
}
/**
* The result of reviewing a single project
*/
export interface ProjectReview {
repoId: RepoRef;
comments: ReviewComment[];
}
/**
* The result of reviewing many projects: For example,
* all the projects in an org
*/
export interface ReviewResult<T extends ProjectReview = ProjectReview> extends HandlerResult {
projectsReviewed: number;
projectReviews: T[];
}
/**
* Give a project a clean bill of health, with no comments
* @param repoId identification of project
* @return {{repoId: RepoRef, comments: Array}}
*/
export function clean(repoId: RepoRef): ProjectReview {
return {
repoId,
comments: [],
};
}
/**
* Function suitable for use by Array.prototype.sort() to sort review
* comments by severity, category, subcategory, and sourceLocation
* path and offset. Items with the same severity, category, and
* subcategory without a location are sorted before those having a
* location.
*
* @param a First element to compare.
* @param b Second element to compare.
* @return -1 if a sorts first, 1 if b sorts first, and 0 if they are equivalent.
*/
export function reviewCommentSorter(a: ReviewComment, b: ReviewComment): number {
if (a.severity !== b.severity) {
const severities = ["error", "warn", "info"];
for (const severity of severities) {
if (a.severity === severity) {
return -1;
} else if (b.severity === severity) {
return 1;
}
}
}
if (a.category !== b.category) {
return a.category.localeCompare(b.category);
}
if (a.subcategory !== b.subcategory) {
return a.subcategory.localeCompare(b.subcategory);
}
if (!a.sourceLocation && b.sourceLocation) {
return -1;
} else if (a.sourceLocation && !b.sourceLocation) {
return 1;
} else if (a.sourceLocation && b.sourceLocation) {
if (a.sourceLocation.path !== b.sourceLocation.path) {
return a.sourceLocation.path.localeCompare(b.sourceLocation.path);
} else {
return a.sourceLocation.offset - b.sourceLocation.offset;
}
}
return 0;
}