Skip pub keyword when parsing extern crate
This change allows racer to follow and parse reexported crates in
external crates.
For example, now it's possible to go to definition of
`amethyst::renderer` which is reexported in `amethyst` as `pub extern
crate amethyst_renderer as renderer`.
@@ -43,25 +43,16 @@ pub fn match_values(src: Src, blobstart: Point, blobend: Point,
it.chain(match_macro(&src, blobstart, blobend, searchstr, filepath, search_type, local).into_iter())
}
-fn find_keyword(src: &str, pattern: &str, search: &str, search_type: SearchType, local: bool)
--> Option<Point> {
- // search for "^(pub\s+)?(unsafe\s+)?pattern\s+search"
-
- // if not local must start with pub
- if !local && !src.starts_with("pub") { return None; }
-
+fn strip_keyword_prefix(src: &str, keyword: &str) -> Option<Point> {
let mut start = 0usize;
-
- // optional (pub\s+)?(unsafe\s+)?
- for pat in ["pub", "unsafe"].into_iter() {
- if src[start..].starts_with(pat) {
+ if src.starts_with(keyword) {
// Rust added support for `pub(in codegen)`; we need to consume the visibility
// specifier for the rest of the code to keep working.
- let allow_scope = pat == &"pub";
+ let allow_scope = keyword == "pub";
let mut levels = 0;
// remove whitespaces ... must have one at least AFTER the visibility restriction
- start += pat.len();
+ start += keyword.len();
let oldstart = start;
for &b in src[start..].as_bytes() {
match b {
@@ -80,7 +71,24 @@ fn find_keyword(src: &str, pattern: &str, search: &str, search_type: SearchType,
_ => break
}
}
- if start == oldstart { return None; }
+ if start != oldstart { return Some(start); }
+ }
+ None
+}
+
+fn find_keyword(src: &str, pattern: &str, search: &str, search_type: SearchType, local: bool)
+-> Option<Point> {
+ // search for "^(pub\s+)?(unsafe\s+)?pattern\s+search"
+
+ // if not local must start with pub
+ if !local && !src.starts_with("pub") { return None; }
+
+ let mut start = 0usize;
+
+ // optional (pub\s+)?(unsafe\s+)?
+ for pat in ["pub", "unsafe"].into_iter() {
+ if let Some(prefix_len) = strip_keyword_prefix(&src[start..], pat) {
+ start += prefix_len;
}
}
@@ -262,7 +270,13 @@ pub fn match_extern_crate(msrc: &str, blobstart: Point, blobend: Point,
searchstr: &str, filepath: &Path, search_type: SearchType,
session: &Session) -> Option<Match> {
let mut res = None;
- let blob = &msrc[blobstart..blobend];
+ let mut blob = &msrc[blobstart..blobend];
+
+ // Temporary fix to parse reexported crates by skipping pub
+ // keyword until racer understands crate visibility.
+ if let Some(start) = strip_keyword_prefix(blob, "pub") {
+ blob = &blob[start..];
+ }
if txt_matches(search_type, &format!("extern crate {}", searchstr), blob) &&
!(txt_matches(search_type, &format!("extern crate {} as", searchstr), blob))
