Skip to content

Commit 322a768

Browse files
xFrednetflip1995
andcommitted
Adapting the lint list to Clippy's new metadata format
Changes included: - Minimum adaption to the new `lints.json` format - Fixing filtering for the new `lints.json` format; hardcoding the lint groups in the index - Recreating the original doc styling for the new format - Fixed sytax highlighting for rust,ignore code blocks - Fixed markdown table extraction in the metadata collector and fixed lint level output - Adding the additional information row for lints - Changed the website title to Clippy's lint list - Flexing the website for mobile users - Added (?) references for lint levels and groups - Making deprecated lints look dead - Removed JS code block language extraction in favor of a rust implementation `rust-clippy#7352` - Added the suspicious lint group to the lint list - Remove trailing whitespaces from index.html - Fix code highlighting - Use default value if the docVersion is empty Co-authored-by: Philipp Krones <[email protected]>
1 parent ac0fd99 commit 322a768

File tree

2 files changed

+172
-63
lines changed

2 files changed

+172
-63
lines changed

clippy_lints/src/utils/internal_lints/metadata_collector.rs

+26-10
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ const DEPRECATED_LINT_TYPE: [&str; 3] = ["clippy_lints", "deprecated_lints", "Cl
114114

115115
/// The index of the applicability name of `paths::APPLICABILITY_VALUES`
116116
const APPLICABILITY_NAME_INDEX: usize = 2;
117+
/// This applicability will be set for unresolved applicability values.
118+
const APPLICABILITY_UNRESOLVED_STR: &str = "Unresolved";
117119

118120
declare_clippy_lint! {
119121
/// **What it does:** Collects metadata about clippy lints for the website.
@@ -192,7 +194,7 @@ impl Drop for MetadataCollector {
192194
let mut lints = std::mem::take(&mut self.lints).into_sorted_vec();
193195
lints
194196
.iter_mut()
195-
.for_each(|x| x.applicability = applicability_info.remove(&x.id));
197+
.for_each(|x| x.applicability = Some(applicability_info.remove(&x.id).unwrap_or_default()));
196198

197199
// Outputting
198200
if Path::new(OUTPUT_FILE).exists() {
@@ -208,7 +210,7 @@ struct LintMetadata {
208210
id: String,
209211
id_span: SerializableSpan,
210212
group: String,
211-
level: &'static str,
213+
level: String,
212214
docs: String,
213215
/// This field is only used in the output and will only be
214216
/// mapped shortly before the actual output.
@@ -221,7 +223,7 @@ impl LintMetadata {
221223
id,
222224
id_span,
223225
group,
224-
level,
226+
level: level.to_string(),
225227
docs,
226228
applicability: None,
227229
}
@@ -269,14 +271,16 @@ impl Serialize for ApplicabilityInfo {
269271
where
270272
S: Serializer,
271273
{
272-
let index = self.applicability.unwrap_or_default();
273-
274274
let mut s = serializer.serialize_struct("ApplicabilityInfo", 2)?;
275275
s.serialize_field("is_multi_part_suggestion", &self.is_multi_part_suggestion)?;
276-
s.serialize_field(
277-
"applicability",
278-
&paths::APPLICABILITY_VALUES[index][APPLICABILITY_NAME_INDEX],
279-
)?;
276+
if let Some(index) = self.applicability {
277+
s.serialize_field(
278+
"applicability",
279+
&paths::APPLICABILITY_VALUES[index][APPLICABILITY_NAME_INDEX],
280+
)?;
281+
} else {
282+
s.serialize_field("applicability", APPLICABILITY_UNRESOLVED_STR)?;
283+
}
280284
s.end()
281285
}
282286
}
@@ -486,6 +490,13 @@ fn extract_attr_docs_or_lint(cx: &LateContext<'_>, item: &Item<'_>) -> Option<St
486490
/// ```
487491
///
488492
/// Would result in `Hello world!\n=^.^=\n`
493+
///
494+
/// ---
495+
///
496+
/// This function may modify the doc comment to ensure that the string can be displayed using a
497+
/// markdown viewer in Clippy's lint list. The following modifications could be applied:
498+
/// * Removal of leading space after a new line. (Important to display tables)
499+
/// * Ensures that code blocks only contain language information
489500
fn extract_attr_docs(cx: &LateContext<'_>, item: &Item<'_>) -> Option<String> {
490501
let attrs = cx.tcx.hir().attrs(item.hir_id());
491502
let mut lines = attrs.iter().filter_map(ast::Attribute::doc_str);
@@ -510,7 +521,12 @@ fn extract_attr_docs(cx: &LateContext<'_>, item: &Item<'_>) -> Option<String> {
510521
continue;
511522
}
512523
}
513-
docs.push_str(line);
524+
// This removes the leading space that the macro translation introduces
525+
if let Some(stripped_doc) = line.strip_prefix(' ') {
526+
docs.push_str(stripped_doc);
527+
} else if !line.is_empty() {
528+
docs.push_str(line);
529+
}
514530
}
515531
Some(docs)
516532
}

util/gh-pages/index.html

+146-53
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
<!DOCTYPE html>
2+
<!--
3+
Welcome to a Clippy's lint list, at least the source code of it. If you are
4+
interested in contributing to this website checkout `util/gh-pages/index.html`
5+
inside the rust-clippy repository.
6+
7+
Otherwise, have a great day =^.^=
8+
-->
29
<html lang="en">
310
<head>
411
<meta charset="UTF-8"/>
512
<meta name="viewport" content="width=device-width, initial-scale=1"/>
613

7-
<title>ALL the Clippy Lints</title>
14+
<title>Clippy Lints</title>
815

916
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css"/>
1017
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.5.0/styles/github.min.css"/>
@@ -22,15 +29,95 @@
2229

2330
.panel-heading { cursor: pointer; }
2431

25-
.panel-title { display: flex; }
32+
.panel-title { display: flex; flex-wrap: wrap;}
2633
.panel-title .label { display: inline-block; }
2734

28-
.panel-title-name { flex: 1; }
35+
.panel-title-name { flex: 1; min-width: 400px;}
2936
.panel-title-name span { vertical-align: bottom; }
3037

3138
.panel .panel-title-name .anchor { display: none; }
3239
.panel:hover .panel-title-name .anchor { display: inline;}
3340

41+
.label {
42+
padding-top: 0.3em;
43+
padding-bottom: 0.3em;
44+
}
45+
46+
.label-lint-group {
47+
min-width: 8em;
48+
}
49+
.label-lint-level {
50+
min-width: 4em;
51+
}
52+
53+
.label-lint-level-allow {
54+
background-color: #5cb85c;
55+
}
56+
.label-lint-level-warn {
57+
background-color: #f0ad4e;
58+
}
59+
.label-lint-level-deny {
60+
background-color: #d9534f;
61+
}
62+
.label-lint-level-none {
63+
background-color: #777777;
64+
opacity: 0.5;
65+
}
66+
67+
.label-group-deprecated {
68+
opacity: 0.5;
69+
}
70+
71+
.label-doc-folding {
72+
color: #000;
73+
background-color: #fff;
74+
border: 1px solid var(--theme-popup-border);
75+
}
76+
.label-doc-folding:hover {
77+
background-color: #e6e6e6;
78+
}
79+
80+
.lint-doc-md > h3 {
81+
border-top: 1px solid var(--theme-popup-border);
82+
padding: 10px 15px;
83+
margin: 0 -15px;
84+
font-size: 18px;
85+
}
86+
.lint-doc-md > h3:first-child {
87+
border-top: none;
88+
padding-top: 0px;
89+
}
90+
91+
@media (max-width:749px) {
92+
.lint-additional-info-container {
93+
display: flex;
94+
flex-flow: column;
95+
}
96+
.lint-additional-info-item + .lint-additional-info-item {
97+
border-top: 1px solid var(--theme-popup-border);
98+
}
99+
}
100+
@media (min-width:750px) {
101+
.lint-additional-info-container {
102+
display: flex;
103+
flex-flow: row;
104+
}
105+
.lint-additional-info-item + .lint-additional-info-item {
106+
border-left: 1px solid var(--theme-popup-border);
107+
}
108+
}
109+
110+
.lint-additional-info-item {
111+
display: inline-flex;
112+
min-width: 200px;
113+
flex-grow: 1;
114+
padding: 9px 5px 5px 15px;
115+
}
116+
117+
.label-applicability {
118+
background-color: #777777;
119+
margin: auto 5px;
120+
}
34121
</style>
35122
<style>
36123
/* Expanding the mdBoom theme*/
@@ -159,7 +246,7 @@
159246

160247
<div class="container" ng-app="clippy" ng-controller="lintList">
161248
<div class="page-header">
162-
<h1>ALL the Clippy Lints</h1>
249+
<h1>Clippy Lints</h1>
163250
</div>
164251

165252
<noscript>
@@ -181,9 +268,12 @@ <h1>ALL the Clippy Lints</h1>
181268
<div class="panel-body row filter-panel">
182269
<div class="col-md-6 form-inline">
183270
<div class="form-group form-group-lg">
184-
<p class="h4">Lint levels</p>
271+
<p class="h4">
272+
Lint levels
273+
<a href="https://doc.rust-lang.org/rustc/lints/levels.html">(?)</a>
274+
</p>
185275
<div class="checkbox" ng-repeat="(level, enabled) in levels">
186-
<label>
276+
<label class="text-capitalize">
187277
<input type="checkbox" ng-model="levels[level]" />
188278
{{level}}
189279
</label>
@@ -192,7 +282,10 @@ <h1>ALL the Clippy Lints</h1>
192282
</div>
193283
<div class="col-md-6 form-inline">
194284
<div class="form-group form-group-lg">
195-
<p class="h4">Lint groups</p>
285+
<p class="h4">
286+
Lint groups
287+
<a href="https://github.com/rust-lang/rust-clippy/#clippy">(?)</a>
288+
</p>
196289
<div class="checkbox" ng-repeat="(group, enabled) in groups">
197290
<label class="text-capitalize">
198291
<input type="checkbox" ng-model="groups[group]" />
@@ -216,9 +309,8 @@ <h1>ALL the Clippy Lints</h1>
216309
</div>
217310
</div>
218311
</div>
219-
220-
<article class="panel panel-default" id="{{lint.id}}"
221-
ng-repeat="lint in data | filter:byLevels | filter:byGroups | filter:bySearch | orderBy:'id' track by lint.id">
312+
<!-- The order of the filters should be from most likely to remove a lint to least likely to improve performance. -->
313+
<article class="panel panel-default" id="{{lint.id}}" ng-repeat="lint in data | filter:bySearch | filter:byGroups | filter:byLevels">
222314
<header class="panel-heading" ng-click="open[lint.id] = !open[lint.id]">
223315
<h2 class="panel-title">
224316
<div class="panel-title-name">
@@ -227,29 +319,36 @@ <h2 class="panel-title">
227319
</div>
228320

229321
<div class="panel-title-addons">
230-
<span class="label label-default text-capitalize">{{lint.group}}</span>
322+
<span class="label label-lint-group label-default label-group-{{lint.group}}">{{lint.group}}</span>
323+
324+
<span class="label label-lint-level label-lint-level-{{lint.level}}">{{lint.level}}</span>
231325

232-
<span ng-if="lint.level == 'Allow'" class="label label-success">Allow</span>
233-
<span ng-if="lint.level == 'Warn'" class="label label-warning">Warn</span>
234-
<span ng-if="lint.level == 'Deny'" class="label label-danger">Deny</span>
235-
<span ng-if="lint.level == 'Deprecated'" class="label label-default">Deprecated</span>
236326

237-
<button class="btn btn-default btn-xs">
238-
<span ng-show="open[lint.id]">&minus;</span>
239-
<span ng-hide="open[lint.id]">&plus;</span>
240-
</button>
327+
<span class="label label-doc-folding" ng-show="open[lint.id]">&minus;</span>
328+
<span class="label label-doc-folding" ng-hide="open[lint.id]">&plus;</span>
241329
</div>
242330
</h2>
243331
</header>
244332

245-
<ul class="list-group lint-docs" ng-if="lint.docs" ng-class="{collapse: true, in: open[lint.id]}">
246-
<li class="list-group-item" ng-repeat="(title, text) in lint.docs">
247-
<h4 class="list-group-item-heading">
248-
{{title}}
249-
</h4>
250-
<div class="list-group-item-text" ng-bind-html="text | markdown"></div>
251-
<a ng-if="title == 'Known problems'" href="https://github.com/rust-lang/rust-clippy/issues?q=is%3Aissue+is%3Aopen+{{lint.id}}">Search on GitHub</a>
252-
</li>
333+
<ul class="list-group lint-docs" ng-class="{collapse: true, in: open[lint.id]}">
334+
<div class="list-group-item lint-doc-md" ng-bind-html="lint.docs | markdown"></div>
335+
<div class="lint-additional-info-container">
336+
<!-- Applicability -->
337+
<div class="lint-additional-info-item">
338+
<span> Applicability: </span>
339+
<span class="label label-default label-applicability">{{lint.applicability.applicability}}</span>
340+
<a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint_defs/enum.Applicability.html#variants">(?)</a>
341+
</div>
342+
<!-- TODO xFrednet 2021-05-19: Somehow collect and show the version See rust-clippy#6492 -->
343+
<!-- Open related issues -->
344+
<div class="lint-additional-info-item">
345+
<a href="https://github.com/rust-lang/rust-clippy/issues?q=is%3Aissue+{{lint.id}}">Related Issues</a>
346+
</div>
347+
<!-- Jump to source -->
348+
<div class="lint-additional-info-item">
349+
<a href="https://github.com/rust-lang/rust-clippy/blob/{{docVersion}}/clippy_lints/{{lint.id_span.path}}#L{{lint.id_span.line}}">View Source</a>
350+
</div>
351+
</div>
253352
</ul>
254353
</article>
255354
</div>
@@ -310,22 +409,6 @@ <h4 class="list-group-item-heading">
310409
}
311410
}
312411

313-
function searchLint(lint, term) {
314-
for (const field in lint.docs) {
315-
// Continue if it's not a property
316-
if (!lint.docs.hasOwnProperty(field)) {
317-
continue;
318-
}
319-
320-
// Return if not found
321-
if (lint.docs[field].toLowerCase().indexOf(term) !== -1) {
322-
return true;
323-
}
324-
}
325-
326-
return false;
327-
}
328-
329412
angular.module("clippy", [])
330413
.filter('markdown', function ($sce) {
331414
return function (text) {
@@ -350,13 +433,25 @@ <h4 class="list-group-item-heading">
350433
})
351434
.controller("lintList", function ($scope, $http, $timeout) {
352435
// Level filter
353-
var LEVEL_FILTERS_DEFAULT = {Allow: true, Warn: true, Deny: true, Deprecated: true};
436+
var LEVEL_FILTERS_DEFAULT = {allow: true, warn: true, deny: true, none: true};
354437
$scope.levels = LEVEL_FILTERS_DEFAULT;
355438
$scope.byLevels = function (lint) {
356439
return $scope.levels[lint.level];
357440
};
358441

359-
$scope.groups = {};
442+
var GROUPS_FILTER_DEFAULT = {
443+
cargo: true,
444+
complexity: true,
445+
correctness: true,
446+
deprecated: false,
447+
nursery: true,
448+
pedantic: true,
449+
perf: true,
450+
restriction: true,
451+
style: true,
452+
suspicious: true,
453+
};
454+
$scope.groups = GROUPS_FILTER_DEFAULT;
360455
$scope.byGroups = function (lint) {
361456
return $scope.groups[lint.group];
362457
};
@@ -377,12 +472,14 @@ <h4 class="list-group-item-heading">
377472
// Search the description
378473
// The use of `for`-loops instead of `foreach` enables us to return early
379474
let terms = searchStr.split(" ");
475+
let docsLowerCase = lint.docs.toLowerCase();
380476
for (index = 0; index < terms.length; index++) {
381-
if (lint.id.indexOf(terms[index]) !== -1) {
477+
// This is more likely and will therefor be checked first
478+
if (docsLowerCase.indexOf(terms[index]) !== -1) {
382479
continue;
383480
}
384481

385-
if (searchLint(lint, terms[index])) {
482+
if (lint.id.indexOf(terms[index]) !== -1) {
386483
continue;
387484
}
388485

@@ -395,6 +492,8 @@ <h4 class="list-group-item-heading">
395492
// Get data
396493
$scope.open = {};
397494
$scope.loading = true;
495+
// This will be used to jump into the source code of the version that this documentation is for.
496+
$scope.docVersion = window.location.pathname.split('/')[2] || "master";
398497

399498
if (window.location.hash.length > 1) {
400499
$scope.search = window.location.hash.slice(1);
@@ -407,12 +506,6 @@ <h4 class="list-group-item-heading">
407506
$scope.data = data;
408507
$scope.loading = false;
409508

410-
// Initialize lint groups (the same structure is also used to enable filtering)
411-
$scope.groups = data.reduce(function (result, val) {
412-
result[val.group] = true;
413-
return result;
414-
}, {});
415-
416509
var selectedGroup = getQueryVariable("sel");
417510
if (selectedGroup) {
418511
selectGroup($scope, selectedGroup.toLowerCase());

0 commit comments

Comments
 (0)