]> git.lizzy.rs Git - rust.git/blobdiff - clippy_lints/src/utils/sugg.rs
Introduce snippet_with_applicability and hir_with_applicability functions
[rust.git] / clippy_lints / src / utils / sugg.rs
index f7d8c1fc15122526660cdbe2b7b124d680ce630a..5bb35474403abbcec61156781ec0087d8565a37d 100644 (file)
@@ -1,3 +1,13 @@
+// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
 //! Contains utility functions to generate suggestions.
 #![deny(clippy::missing_docs_in_private_items)]
 
@@ -6,6 +16,7 @@
 use crate::rustc::lint::{EarlyContext, LateContext, LintContext};
 use crate::rustc_errors;
 use std::borrow::Cow;
+use std::convert::TryInto;
 use std::fmt::Display;
 use std;
 use crate::syntax::source_map::{CharPos, Span};
@@ -85,6 +96,15 @@ pub fn hir(cx: &LateContext<'_, '_>, expr: &hir::Expr, default: &'a str) -> Self
         Self::hir_opt(cx, expr).unwrap_or_else(|| Sugg::NonParen(Cow::Borrowed(default)))
     }
 
+    pub fn hir_with_applicability(cx: &LateContext<'_, '_>, expr: &hir::Expr, default: &'a str, applicability: &mut Applicability) -> Self {
+        Self::hir_opt(cx, expr).unwrap_or_else(|| {
+            if *applicability == Applicability::MachineApplicable {
+                *applicability = Applicability::HasPlaceholders;
+            }
+            Sugg::NonParen(Cow::Borrowed(default))
+        })
+    }
+
     /// Prepare a suggestion from an expression.
     pub fn ast(cx: &EarlyContext<'_>, expr: &ast::Expr, default: &'a str) -> Self {
         use crate::syntax::ast::RangeLimits;
@@ -462,7 +482,7 @@ pub trait DiagnosticBuilderExt<'a, T: LintContext<'a>> {
     /// ```rust,ignore
     /// db.suggest_item_with_attr(cx, item, "#[derive(Default)]");
     /// ```
-    fn suggest_item_with_attr<D: Display + ?Sized>(&mut self, cx: &T, item: Span, msg: &str, attr: &D);
+    fn suggest_item_with_attr<D: Display + ?Sized>(&mut self, cx: &T, item: Span, msg: &str, attr: &D, applicability: Applicability);
 
     /// Suggest to add an item before another.
     ///
@@ -476,7 +496,7 @@ pub trait DiagnosticBuilderExt<'a, T: LintContext<'a>> {
     ///     bar();
     /// }");
     /// ```
-    fn suggest_prepend_item(&mut self, cx: &T, item: Span, msg: &str, new_item: &str);
+    fn suggest_prepend_item(&mut self, cx: &T, item: Span, msg: &str, new_item: &str, applicability: Applicability);
 
     /// Suggest to completely remove an item.
     ///
@@ -489,11 +509,11 @@ pub trait DiagnosticBuilderExt<'a, T: LintContext<'a>> {
     /// ```rust,ignore
     /// db.suggest_remove_item(cx, item, "remove this")
     /// ```
-    fn suggest_remove_item(&mut self, cx: &T, item: Span, msg: &str);
+    fn suggest_remove_item(&mut self, cx: &T, item: Span, msg: &str, applicability: Applicability);
 }
 
 impl<'a, 'b, 'c, T: LintContext<'c>> DiagnosticBuilderExt<'c, T> for rustc_errors::DiagnosticBuilder<'b> {
-    fn suggest_item_with_attr<D: Display + ?Sized>(&mut self, cx: &T, item: Span, msg: &str, attr: &D) {
+    fn suggest_item_with_attr<D: Display + ?Sized>(&mut self, cx: &T, item: Span, msg: &str, attr: &D, applicability: Applicability) {
         if let Some(indent) = indentation(cx, item) {
             let span = item.with_hi(item.lo());
 
@@ -501,12 +521,12 @@ fn suggest_item_with_attr<D: Display + ?Sized>(&mut self, cx: &T, item: Span, ms
                         span,
                         msg,
                         format!("{}\n{}", attr, indent),
-                        Applicability::Unspecified,
+                        applicability,
                         );
         }
     }
 
-    fn suggest_prepend_item(&mut self, cx: &T, item: Span, msg: &str, new_item: &str) {
+    fn suggest_prepend_item(&mut self, cx: &T, item: Span, msg: &str, new_item: &str, applicability: Applicability) {
         if let Some(indent) = indentation(cx, item) {
             let span = item.with_hi(item.lo());
 
@@ -527,29 +547,29 @@ fn suggest_prepend_item(&mut self, cx: &T, item: Span, msg: &str, new_item: &str
                         span,
                         msg,
                         format!("{}\n{}", new_item, indent),
-                        Applicability::Unspecified,
+                        applicability,
                         );
         }
     }
 
-    fn suggest_remove_item(&mut self, cx: &T, item: Span, msg: &str) {
+    fn suggest_remove_item(&mut self, cx: &T, item: Span, msg: &str, applicability: Applicability) {
         let mut remove_span = item;
         let hi = cx.sess().source_map().next_point(remove_span).hi();
         let fmpos = cx.sess().source_map().lookup_byte_offset(hi);
 
-        if let Some(ref src) = fmpos.fm.src {
+        if let Some(ref src) = fmpos.sf.src {
             let non_whitespace_offset = src[fmpos.pos.to_usize()..].find(|c| c != ' ' && c != '\t' && c != '\n');
 
             if let Some(non_whitespace_offset) = non_whitespace_offset {
-                remove_span = remove_span.with_hi(remove_span.hi() + BytePos(non_whitespace_offset as u32))
+                remove_span = remove_span.with_hi(remove_span.hi() + BytePos(non_whitespace_offset.try_into().expect("offset too large")))
             }
         }
 
         self.span_suggestion_with_applicability(
-                    remove_span,
-                    msg,
-                    String::new(),
-                    Applicability::Unspecified,
-                    );
+            remove_span,
+            msg,
+            String::new(),
+            applicability,
+        );
     }
 }