rust-lang / rls

Repository for the Rust Language Server (aka RLS)
Other
3.51k stars 257 forks source link

Hovering on macro does not display tooltip (even if we can go to def) #1419

Open Xanewok opened 5 years ago

Xanewok commented 5 years ago

The simple case would be println macro, see https://github.com/rust-lang/rls-vscode/issues/238 for a simple reproduction.

DevinR528 commented 4 years ago

Is there work being done on this and if not roughly were would one start if interested in helping this along.

DevinR528 commented 4 years ago

I started a very rough draft that has nothing to do with rls macro-docs, I started with the stupid-stats skeleton.

Using rustc_lint::EarlyLintPass I collect all the relevant info about the macro declaration into a HashMap (this could be whatever rls needs). The problem with this is you cannot without using lazy_static get this information out of the LintStore::register_early_pass(|| Box::new(dyn EarlyLintPass)) closure.

impl EarlyLintPass for MacroDoc {
    fn check_item(&mut self, _: &EarlyContext, it: &ast::Item) {
        if let ast::ItemKind::MacroDef(_) = &it.kind {
            let docs = it.attrs
                .iter()
                .filter(|attr| attr.is_doc_comment())
                .flat_map(|attr| attr.doc_str())
                .map(|sym| {
                    // this is just to get something to print would be done properly
                   sym.as_str().chars()
                        .filter(|c| c != &'/')
                        .collect::<String>()
                })
                .collect::<Vec<_>>()
                .join("\n");
            // insert is a static Mutex<HashMap...
            self.insert(it.ident.as_str().to_string(), Comments::new(it.span, docs))
        }
    }
}

struct RegisterMacDocs;
impl Callbacks for RegisterMacDocs {
    fn config(&mut self, config: &mut Config) {
        config.opts.debugging_opts.save_analysis = true;
        let previous = config.register_lints.take();
        config.register_lints = Some(Box::new(move |sess, lint_store| {
            if let Some(previous) = &previous {
                (previous)(sess, lint_store);
            }
            lint_store.register_lints(&[&MACRO_DOCS]);
            lint_store.register_early_pass(|| Box::new(MacroDoc));
        }));
    }
}