2016-06-03 3 views
3

Я пытаюсь извлечь имя функции из следующего кода Rust.Как получить абсолютное имя синтаксиса :: ast :: Ident?

// example.rs 

pub mod hello { 
    pub mod world { 
     pub fn greetings() { 
      println!("Hello, world!") 
     } 
    } 
} 

Вот код, который пытается извлечь имя функции из example.rs.

//runner.rs 

/* 
* This program will only compile with nightly Rust 
* 
* To compile 
* rustc runner.rs 
* 
* To run 
* LD_LIBRARY_PATH=$(rustc --print sysroot)/lib ./runner 
*/ 

#![feature(rustc_private)] 
extern crate syntax; 

use syntax::visit::{ self, Visitor, FnKind }; 
use syntax::ast::{ FnDecl, Block, NodeId, Mac }; 
use syntax::codemap::{ Span }; 
use syntax::{ parse, ast }; 
use std::path::Path; 

struct MyVisitor; 

impl<'x> Visitor<'x> for MyVisitor { 
    fn visit_fn<'v>(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: &'v Block, s: Span, _: NodeId) { 
     let name; 
     match fk { 
      visit::FnKind::Method(_ident, ref _method_sig, _option) => { 
       name = (*_ident.name.as_str()).to_string(); 
      } 
      visit::FnKind::ItemFn(_ident, ref _generics, _unsafety, _constness, _abi, _visibility) => { 
       name = (*_ident.name.as_str()).to_string(); 
      } 
      visit::FnKind::Closure => { 
       name = "".to_string(); 
      } 
     }; 
     println!("{}", name); 
     visit::walk_fn(self, fk, fd, b, s); 
    } 

    fn visit_mac<'v>(&mut self, _mac: &'v Mac) { 
     // do nothing 
     // just overriding here because parent panics as 
     // panic!("visit_mac disabled by default"); 
    } 
} 

fn build_crate(path: &std::path::Path) -> ast::Crate { 
    let sess = parse::ParseSess::new(); 
    let filemap = sess.codemap().load_file(path).unwrap(); 
    let cfg = ast::CrateConfig::new(); 
    let reader = parse::lexer::StringReader::new(&sess.span_diagnostic, filemap); 
    let mut parser = parse::parser::Parser::new(&sess, cfg, Box::new(reader)); 
    return parser.parse_crate_mod().unwrap(); 
} 

fn main() { 
    let krate = build_crate(Path::new("./example.rs")); 
    let mut visitor = MyVisitor {}; 
    visit::walk_crate(&mut visitor, &krate); 
} 

Проблема заключается в том, что она печатает greetings, как выход, но я хочу, полное имя, то есть, hello::world::greetings. Как мне это сделать?

ответ

3

Вы не можете. Ident - это просто имя (+ информация о расширении макросов).

Что вы можете сделать, это использовать посетитель, чтобы построить путь модуля, также путем реализации метода visit_item и сохранения текущего пути:

fn visit_item(&mut self, i: &'v Item) { 
    self.modules.push(i.ident); 
    walk_item(self, i); 
    self.modules.pop(); 
} 

Затем вы можете напечатать весь путь:

for ident in &self.modules { 
    print!("::{}", ident.name.as_str()); 
} 
println!(""); 
+0

быстрый вопрос: в чем разница между 'visit_mod' и' visit_item'? И почему вы рекомендуете переопределять 'visit_item' вместо' visit_mod'? –

+1

'visit_mod' не дает вам возможности получить имя модуля. По крайней мере, не без запроса «TyCtxt», который в этом случае несколько завышен. Также вы не получаете таких функций, как функции. Поэтому, если вы определяете функцию внутри функции, вы не получите правильный путь, когда просто используете модули для создания имени. –

Смежные вопросы