Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adapting the lint list to Clippy's new metadata format #7279

Merged
merged 1 commit into from
Jul 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 26 additions & 10 deletions clippy_lints/src/utils/internal_lints/metadata_collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ const DEPRECATED_LINT_TYPE: [&str; 3] = ["clippy_lints", "deprecated_lints", "Cl

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

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

// Outputting
if Path::new(OUTPUT_FILE).exists() {
Expand All @@ -208,7 +210,7 @@ struct LintMetadata {
id: String,
id_span: SerializableSpan,
group: String,
level: &'static str,
level: String,
docs: String,
/// This field is only used in the output and will only be
/// mapped shortly before the actual output.
Expand All @@ -221,7 +223,7 @@ impl LintMetadata {
id,
id_span,
group,
level,
level: level.to_string(),
docs,
applicability: None,
}
Expand Down Expand Up @@ -269,14 +271,16 @@ impl Serialize for ApplicabilityInfo {
where
S: Serializer,
{
let index = self.applicability.unwrap_or_default();

let mut s = serializer.serialize_struct("ApplicabilityInfo", 2)?;
s.serialize_field("is_multi_part_suggestion", &self.is_multi_part_suggestion)?;
s.serialize_field(
"applicability",
&paths::APPLICABILITY_VALUES[index][APPLICABILITY_NAME_INDEX],
)?;
if let Some(index) = self.applicability {
s.serialize_field(
"applicability",
&paths::APPLICABILITY_VALUES[index][APPLICABILITY_NAME_INDEX],
)?;
} else {
s.serialize_field("applicability", APPLICABILITY_UNRESOLVED_STR)?;
}
s.end()
}
}
Expand Down Expand Up @@ -486,6 +490,13 @@ fn extract_attr_docs_or_lint(cx: &LateContext<'_>, item: &Item<'_>) -> Option<St
/// ```
///
/// Would result in `Hello world!\n=^.^=\n`
///
/// ---
///
/// This function may modify the doc comment to ensure that the string can be displayed using a
/// markdown viewer in Clippy's lint list. The following modifications could be applied:
/// * Removal of leading space after a new line. (Important to display tables)
/// * Ensures that code blocks only contain language information
fn extract_attr_docs(cx: &LateContext<'_>, item: &Item<'_>) -> Option<String> {
let attrs = cx.tcx.hir().attrs(item.hir_id());
let mut lines = attrs.iter().filter_map(ast::Attribute::doc_str);
Expand All @@ -510,7 +521,12 @@ fn extract_attr_docs(cx: &LateContext<'_>, item: &Item<'_>) -> Option<String> {
continue;
}
}
docs.push_str(line);
// This removes the leading space that the macro translation introduces
if let Some(stripped_doc) = line.strip_prefix(' ') {
docs.push_str(stripped_doc);
} else if !line.is_empty() {
docs.push_str(line);
}
}
Some(docs)
}
Expand Down
199 changes: 146 additions & 53 deletions util/gh-pages/index.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
<!DOCTYPE html>
<!--
Welcome to a Clippy's lint list, at least the source code of it. If you are
interested in contributing to this website checkout `util/gh-pages/index.html`
inside the rust-clippy repository.

Otherwise, have a great day =^.^=
-->
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>

<title>ALL the Clippy Lints</title>
<title>Clippy Lints</title>

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

.panel-heading { cursor: pointer; }

.panel-title { display: flex; }
.panel-title { display: flex; flex-wrap: wrap;}
.panel-title .label { display: inline-block; }

.panel-title-name { flex: 1; }
.panel-title-name { flex: 1; min-width: 400px;}
.panel-title-name span { vertical-align: bottom; }

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

.label {
padding-top: 0.3em;
padding-bottom: 0.3em;
}

.label-lint-group {
min-width: 8em;
}
.label-lint-level {
min-width: 4em;
}

.label-lint-level-allow {
background-color: #5cb85c;
}
.label-lint-level-warn {
background-color: #f0ad4e;
}
.label-lint-level-deny {
background-color: #d9534f;
}
.label-lint-level-none {
background-color: #777777;
opacity: 0.5;
}

.label-group-deprecated {
opacity: 0.5;
}

.label-doc-folding {
color: #000;
background-color: #fff;
border: 1px solid var(--theme-popup-border);
}
.label-doc-folding:hover {
background-color: #e6e6e6;
}

.lint-doc-md > h3 {
border-top: 1px solid var(--theme-popup-border);
padding: 10px 15px;
margin: 0 -15px;
font-size: 18px;
}
.lint-doc-md > h3:first-child {
border-top: none;
padding-top: 0px;
}

@media (max-width:749px) {
.lint-additional-info-container {
display: flex;
flex-flow: column;
}
.lint-additional-info-item + .lint-additional-info-item {
border-top: 1px solid var(--theme-popup-border);
}
}
@media (min-width:750px) {
.lint-additional-info-container {
display: flex;
flex-flow: row;
}
.lint-additional-info-item + .lint-additional-info-item {
border-left: 1px solid var(--theme-popup-border);
}
}

.lint-additional-info-item {
display: inline-flex;
min-width: 200px;
flex-grow: 1;
padding: 9px 5px 5px 15px;
}

.label-applicability {
background-color: #777777;
margin: auto 5px;
}
</style>
<style>
/* Expanding the mdBoom theme*/
Expand Down Expand Up @@ -159,7 +246,7 @@

<div class="container" ng-app="clippy" ng-controller="lintList">
<div class="page-header">
<h1>ALL the Clippy Lints</h1>
<h1>Clippy Lints</h1>
</div>

<noscript>
Expand All @@ -181,9 +268,12 @@ <h1>ALL the Clippy Lints</h1>
<div class="panel-body row filter-panel">
<div class="col-md-6 form-inline">
<div class="form-group form-group-lg">
<p class="h4">Lint levels</p>
<p class="h4">
Lint levels
<a href="https://doc.rust-lang.org/rustc/lints/levels.html">(?)</a>
</p>
<div class="checkbox" ng-repeat="(level, enabled) in levels">
<label>
<label class="text-capitalize">
<input type="checkbox" ng-model="levels[level]" />
{{level}}
</label>
Expand All @@ -192,7 +282,10 @@ <h1>ALL the Clippy Lints</h1>
</div>
<div class="col-md-6 form-inline">
<div class="form-group form-group-lg">
<p class="h4">Lint groups</p>
<p class="h4">
Lint groups
<a href="https://github.com/rust-lang/rust-clippy/#clippy">(?)</a>
</p>
<div class="checkbox" ng-repeat="(group, enabled) in groups">
<label class="text-capitalize">
<input type="checkbox" ng-model="groups[group]" />
Expand All @@ -216,9 +309,8 @@ <h1>ALL the Clippy Lints</h1>
</div>
</div>
</div>

<article class="panel panel-default" id="{{lint.id}}"
ng-repeat="lint in data | filter:byLevels | filter:byGroups | filter:bySearch | orderBy:'id' track by lint.id">
<!-- The order of the filters should be from most likely to remove a lint to least likely to improve performance. -->
<article class="panel panel-default" id="{{lint.id}}" ng-repeat="lint in data | filter:bySearch | filter:byGroups | filter:byLevels">
<header class="panel-heading" ng-click="open[lint.id] = !open[lint.id]">
<h2 class="panel-title">
<div class="panel-title-name">
Expand All @@ -227,29 +319,36 @@ <h2 class="panel-title">
</div>

<div class="panel-title-addons">
<span class="label label-default text-capitalize">{{lint.group}}</span>
<span class="label label-lint-group label-default label-group-{{lint.group}}">{{lint.group}}</span>

<span class="label label-lint-level label-lint-level-{{lint.level}}">{{lint.level}}</span>

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

<button class="btn btn-default btn-xs">
<span ng-show="open[lint.id]">&minus;</span>
<span ng-hide="open[lint.id]">&plus;</span>
</button>
<span class="label label-doc-folding" ng-show="open[lint.id]">&minus;</span>
<span class="label label-doc-folding" ng-hide="open[lint.id]">&plus;</span>
</div>
</h2>
</header>

<ul class="list-group lint-docs" ng-if="lint.docs" ng-class="{collapse: true, in: open[lint.id]}">
<li class="list-group-item" ng-repeat="(title, text) in lint.docs">
<h4 class="list-group-item-heading">
{{title}}
</h4>
<div class="list-group-item-text" ng-bind-html="text | markdown"></div>
<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>
</li>
<ul class="list-group lint-docs" ng-class="{collapse: true, in: open[lint.id]}">
<div class="list-group-item lint-doc-md" ng-bind-html="lint.docs | markdown"></div>
<div class="lint-additional-info-container">
<!-- Applicability -->
<div class="lint-additional-info-item">
<span> Applicability: </span>
<span class="label label-default label-applicability">{{lint.applicability.applicability}}</span>
<a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint_defs/enum.Applicability.html#variants">(?)</a>
</div>
<!-- TODO xFrednet 2021-05-19: Somehow collect and show the version See rust-clippy#6492 -->
<!-- Open related issues -->
<div class="lint-additional-info-item">
<a href="https://github.com/rust-lang/rust-clippy/issues?q=is%3Aissue+{{lint.id}}">Related Issues</a>
</div>
<!-- Jump to source -->
<div class="lint-additional-info-item">
<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>
</div>
</div>
</ul>
</article>
</div>
Expand Down Expand Up @@ -310,22 +409,6 @@ <h4 class="list-group-item-heading">
}
}

