]> git.lizzy.rs Git - rust.git/commitdiff
Add a lint to detect unnecessarily qualified names
authorSeo Sanghyeon <sanxiyn@gmail.com>
Mon, 8 Jul 2013 15:34:28 +0000 (00:34 +0900)
committerSeo Sanghyeon <sanxiyn@gmail.com>
Wed, 10 Jul 2013 10:09:03 +0000 (19:09 +0900)
src/librustc/middle/lint.rs
src/librustc/middle/resolve.rs
src/libsyntax/ast_util.rs

index 0fc19ffd78e521ab8694a0c743f5822cc5b725b2..8074b5b3b40abec9138f58bc53a985c0c4fd9c29 100644 (file)
@@ -71,6 +71,7 @@
 pub enum lint {
     ctypes,
     unused_imports,
+    unnecessary_qualification,
     while_true,
     path_statement,
     implicit_copies,
@@ -148,6 +149,13 @@ enum LintSource {
         default: warn
      }),
 
+    ("unnecessary_qualification",
+     LintSpec {
+        lint: unnecessary_qualification,
+        desc: "detects unnecessarily qualified names",
+        default: allow
+     }),
+
     ("while_true",
      LintSpec {
         lint: while_true,
@@ -557,11 +565,7 @@ fn item_stopping_visitor<E: Copy>(outer: visit::vt<E>) -> visit::vt<E> {
                 _ => (outer.visit_fn)(fk, fd, b, s, id, (e, v))
             }
         },
-    .. **(ty_stopping_visitor(outer))})
-}
-
-fn ty_stopping_visitor<E>(v: visit::vt<E>) -> visit::vt<E> {
-    visit::mk_vt(@visit::Visitor {visit_ty: |_t, (_e, _v)| { },.. **v})
+    .. **outer})
 }
 
 fn lint_while_true() -> visit::vt<@mut Context> {
index 041d52a690425925d2230ab376a13e76c3f30e79..619bfbdb5478415bad9e5e8b289c89b04ff57d47 100644 (file)
@@ -17,7 +17,7 @@
 use metadata::cstore::find_extern_mod_stmt_cnum;
 use metadata::decoder::{def_like, dl_def, dl_field, dl_impl};
 use middle::lang_items::LanguageItems;
-use middle::lint::unused_imports;
+use middle::lint::{unnecessary_qualification, unused_imports};
 use middle::pat_util::pat_bindings;
 
 use syntax::ast::*;
@@ -3561,7 +3561,7 @@ pub fn resolve_item(@mut self, item: @item, visitor: ResolveVisitor) {
 
                     // Resolve derived traits.
                     for traits.iter().advance |trt| {
-                        self.resolve_trait_reference(trt, visitor, TraitDerivation);
+                        self.resolve_trait_reference(item.id, trt, visitor, TraitDerivation);
                     }
 
                     for (*methods).iter().advance |method| {
@@ -3802,27 +3802,29 @@ pub fn resolve_type_parameters(@mut self,
                                    visitor: ResolveVisitor) {
         for type_parameters.iter().advance |type_parameter| {
             for type_parameter.bounds.iter().advance |bound| {
-                self.resolve_type_parameter_bound(bound, visitor);
+                self.resolve_type_parameter_bound(type_parameter.id, bound, visitor);
             }
         }
     }
 
     pub fn resolve_type_parameter_bound(@mut self,
+                                        id: node_id,
                                         type_parameter_bound: &TyParamBound,
                                         visitor: ResolveVisitor) {
         match *type_parameter_bound {
             TraitTyParamBound(ref tref) => {
-                self.resolve_trait_reference(tref, visitor, TraitBoundingTypeParameter)
+                self.resolve_trait_reference(id, tref, visitor, TraitBoundingTypeParameter)
             }
             RegionTyParamBound => {}
         }
     }
 
     pub fn resolve_trait_reference(@mut self,
+                                   id: node_id,
                                    trait_reference: &trait_ref,
                                    visitor: ResolveVisitor,
                                    reference_type: TraitReferenceType) {
-        match self.resolve_path(&trait_reference.path, TypeNS, true, visitor) {
+        match self.resolve_path(id, &trait_reference.path, TypeNS, true, visitor) {
             None => {
                 let path_str = self.idents_to_str(trait_reference.path.idents);
 
@@ -3930,7 +3932,8 @@ pub fn resolve_implementation(@mut self,
             let original_trait_refs;
             match opt_trait_reference {
                 &Some(ref trait_reference) => {
-                    self.resolve_trait_reference(trait_reference, visitor, TraitImplementation);
+                    self.resolve_trait_reference(id, trait_reference, visitor,
+                        TraitImplementation);
 
                     // Record the current set of trait references.
                     let mut new_trait_refs = ~[];
@@ -4142,7 +4145,7 @@ pub fn resolve_type(@mut self, ty: &Ty, visitor: ResolveVisitor) {
 
                 match result_def {
                     None => {
-                        match self.resolve_path(path, TypeNS, true, visitor) {
+                        match self.resolve_path(ty.id, path, TypeNS, true, visitor) {
                             Some(def) => {
                                 debug!("(resolving type) resolved `%s` to \
                                         type %?",
@@ -4179,7 +4182,7 @@ pub fn resolve_type(@mut self, ty: &Ty, visitor: ResolveVisitor) {
 
                 do bounds.map |bound_vec| {
                     for bound_vec.iter().advance |bound| {
-                        self.resolve_type_parameter_bound(bound, visitor);
+                        self.resolve_type_parameter_bound(ty.id, bound, visitor);
                     }
                 };
             }
@@ -4187,7 +4190,7 @@ pub fn resolve_type(@mut self, ty: &Ty, visitor: ResolveVisitor) {
             ty_closure(c) => {
                 do c.bounds.map |bounds| {
                     for bounds.iter().advance |bound| {
-                        self.resolve_type_parameter_bound(bound, visitor);
+                        self.resolve_type_parameter_bound(ty.id, bound, visitor);
                     }
                 };
                 visit_ty(ty, ((), visitor));
@@ -4340,7 +4343,7 @@ struct in scope",
 
                 pat_ident(binding_mode, ref path, _) => {
                     // This must be an enum variant, struct, or constant.
-                    match self.resolve_path(path, ValueNS, false, visitor) {
+                    match self.resolve_path(pat_id, path, ValueNS, false, visitor) {
                         Some(def @ def_variant(*)) |
                                 Some(def @ def_struct(*)) => {
                             self.record_def(pattern.id, def);
@@ -4373,7 +4376,7 @@ struct in scope",
 
                 pat_enum(ref path, _) => {
                     // This must be an enum variant, struct or const.
-                    match self.resolve_path(path, ValueNS, false, visitor) {
+                    match self.resolve_path(pat_id, path, ValueNS, false, visitor) {
                         Some(def @ def_fn(*))      |
                         Some(def @ def_variant(*)) |
                         Some(def @ def_struct(*))  |
@@ -4410,7 +4413,7 @@ struct in scope",
                 }
 
                 pat_struct(ref path, _, _) => {
-                    match self.resolve_path(path, TypeNS, false, visitor) {
+                    match self.resolve_path(pat_id, path, TypeNS, false, visitor) {
                         Some(def_ty(class_id))
                                 if self.structs.contains(&class_id) => {
                             let class_def = def_struct(class_id);
@@ -4484,6 +4487,7 @@ pub fn resolve_bare_identifier_pattern(@mut self, name: ident)
     /// If `check_ribs` is true, checks the local definitions first; i.e.
     /// doesn't skip straight to the containing module.
     pub fn resolve_path(@mut self,
+                        id: node_id,
                         path: &Path,
                         namespace: Namespace,
                         check_ribs: bool,
@@ -4500,16 +4504,24 @@ pub fn resolve_path(@mut self,
                                                     namespace);
         }
 
+        let unqualified_def = self.resolve_identifier(
+            *path.idents.last(), namespace, check_ribs, path.span);
+
         if path.idents.len() > 1 {
-            return self.resolve_module_relative_path(path,
-                                                     self.xray_context,
-                                                     namespace);
+            let def = self.resolve_module_relative_path(
+                path, self.xray_context, namespace);
+            match (def, unqualified_def) {
+                (Some(d), Some(ud)) if d == ud => {
+                    self.session.add_lint(unnecessary_qualification,
+                                          id, path.span,
+                                          ~"unnecessary qualification");
+                }
+                _ => ()
+            }
+            return def;
         }
 
-        return self.resolve_identifier(*path.idents.last(),
-                                       namespace,
-                                       check_ribs,
-                                       path.span);
+        return unqualified_def;
     }
 
     pub fn resolve_identifier(@mut self,
@@ -4920,7 +4932,7 @@ pub fn resolve_expr(@mut self, expr: @expr, visitor: ResolveVisitor) {
                 // This is a local path in the value namespace. Walk through
                 // scopes looking for it.
 
-                match self.resolve_path(path, ValueNS, true, visitor) {
+                match self.resolve_path(expr.id, path, ValueNS, true, visitor) {
                     Some(def) => {
                         // Write the result into the def map.
                         debug!("(resolving expr) resolved `%s`",
@@ -4987,7 +4999,7 @@ pub fn resolve_expr(@mut self, expr: @expr, visitor: ResolveVisitor) {
 
             expr_struct(ref path, _, _) => {
                 // Resolve the path to the structure it goes to.
-                match self.resolve_path(path, TypeNS, false, visitor) {
+                match self.resolve_path(expr.id, path, TypeNS, false, visitor) {
                     Some(def_ty(class_id)) | Some(def_struct(class_id))
                             if self.structs.contains(&class_id) => {
                         let class_def = def_struct(class_id);
index 78be8e6f180af8f58fb4952f2eda42ee42036d80..2c62432c7f95220191c0da4b002c190e2d711895 100644 (file)
@@ -462,6 +462,7 @@ pub fn id_visitor<T: Copy>(vfn: @fn(node_id, T)) -> visit::vt<T> {
         },
 
         visit_ty: |ty, (t, vt)| {
+            vfn(ty.id, copy t);
             match ty.node {
               ty_path(_, _, id) => vfn(id, copy t),
               _ => { /* fall through */ }