]> git.lizzy.rs Git - rust.git/blob - src/imports.rs
Merge pull request #43 from tbu-/pr_nostaticmut
[rust.git] / src / imports.rs
1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use visitor::FmtVisitor;
12 use lists::{write_list, ListFormatting, SeparatorTactic, ListTactic};
13
14 use syntax::ast;
15 use syntax::codemap::Span;
16 use syntax::parse::token;
17 use syntax::print::pprust;
18
19 use {IDEAL_WIDTH, MAX_WIDTH};
20
21 // TODO change import lists with one item to a single import
22 //      remove empty lists (if they're even possible)
23 // TODO (some day) remove unused imports, expand globs, compress many single imports into a list import
24
25 impl<'a> FmtVisitor<'a> {
26     // Basically just pretty prints a multi-item import.
27     pub fn rewrite_use_list(&mut self,
28                             path: &ast::Path,
29                             path_list: &[ast::PathListItem],
30                             visibility: ast::Visibility,
31                             vp_span: Span) -> String {
32         // FIXME check indentation
33         let l_loc = self.codemap.lookup_char_pos(vp_span.lo);
34
35         let path_str = pprust::path_to_string(&path);
36
37         let vis = match visibility {
38             ast::Public => "pub ",
39             _ => ""
40         };
41
42         // 1 = {
43         let mut indent = l_loc.col.0 + path_str.len() + 1;
44         if path_str.len() > 0 {
45             // 2 = ::
46             indent += 2;
47         }
48         // 2 = } + ;
49         let used_width = indent + 2 + vis.len();
50         let budget = if used_width >= IDEAL_WIDTH {
51             if used_width < MAX_WIDTH {
52                 MAX_WIDTH - used_width
53             } else {
54                 // Give up
55                 return String::new();
56             }
57         } else {
58             IDEAL_WIDTH - used_width
59         };
60         let fmt = ListFormatting {
61             tactic: ListTactic::Mixed,
62             separator: ",",
63             trailing_separator: SeparatorTactic::Never,
64             indent: indent,
65             h_width: budget,
66             v_width: budget,
67         };
68
69         // TODO handle any comments inbetween items.
70         // If `self` is in the list, put it first.
71         let head = if path_list.iter().any(|vpi|
72             if let ast::PathListItem_::PathListMod{ .. } = vpi.node {
73                 true
74             } else {
75                 false
76             }
77         ) {
78             Some(("self".to_owned(), String::new()))
79         } else {
80             None
81         };
82
83         let items: Vec<_> = head.into_iter().chain(path_list.iter().filter_map(|vpi| {
84             match vpi.node {
85                 ast::PathListItem_::PathListIdent{ name, .. } => {
86                     Some((token::get_ident(name).to_string(), String::new()))
87                 }
88                 // Skip `self`, because we added it above.
89                 ast::PathListItem_::PathListMod{ .. } => None,
90             }
91         })).collect();
92         if path_str.len() == 0 {
93             format!("{}use {{{}}};", vis, write_list(&items, &fmt))
94         } else {
95             format!("{}use {}::{{{}}};", vis, path_str, write_list(&items, &fmt))
96         }
97     }
98 }