function searchLint(lint, term) {
for (const field in lint.docs) {
// Continue if it's not a property
if (!lint.docs.hasOwnProperty(field)) {
continue;
}

// Return if not found
if (lint.docs[field].toLowerCase().indexOf(term) !== -1) {
return true;
}
}

return false;
}

angular.module("clippy", [])
.filter('markdown', function ($sce) {
return function (text) {
Expand All @@ -350,13 +433,25 @@ <h4 class="list-group-item-heading">
})
.controller("lintList", function ($scope, $http, $timeout) {
// Level filter
var LEVEL_FILTERS_DEFAULT = {Allow: true, Warn: true, Deny: true, Deprecated: true};
var LEVEL_FILTERS_DEFAULT = {allow: true, warn: true, deny: true, none: true};
$scope.levels = LEVEL_FILTERS_DEFAULT;
$scope.byLevels = function (lint) {
return $scope.levels[lint.level];
};

$scope.groups = {};
var GROUPS_FILTER_DEFAULT = {
cargo: true,
complexity: true,
correctness: true,
deprecated: false,
nursery: true,
pedantic: true,
perf: true,
restriction: true,
style: true,
suspicious: true,
};
$scope.groups = GROUPS_FILTER_DEFAULT;
$scope.byGroups = function (lint) {
return $scope.groups[lint.group];
};
Expand All @@ -377,12 +472,14 @@ <h4 class="list-group-item-heading">
// Search the description
// The use of `for`-loops instead of `foreach` enables us to return early
let terms = searchStr.split(" ");
let docsLowerCase = lint.docs.toLowerCase();
for (index = 0; index < terms.length; index++) {
if (lint.id.indexOf(terms[index]) !== -1) {
// This is more likely and will therefor be checked first
if (docsLowerCase.indexOf(terms[index]) !== -1) {
continue;
}

if (searchLint(lint, terms[index])) {
if (lint.id.indexOf(terms[index]) !== -1) {
continue;
}

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

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

// Initialize lint groups (the same structure is also used to enable filtering)
$scope.groups = data.reduce(function (result, val) {
result[val.group] = true;
return result;
}, {});

var selectedGroup = getQueryVariable("sel");
if (selectedGroup) {
selectGroup($scope, selectedGroup.toLowerCase());
Expand Down