├── .gitignore ├── test_data ├── exprs │ ├── Cargo.lock │ ├── Cargo.toml │ ├── src │ │ └── main.rs │ └── save-analysis │ │ └── exprs.json ├── hello │ ├── Cargo.lock │ ├── Cargo.toml │ ├── src │ │ └── main.rs │ └── save-analysis │ │ └── hello.json ├── types │ ├── Cargo.lock │ ├── Cargo.toml │ ├── src │ │ └── main.rs │ └── save-analysis │ │ └── types-e743a203eefaed5b.json ├── rename │ ├── Cargo.lock │ ├── Cargo.toml │ ├── src │ │ └── main.rs │ └── save-analysis │ │ └── rename.json ├── make_data.sh └── rust-analysis │ ├── libstd_unicode-919969778ffdc60a.json │ ├── libprofiler_builtins-50e7d4a810e2b7d4.json │ ├── librustc_asan-b2b370d757ab1d80.json │ ├── librustc_tsan-7c3a091fdb6e944e.json │ ├── libpanic_abort-627bb601930ec2f6.json │ ├── liballoc_system-efb53e76be37f014.json │ ├── liballoc_jemalloc-67da9297e5607113.json │ └── libpanic_unwind-4da7cb5dd1fef0c2.json ├── .travis.yml ├── README.md ├── Cargo.toml ├── src ├── util.rs ├── listings │ └── mod.rs ├── symbol_query.rs ├── raw.rs ├── loader.rs ├── analysis.rs ├── test │ └── mod.rs ├── lowering.rs └── lib.rs ├── examples └── print-crate-id.rs ├── benches └── std_api_crate.rs └── Cargo.lock /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | test 3 | -------------------------------------------------------------------------------- /test_data/exprs/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "exprs" 3 | version = "0.1.0" 4 | 5 | -------------------------------------------------------------------------------- /test_data/hello/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "hello" 3 | version = "0.1.0" 4 | 5 | -------------------------------------------------------------------------------- /test_data/types/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "types" 3 | version = "0.1.0" 4 | 5 | -------------------------------------------------------------------------------- /test_data/rename/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "rename" 3 | version = "0.1.0" 4 | 5 | -------------------------------------------------------------------------------- /test_data/exprs/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "exprs" 3 | version = "0.1.0" 4 | authors = ["Nick Cameron "] 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /test_data/hello/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "hello" 3 | version = "0.1.0" 4 | authors = ["Nick Cameron "] 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /test_data/rename/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rename" 3 | version = "0.1.0" 4 | authors = ["Nick Cameron "] 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /test_data/types/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "types" 3 | version = "0.1.0" 4 | authors = ["Nick Cameron "] 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /test_data/hello/src/main.rs: -------------------------------------------------------------------------------- 1 | fn print_hello() { 2 | let name = "world"; 3 | println!("Hello, {}!", name); 4 | } 5 | 6 | fn main() { 7 | print_hello(); 8 | } 9 | -------------------------------------------------------------------------------- /test_data/exprs/src/main.rs: -------------------------------------------------------------------------------- 1 | struct Foo; 2 | 3 | impl Foo { 4 | fn bar(&self) { 5 | let _ = self; 6 | } 7 | } 8 | 9 | pub extern "C" fn foo() {} 10 | 11 | fn main() { 12 | foo(); 13 | } 14 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | dist: trusty 3 | sudo: false 4 | cache: cargo 5 | os: 6 | - linux 7 | - osx 8 | rust: 9 | - nightly 10 | script: 11 | - cargo build --release --verbose 12 | - cargo test --release --verbose 13 | -------------------------------------------------------------------------------- /test_data/rename/src/main.rs: -------------------------------------------------------------------------------- 1 | mod a { 2 | pub fn bar() {} 3 | pub fn qux() {} 4 | } 5 | 6 | mod b { 7 | use a::qux; 8 | use a::bar as baz; 9 | 10 | pub fn foo() { 11 | qux(); 12 | baz(); 13 | } 14 | } 15 | 16 | fn main() {} 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/nrc/rls-analysis.svg?branch=master)](https://travis-ci.org/nrc/rls-analysis) 2 | 3 | # rls-analysis 4 | **NOTE:** Development has been moved to the central [RLS](https://github.com/rust-lang/rls) repository. 5 | 6 | Library for processing rustc's save-analysis data for the RLS. 7 | 8 | [API Documentation](https://docs.rs/rls-analysis/) 9 | -------------------------------------------------------------------------------- /test_data/types/src/main.rs: -------------------------------------------------------------------------------- 1 | struct Foo { 2 | f: u32, 3 | } 4 | 5 | fn main() { 6 | let x = Foo { f: 42 }; 7 | let _: Foo = x; 8 | } 9 | 10 | fn foo(x: Foo) -> Foo { 11 | let test_binding = true; 12 | const TEST_CONST: bool = true; 13 | static TEST_STATIC: u32 = 16; 14 | panic!(); 15 | } 16 | 17 | mod test_module { 18 | type TestType = u32; 19 | } 20 | 21 | union TestUnion { 22 | f1: u32 23 | } 24 | 25 | trait TestTrait { 26 | fn test_method(&self); 27 | } 28 | 29 | enum FooEnum { 30 | TupleVariant, 31 | StructVariant { x: u8 }, 32 | } 33 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rls-analysis" 3 | version = "0.16.12" 4 | authors = ["Nick Cameron "] 5 | description = "Library for processing rustc's save-analysis data for the RLS" 6 | license = "Apache-2.0/MIT" 7 | repository = "https://github.com/rust-dev-tools/rls-analysis" 8 | categories = ["development-tools"] 9 | exclude = [ 10 | "test_data/*", 11 | ] 12 | 13 | [dependencies] 14 | rustc-serialize = "0.3" 15 | log = "0.4" 16 | rls-data = "= 0.18.2" 17 | rls-span = "0.4" 18 | derive-new = "0.5" 19 | fst = { version = "0.3", default-features = false } 20 | itertools = "0.7.3" 21 | json = "0.11.13" 22 | 23 | [dev-dependencies] 24 | lazy_static = "1" 25 | env_logger = "0.5" 26 | -------------------------------------------------------------------------------- /src/util.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The RLS Project Developers. 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | #[cfg(unix)] 10 | pub fn get_resident() -> Option { 11 | use std::fs::File; 12 | use std::io::Read; 13 | 14 | let field = 1; 15 | let mut f = File::open("/proc/self/statm").ok()?; 16 | let mut contents = String::new(); 17 | f.read_to_string(&mut contents).ok()?; 18 | let s = contents.split_whitespace().nth(field)?; 19 | let npages = s.parse::().ok()?; 20 | Some(npages * 4096) 21 | } 22 | 23 | #[cfg(not(unix))] 24 | pub fn get_resident() -> Option { 25 | None 26 | } 27 | -------------------------------------------------------------------------------- /test_data/make_data.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This script reproduces all save-analysis data in the test_data directories. 3 | 4 | # $1 is where to run cargo build 5 | # $2 is the output dir 6 | function build { 7 | echo "$1 => $2" 8 | output="$(pwd)/$2" 9 | pushd "$1" > /dev/null 10 | RUSTFLAGS=-Zsave-analysis cargo build 11 | cp target/debug/deps/save-analysis/*.json "$output" 12 | # strip all hashes from filenames libfoo-[hash].json -> libfoo.json 13 | for from in $output/*.json; do 14 | to=$(echo "$from" | sed -e "s/\(.*\)-[a-f0-9]*.json/\1.json/1") 15 | mv "$from" "$to" 16 | done 17 | popd > /dev/null 18 | } 19 | 20 | # Data for rls-analysis. This is essentially a bootstrap. Be careful when using 21 | # this data because the source is not pinned, therefore the data will change 22 | # regularly. It should basically just be used as a 'big'-ish set of real-world 23 | # data for smoke testing. 24 | 25 | rm rls-analysis/*.json 26 | build .. rls-analysis 27 | 28 | # Hello world test case 29 | build hello hello/save-analysis 30 | 31 | # Types 32 | build types types/save-analysis 33 | 34 | # Expressions 35 | build exprs exprs/save-analysis 36 | 37 | # all_ref_unique 38 | build rename rename/save-analysis 39 | -------------------------------------------------------------------------------- /examples/print-crate-id.rs: -------------------------------------------------------------------------------- 1 | extern crate rls_analysis; 2 | extern crate env_logger; 3 | 4 | use rls_analysis::{AnalysisHost, AnalysisLoader, SearchDirectory}; 5 | use std::path::{Path, PathBuf}; 6 | use std::env; 7 | 8 | #[derive(Clone)] 9 | pub struct Loader { 10 | deps_dir: PathBuf, 11 | } 12 | 13 | impl Loader { 14 | pub fn new(deps_dir: PathBuf) -> Self { 15 | Self { deps_dir } 16 | } 17 | } 18 | 19 | impl AnalysisLoader for Loader { 20 | fn needs_hard_reload(&self, _: &Path) -> bool { 21 | true 22 | } 23 | 24 | fn fresh_host(&self) -> AnalysisHost { 25 | AnalysisHost::new_with_loader(self.clone()) 26 | } 27 | 28 | fn set_path_prefix(&mut self, _: &Path) {} 29 | 30 | fn abs_path_prefix(&self) -> Option { 31 | None 32 | } 33 | fn search_directories(&self) -> Vec { 34 | vec![SearchDirectory { 35 | path: self.deps_dir.clone(), 36 | prefix_rewrite: None, 37 | }] 38 | } 39 | } 40 | 41 | fn main() { 42 | env_logger::init(); 43 | if env::args().len() < 2 { 44 | println!("Usage: print-crate-id "); 45 | std::process::exit(1); 46 | } 47 | let loader = Loader::new(PathBuf::from(env::args().nth(1).unwrap())); 48 | let crates = rls_analysis::read_analysis_from_files(&loader, Default::default(), &[]); 49 | 50 | for krate in &crates { 51 | println!("Crate {:?} data version {:?}", krate.id, krate.analysis.version); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/listings/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The RLS Project Developers. 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | use std::io; 10 | use std::path::Path; 11 | use std::time::SystemTime; 12 | 13 | #[derive(Debug, Clone)] 14 | pub struct DirectoryListing { 15 | pub path: Vec, 16 | pub files: Vec, 17 | } 18 | 19 | #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)] 20 | pub struct Listing { 21 | pub kind: ListingKind, 22 | pub name: String, 23 | } 24 | 25 | #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)] 26 | pub enum ListingKind { 27 | Directory, 28 | // Time last modified. 29 | File(SystemTime), 30 | } 31 | 32 | impl DirectoryListing { 33 | pub fn from_path(path: &Path) -> io::Result { 34 | let mut files = vec![]; 35 | let dir = path.read_dir()?; 36 | 37 | for entry in dir { 38 | if let Ok(entry) = entry { 39 | let name = entry.file_name().to_str().unwrap().to_owned(); 40 | if let Ok(file_type) = entry.file_type() { 41 | if file_type.is_dir() { 42 | files.push(Listing { 43 | kind: ListingKind::Directory, 44 | name: name, 45 | }); 46 | } else if file_type.is_file() { 47 | files.push(Listing { 48 | kind: ListingKind::File(entry.metadata()?.modified()?), 49 | name: name, 50 | }); 51 | } 52 | } 53 | } 54 | } 55 | 56 | files.sort(); 57 | 58 | Ok(DirectoryListing { 59 | path: path.components() 60 | .map(|c| c.as_os_str().to_str().unwrap().to_owned()) 61 | .collect(), 62 | files, 63 | }) 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /benches/std_api_crate.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The RLS Project Developers. 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | #![feature(test)] 10 | 11 | extern crate rls_analysis; 12 | #[macro_use] 13 | extern crate derive_new; 14 | #[macro_use] 15 | extern crate lazy_static; 16 | extern crate test; 17 | use test::Bencher; 18 | 19 | use std::path::{Path, PathBuf}; 20 | use std::sync::RwLock; 21 | 22 | use rls_analysis::{AnalysisHost, AnalysisLoader, SearchDirectory}; 23 | 24 | #[derive(Clone, new)] 25 | struct TestAnalysisLoader { 26 | path: PathBuf, 27 | } 28 | 29 | impl AnalysisLoader for TestAnalysisLoader { 30 | fn needs_hard_reload(&self, _path_prefix: &Path) -> bool { 31 | true 32 | } 33 | 34 | fn fresh_host(&self) -> AnalysisHost { 35 | AnalysisHost::new_with_loader(self.clone()) 36 | } 37 | 38 | fn set_path_prefix(&mut self, _path_prefix: &Path) {} 39 | 40 | fn abs_path_prefix(&self) -> Option { 41 | panic!(); 42 | } 43 | 44 | fn search_directories(&self) -> Vec { 45 | vec![SearchDirectory::new(self.path.clone(), None)] 46 | } 47 | } 48 | 49 | lazy_static! { 50 | static ref STDLIB_FILE_PATH: PathBuf = PathBuf::from("/checkout/src/libstd/lib.rs"); 51 | static ref STDLIB_DATA_PATH: PathBuf = PathBuf::from("test_data/rust-analysis"); 52 | 53 | static ref HOST: RwLock> = { 54 | let host = AnalysisHost::new_with_loader(TestAnalysisLoader::new( 55 | STDLIB_DATA_PATH.clone(), 56 | )); 57 | host.reload(&STDLIB_DATA_PATH, &STDLIB_DATA_PATH).unwrap(); 58 | RwLock::new(host) 59 | }; 60 | } 61 | 62 | #[bench] 63 | fn search_for_id(b: &mut Bencher) { 64 | let host = HOST.read().unwrap(); 65 | 66 | b.iter(|| { 67 | let _ = host.search_for_id("no_std"); 68 | }); 69 | } 70 | 71 | #[bench] 72 | fn search(b: &mut Bencher) { 73 | let host = HOST.read().unwrap(); 74 | b.iter(|| { 75 | let _ = host.search("some_inexistent_symbol"); 76 | 77 | }) 78 | } 79 | 80 | #[bench] 81 | fn symbols(b: &mut Bencher) { 82 | let host = HOST.read().unwrap(); 83 | b.iter(|| { 84 | let _ = host.symbols(&STDLIB_FILE_PATH); 85 | }) 86 | } 87 | 88 | #[bench] 89 | fn reload(b: &mut Bencher) { 90 | let host = HOST.write().unwrap(); 91 | b.iter(|| { 92 | host.reload(&STDLIB_DATA_PATH, &STDLIB_DATA_PATH).unwrap(); 93 | }) 94 | } -------------------------------------------------------------------------------- /test_data/rust-analysis/libstd_unicode-919969778ffdc60a.json: -------------------------------------------------------------------------------- 1 | {"config":{"output_file":null,"full_docs":false,"pub_only":true,"reachable_only":false,"distro_crate":true,"signatures":false,"borrow_data":false},"prelude":{"crate_id":{"name":"std_unicode","disambiguator":[8827476480046634576,10577496379195961843]},"crate_root":"libstd_unicode","external_crates":[{"file_name":"/Users/travis/build/rust-lang/rust/src/libstd_unicode/lib.rs","num":1,"id":{"name":"compiler_builtins","disambiguator":[12047234932576597458,5077187143126647032]}},{"file_name":"/Users/travis/build/rust-lang/rust/src/libstd_unicode/lib.rs","num":2,"id":{"name":"core","disambiguator":[12641647969103297473,10130382509811922120]}}],"span":{"file_name":[108,105,98,115,116,100,95,117,110,105,99,111,100,101,47,108,105,98,46,114,115],"byte_start":472,"byte_end":1618,"line_start":11,"line_end":36,"column_start":1,"column_end":26}},"imports":[{"kind":"GlobUse","ref_id":null,"span":{"file_name":[108,105,98,115,116,100,95,117,110,105,99,111,100,101,47,108,105,98,46,114,115],"byte_start":1616,"byte_end":1617,"line_start":36,"line_end":36,"column_start":24,"column_end":25},"name":"*","value":"","parent":{"krate":0,"index":0}}],"defs":[{"kind":"Mod","id":{"krate":0,"index":0},"span":{"file_name":[108,105,98,115,116,100,95,117,110,105,99,111,100,101,47,108,105,98,46,114,115],"byte_start":472,"byte_end":1618,"line_start":11,"line_end":36,"column_start":1,"column_end":26},"name":"","qualname":"::","value":"libstd_unicode/lib.rs","parent":null,"children":[{"krate":0,"index":2},{"krate":0,"index":4},{"krate":0,"index":6},{"krate":0,"index":8}],"decl_id":null,"docs":" # The Unicode Library","sig":null,"attributes":[{"value":"unstable(feature = \"unicode\", issue = \"27783\")","span":{"file_name":[108,105,98,115,116,100,95,117,110,105,99,111,100,101,47,108,105,98,46,114,115],"byte_start":974,"byte_end":1024,"line_start":23,"line_end":23,"column_start":1,"column_end":51}},{"value":"no_std","span":{"file_name":[108,105,98,115,116,100,95,117,110,105,99,111,100,101,47,108,105,98,46,114,115],"byte_start":1455,"byte_end":1465,"line_start":30,"line_end":30,"column_start":1,"column_end":11}},{"value":"feature(unicode_internals)","span":{"file_name":[108,105,98,115,116,100,95,117,110,105,99,111,100,101,47,108,105,98,46,114,115],"byte_start":1467,"byte_end":1497,"line_start":32,"line_end":32,"column_start":1,"column_end":31}},{"value":"feature(staged_api)","span":{"file_name":[108,105,98,115,116,100,95,117,110,105,99,111,100,101,47,108,105,98,46,114,115],"byte_start":1498,"byte_end":1521,"line_start":33,"line_end":33,"column_start":1,"column_end":24}},{"value":"rustc_deprecated(since = \"1.27.0\", reason = \"moved into libcore\")","span":{"file_name":[108,105,98,115,116,100,95,117,110,105,99,111,100,101,47,108,105,98,46,114,115],"byte_start":1522,"byte_end":1591,"line_start":34,"line_end":34,"column_start":1,"column_end":70}}]}],"impls":[],"refs":[],"macro_refs":[],"relations":[]} -------------------------------------------------------------------------------- /test_data/rust-analysis/libprofiler_builtins-50e7d4a810e2b7d4.json: -------------------------------------------------------------------------------- 1 | {"config":{"output_file":null,"full_docs":false,"pub_only":true,"reachable_only":false,"distro_crate":true,"signatures":false,"borrow_data":false},"prelude":{"crate_id":{"name":"profiler_builtins","disambiguator":[6367140109538088216,512491525313494260]},"crate_root":"libprofiler_builtins","external_crates":[{"file_name":"/Users/travis/build/rust-lang/rust/src/libprofiler_builtins/lib.rs","num":1,"id":{"name":"compiler_builtins","disambiguator":[12047234932576597458,5077187143126647032]}},{"file_name":"/Users/travis/build/rust-lang/rust/src/libprofiler_builtins/lib.rs","num":2,"id":{"name":"core","disambiguator":[12641647969103297473,10130382509811922120]}}],"span":{"file_name":[108,105,98,112,114,111,102,105,108,101,114,95,98,117,105,108,116,105,110,115,47,108,105,98,46,114,115],"byte_start":467,"byte_end":725,"line_start":11,"line_end":18,"column_start":1,"column_end":24}},"imports":[],"defs":[{"kind":"Mod","id":{"krate":0,"index":0},"span":{"file_name":[108,105,98,112,114,111,102,105,108,101,114,95,98,117,105,108,116,105,110,115,47,108,105,98,46,114,115],"byte_start":467,"byte_end":725,"line_start":11,"line_end":18,"column_start":1,"column_end":24},"name":"","qualname":"::","value":"libprofiler_builtins/lib.rs","parent":null,"children":[{"krate":0,"index":2},{"krate":0,"index":4},{"krate":0,"index":6}],"decl_id":null,"docs":"","sig":null,"attributes":[{"value":"no_std","span":{"file_name":[108,105,98,112,114,111,102,105,108,101,114,95,98,117,105,108,116,105,110,115,47,108,105,98,46,114,115],"byte_start":467,"byte_end":477,"line_start":11,"line_end":11,"column_start":1,"column_end":11}},{"value":"feature(profiler_runtime)","span":{"file_name":[108,105,98,112,114,111,102,105,108,101,114,95,98,117,105,108,116,105,110,115,47,108,105,98,46,114,115],"byte_start":478,"byte_end":507,"line_start":12,"line_end":12,"column_start":1,"column_end":30}},{"value":"profiler_runtime","span":{"file_name":[108,105,98,112,114,111,102,105,108,101,114,95,98,117,105,108,116,105,110,115,47,108,105,98,46,114,115],"byte_start":508,"byte_end":528,"line_start":13,"line_end":13,"column_start":1,"column_end":21}},{"value":"unstable(feature = \"profiler_runtime_lib\",\n reason = \"internal implementation detail of rustc right now\",\n issue = \"0\")","span":{"file_name":[108,105,98,112,114,111,102,105,108,101,114,95,98,117,105,108,116,105,110,115,47,108,105,98,46,114,115],"byte_start":529,"byte_end":674,"line_start":14,"line_end":16,"column_start":1,"column_end":26}},{"value":"allow(unused_features)","span":{"file_name":[108,105,98,112,114,111,102,105,108,101,114,95,98,117,105,108,116,105,110,115,47,108,105,98,46,114,115],"byte_start":675,"byte_end":701,"line_start":17,"line_end":17,"column_start":1,"column_end":27}},{"value":"feature(staged_api)","span":{"file_name":[108,105,98,112,114,111,102,105,108,101,114,95,98,117,105,108,116,105,110,115,47,108,105,98,46,114,115],"byte_start":702,"byte_end":725,"line_start":18,"line_end":18,"column_start":1,"column_end":24}}]}],"impls":[],"refs":[],"macro_refs":[],"relations":[]} -------------------------------------------------------------------------------- /test_data/rust-analysis/librustc_asan-b2b370d757ab1d80.json: -------------------------------------------------------------------------------- 1 | {"config":{"output_file":null,"full_docs":false,"pub_only":true,"reachable_only":false,"distro_crate":true,"signatures":false,"borrow_data":false},"prelude":{"crate_id":{"name":"rustc_asan","disambiguator":[9901366168080351187,2157845742380160464]},"crate_root":"librustc_asan","external_crates":[{"file_name":"/Users/travis/build/rust-lang/rust/src/librustc_asan/lib.rs","num":1,"id":{"name":"compiler_builtins","disambiguator":[12047234932576597458,5077187143126647032]}},{"file_name":"/Users/travis/build/rust-lang/rust/src/librustc_asan/lib.rs","num":2,"id":{"name":"core","disambiguator":[12641647969103297473,10130382509811922120]}},{"file_name":"/Users/travis/build/rust-lang/rust/src/librustc_asan/lib.rs","num":3,"id":{"name":"alloc_system","disambiguator":[12248884017658358091,17580744942517357114]}},{"file_name":"/Users/travis/build/rust-lang/rust/src/librustc_asan/lib.rs","num":4,"id":{"name":"libc","disambiguator":[10677312091366318875,12914270607935649197]}}],"span":{"file_name":[108,105,98,114,117,115,116,99,95,97,115,97,110,47,108,105,98,46,114,115],"byte_start":467,"byte_end":886,"line_start":11,"line_end":27,"column_start":1,"column_end":31}},"imports":[],"defs":[{"kind":"Mod","id":{"krate":0,"index":0},"span":{"file_name":[108,105,98,114,117,115,116,99,95,97,115,97,110,47,108,105,98,46,114,115],"byte_start":467,"byte_end":886,"line_start":11,"line_end":27,"column_start":1,"column_end":31},"name":"","qualname":"::","value":"librustc_asan/lib.rs","parent":null,"children":[{"krate":0,"index":2},{"krate":0,"index":4},{"krate":0,"index":6},{"krate":0,"index":8},{"krate":0,"index":10},{"krate":0,"index":12},{"krate":0,"index":14}],"decl_id":null,"docs":"","sig":null,"attributes":[{"value":"sanitizer_runtime","span":{"file_name":[108,105,98,114,117,115,116,99,95,97,115,97,110,47,108,105,98,46,114,115],"byte_start":467,"byte_end":488,"line_start":11,"line_end":11,"column_start":1,"column_end":22}},{"value":"feature(alloc_system)","span":{"file_name":[108,105,98,114,117,115,116,99,95,97,115,97,110,47,108,105,98,46,114,115],"byte_start":489,"byte_end":514,"line_start":12,"line_end":12,"column_start":1,"column_end":26}},{"value":"feature(allocator_api)","span":{"file_name":[108,105,98,114,117,115,116,99,95,97,115,97,110,47,108,105,98,46,114,115],"byte_start":515,"byte_end":541,"line_start":13,"line_end":13,"column_start":1,"column_end":27}},{"value":"feature(global_allocator)","span":{"file_name":[108,105,98,114,117,115,116,99,95,97,115,97,110,47,108,105,98,46,114,115],"byte_start":542,"byte_end":571,"line_start":14,"line_end":14,"column_start":1,"column_end":30}},{"value":"feature(sanitizer_runtime)","span":{"file_name":[108,105,98,114,117,115,116,99,95,97,115,97,110,47,108,105,98,46,114,115],"byte_start":572,"byte_end":602,"line_start":15,"line_end":15,"column_start":1,"column_end":31}},{"value":"feature(staged_api)","span":{"file_name":[108,105,98,114,117,115,116,99,95,97,115,97,110,47,108,105,98,46,114,115],"byte_start":603,"byte_end":626,"line_start":16,"line_end":16,"column_start":1,"column_end":24}},{"value":"no_std","span":{"file_name":[108,105,98,114,117,115,116,99,95,97,115,97,110,47,108,105,98,46,114,115],"byte_start":627,"byte_end":637,"line_start":17,"line_end":17,"column_start":1,"column_end":11}},{"value":"unstable(feature = \"sanitizer_runtime_lib\",\n reason = \"internal implementation detail of sanitizers\",\n issue = \"0\")","span":{"file_name":[108,105,98,114,117,115,116,99,95,97,115,97,110,47,108,105,98,46,114,115],"byte_start":638,"byte_end":779,"line_start":18,"line_end":20,"column_start":1,"column_end":26}}]}],"impls":[],"refs":[],"macro_refs":[],"relations":[]} -------------------------------------------------------------------------------- /test_data/rust-analysis/librustc_tsan-7c3a091fdb6e944e.json: -------------------------------------------------------------------------------- 1 | {"config":{"output_file":null,"full_docs":false,"pub_only":true,"reachable_only":false,"distro_crate":true,"signatures":false,"borrow_data":false},"prelude":{"crate_id":{"name":"rustc_tsan","disambiguator":[9705872482283351085,6609562665756847170]},"crate_root":"librustc_tsan","external_crates":[{"file_name":"/Users/travis/build/rust-lang/rust/src/librustc_tsan/lib.rs","num":1,"id":{"name":"compiler_builtins","disambiguator":[12047234932576597458,5077187143126647032]}},{"file_name":"/Users/travis/build/rust-lang/rust/src/librustc_tsan/lib.rs","num":2,"id":{"name":"core","disambiguator":[12641647969103297473,10130382509811922120]}},{"file_name":"/Users/travis/build/rust-lang/rust/src/librustc_tsan/lib.rs","num":3,"id":{"name":"alloc_system","disambiguator":[12248884017658358091,17580744942517357114]}},{"file_name":"/Users/travis/build/rust-lang/rust/src/librustc_tsan/lib.rs","num":4,"id":{"name":"libc","disambiguator":[10677312091366318875,12914270607935649197]}}],"span":{"file_name":[108,105,98,114,117,115,116,99,95,116,115,97,110,47,108,105,98,46,114,115],"byte_start":467,"byte_end":886,"line_start":11,"line_end":27,"column_start":1,"column_end":31}},"imports":[],"defs":[{"kind":"Mod","id":{"krate":0,"index":0},"span":{"file_name":[108,105,98,114,117,115,116,99,95,116,115,97,110,47,108,105,98,46,114,115],"byte_start":467,"byte_end":886,"line_start":11,"line_end":27,"column_start":1,"column_end":31},"name":"","qualname":"::","value":"librustc_tsan/lib.rs","parent":null,"children":[{"krate":0,"index":2},{"krate":0,"index":4},{"krate":0,"index":6},{"krate":0,"index":8},{"krate":0,"index":10},{"krate":0,"index":12},{"krate":0,"index":14}],"decl_id":null,"docs":"","sig":null,"attributes":[{"value":"sanitizer_runtime","span":{"file_name":[108,105,98,114,117,115,116,99,95,116,115,97,110,47,108,105,98,46,114,115],"byte_start":467,"byte_end":488,"line_start":11,"line_end":11,"column_start":1,"column_end":22}},{"value":"feature(alloc_system)","span":{"file_name":[108,105,98,114,117,115,116,99,95,116,115,97,110,47,108,105,98,46,114,115],"byte_start":489,"byte_end":514,"line_start":12,"line_end":12,"column_start":1,"column_end":26}},{"value":"feature(allocator_api)","span":{"file_name":[108,105,98,114,117,115,116,99,95,116,115,97,110,47,108,105,98,46,114,115],"byte_start":515,"byte_end":541,"line_start":13,"line_end":13,"column_start":1,"column_end":27}},{"value":"feature(global_allocator)","span":{"file_name":[108,105,98,114,117,115,116,99,95,116,115,97,110,47,108,105,98,46,114,115],"byte_start":542,"byte_end":571,"line_start":14,"line_end":14,"column_start":1,"column_end":30}},{"value":"feature(sanitizer_runtime)","span":{"file_name":[108,105,98,114,117,115,116,99,95,116,115,97,110,47,108,105,98,46,114,115],"byte_start":572,"byte_end":602,"line_start":15,"line_end":15,"column_start":1,"column_end":31}},{"value":"feature(staged_api)","span":{"file_name":[108,105,98,114,117,115,116,99,95,116,115,97,110,47,108,105,98,46,114,115],"byte_start":603,"byte_end":626,"line_start":16,"line_end":16,"column_start":1,"column_end":24}},{"value":"no_std","span":{"file_name":[108,105,98,114,117,115,116,99,95,116,115,97,110,47,108,105,98,46,114,115],"byte_start":627,"byte_end":637,"line_start":17,"line_end":17,"column_start":1,"column_end":11}},{"value":"unstable(feature = \"sanitizer_runtime_lib\",\n reason = \"internal implementation detail of sanitizers\",\n issue = \"0\")","span":{"file_name":[108,105,98,114,117,115,116,99,95,116,115,97,110,47,108,105,98,46,114,115],"byte_start":638,"byte_end":779,"line_start":18,"line_end":20,"column_start":1,"column_end":26}}]}],"impls":[],"refs":[],"macro_refs":[],"relations":[]} -------------------------------------------------------------------------------- /test_data/exprs/save-analysis/exprs.json: -------------------------------------------------------------------------------- 1 | {"config":{"output_file":null,"full_docs":false,"pub_only":false,"reachable_only":false,"distro_crate":false,"signatures":false,"borrow_data":false},"prelude":{"crate_id":{"name":"exprs","disambiguator":[6574077688061423980,8017575010758930686]},"crate_root":"src","external_crates":[{"file_name":"/Users/nick/version-controlled/rls-analysis/test_data/exprs/src/main.rs","num":1,"id":{"name":"std","disambiguator":[6489337983672760984,1544662242798124353]}},{"file_name":"/Users/nick/version-controlled/rls-analysis/test_data/exprs/src/main.rs","num":2,"id":{"name":"compiler_builtins","disambiguator":[12047234932576597458,5077187143126647032]}},{"file_name":"/Users/nick/version-controlled/rls-analysis/test_data/exprs/src/main.rs","num":3,"id":{"name":"core","disambiguator":[12641647969103297473,10130382509811922120]}},{"file_name":"/Users/nick/version-controlled/rls-analysis/test_data/exprs/src/main.rs","num":4,"id":{"name":"alloc","disambiguator":[7492281898511940165,14124905697399198535]}},{"file_name":"/Users/nick/version-controlled/rls-analysis/test_data/exprs/src/main.rs","num":5,"id":{"name":"alloc_system","disambiguator":[12248884017658358091,17580744942517357114]}},{"file_name":"/Users/nick/version-controlled/rls-analysis/test_data/exprs/src/main.rs","num":6,"id":{"name":"libc","disambiguator":[10677312091366318875,12914270607935649197]}},{"file_name":"/Users/nick/version-controlled/rls-analysis/test_data/exprs/src/main.rs","num":7,"id":{"name":"unwind","disambiguator":[13357724146610223715,10513570149384825499]}},{"file_name":"/Users/nick/version-controlled/rls-analysis/test_data/exprs/src/main.rs","num":8,"id":{"name":"alloc_jemalloc","disambiguator":[17994208587689535795,10583317287541686664]}},{"file_name":"/Users/nick/version-controlled/rls-analysis/test_data/exprs/src/main.rs","num":9,"id":{"name":"panic_unwind","disambiguator":[1643721027292504100,10916951709470146856]}}],"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":0,"byte_end":127,"line_start":1,"line_end":13,"column_start":1,"column_end":2}},"imports":[],"defs":[{"kind":"Mod","id":{"krate":0,"index":0},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":0,"byte_end":127,"line_start":1,"line_end":13,"column_start":1,"column_end":2},"name":"","qualname":"::","value":"src/main.rs","parent":null,"children":[{"krate":0,"index":2},{"krate":0,"index":4},{"krate":0,"index":6},{"krate":0,"index":8},{"krate":0,"index":12},{"krate":0,"index":14}],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Struct","id":{"krate":0,"index":6},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":7,"byte_end":10,"line_start":1,"line_end":1,"column_start":8,"column_end":11},"name":"Foo","qualname":"::Foo","value":"","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Local","id":{"krate":0,"index":4294967282},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":36,"byte_end":40,"line_start":4,"line_end":4,"column_start":13,"column_end":17},"name":"self","qualname":"::bar::self","value":"&Foo","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Method","id":{"krate":0,"index":10},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":31,"byte_end":34,"line_start":4,"line_end":4,"column_start":8,"column_end":11},"name":"bar","qualname":"::bar","value":"fn (&self) -> ()","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Function","id":{"krate":0,"index":12},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":93,"byte_end":96,"line_start":9,"line_end":9,"column_start":19,"column_end":22},"name":"foo","qualname":"::foo","value":"fn () -> ()","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Function","id":{"krate":0,"index":14},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":106,"byte_end":110,"line_start":11,"line_end":11,"column_start":4,"column_end":8},"name":"main","qualname":"::main","value":"fn () -> ()","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]}],"impls":[{"id":0,"kind":"Inherent","span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":18,"byte_end":21,"line_start":3,"line_end":3,"column_start":6,"column_end":9},"value":"","parent":null,"children":[{"krate":0,"index":10}],"docs":"","sig":null,"attributes":[]}],"refs":[{"kind":"Mod","span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":0,"byte_end":0,"line_start":1,"line_end":1,"column_start":1,"column_end":1},"ref_id":{"krate":4294967295,"index":4294967295}},{"kind":"Mod","span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":0,"byte_end":0,"line_start":1,"line_end":1,"column_start":1,"column_end":1},"ref_id":{"krate":4294967295,"index":4294967295}},{"kind":"Mod","span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":0,"byte_end":0,"line_start":1,"line_end":1,"column_start":1,"column_end":1},"ref_id":{"krate":4294967295,"index":4294967295}},{"kind":"Type","span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":18,"byte_end":21,"line_start":3,"line_end":3,"column_start":6,"column_end":9},"ref_id":{"krate":0,"index":6}},{"kind":"Variable","span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":60,"byte_end":64,"line_start":5,"line_end":5,"column_start":17,"column_end":21},"ref_id":{"krate":0,"index":4294967282}},{"kind":"Function","span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":119,"byte_end":122,"line_start":12,"line_end":12,"column_start":5,"column_end":8},"ref_id":{"krate":0,"index":12}}],"macro_refs":[],"relations":[{"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":18,"byte_end":21,"line_start":3,"line_end":3,"column_start":6,"column_end":9},"kind":{"variant":"Impl","fields":[0]},"from":{"krate":0,"index":6},"to":{"krate":4294967295,"index":4294967295}}]} -------------------------------------------------------------------------------- /src/symbol_query.rs: -------------------------------------------------------------------------------- 1 | use fst::{self, Streamer}; 2 | 3 | /// `SymbolQuery` specifies the preficate for filtering symbols by name. 4 | /// 5 | /// All matching is case-insensitive. Filtering by prefix or by subsequence 6 | /// is supported, subsequence being a good default choice. 7 | /// 8 | /// As the number of results might be huge, consider the `limit` hint, 9 | /// which serves as *approximate* limit on the number of results returned. 10 | /// 11 | /// To implement async streaming/pagination, use `greater_than` together with 12 | /// `limit`. 13 | #[derive(Debug)] 14 | pub struct SymbolQuery { 15 | query_string: String, 16 | mode: Mode, 17 | limit: usize, 18 | greater_than: String, 19 | } 20 | 21 | #[derive(Debug, Clone, Copy)] 22 | enum Mode { Prefix, Subsequence } 23 | 24 | impl SymbolQuery { 25 | fn new(query_string: String, mode: Mode) -> SymbolQuery { 26 | SymbolQuery { 27 | query_string, mode, 28 | limit: usize::max_value(), 29 | greater_than: String::new() 30 | } 31 | } 32 | 33 | pub fn subsequence(query_string: &str) -> SymbolQuery { 34 | SymbolQuery::new(query_string.to_lowercase(), Mode::Subsequence) 35 | } 36 | 37 | pub fn prefix(query_string: &str) -> SymbolQuery { 38 | SymbolQuery::new(query_string.to_lowercase(), Mode::Prefix) 39 | } 40 | 41 | pub fn limit(self, limit: usize) -> SymbolQuery { 42 | SymbolQuery { limit, ..self } 43 | } 44 | 45 | pub fn greater_than(self, greater_than: &str) -> SymbolQuery { 46 | SymbolQuery { greater_than: greater_than.to_lowercase(), ..self } 47 | } 48 | 49 | pub(crate) fn build_stream<'a, I>(&'a self, fsts: I) -> fst::map::Union<'a> 50 | where 51 | I: Iterator, 52 | { 53 | let mut stream = fst::map::OpBuilder::new(); 54 | let automaton = QueryAutomaton { query: &self.query_string, mode: self.mode }; 55 | for fst in fsts { 56 | stream = stream.add( 57 | fst.search(automaton).gt(&self.greater_than) 58 | ); 59 | } 60 | stream.union() 61 | } 62 | 63 | pub(crate) fn search_stream(&self, mut stream: fst::map::Union, f: F) -> Vec 64 | where 65 | F: Fn(&mut Vec, &fst::map::IndexedValue), 66 | { 67 | let mut res = Vec::new(); 68 | while let Some((_, entries)) = stream.next() { 69 | for e in entries { 70 | f(&mut res, e); 71 | } 72 | if res.len() >= self.limit { 73 | break; 74 | } 75 | } 76 | res 77 | } 78 | } 79 | 80 | /// See http://docs.rs/fst for how we implement query processing. 81 | /// 82 | /// In a nutshell, both the query and the set of available symbols 83 | /// are encoded as two finite state machines. Then, the intersection 84 | /// of state machines is built, which gives all the symbols matching 85 | /// the query. 86 | /// 87 | /// The `fst::Automaton` impl below implements a state machine for 88 | /// the query, where the state is the number of bytes already matched. 89 | #[derive(Clone, Copy)] 90 | struct QueryAutomaton<'a> { 91 | query: &'a str, 92 | mode: Mode, 93 | } 94 | 95 | const NO_MATCH: usize = !0; 96 | 97 | impl<'a> fst::Automaton for QueryAutomaton<'a> { 98 | type State = usize; 99 | 100 | fn start(&self) -> usize { 101 | 0 102 | } 103 | 104 | fn is_match(&self, &state: &usize) -> bool { 105 | state == self.query.len() 106 | } 107 | 108 | fn accept(&self, &state: &usize, byte: u8) -> usize { 109 | if state == NO_MATCH { 110 | return state; 111 | } 112 | if state == self.query.len() { 113 | return state; 114 | } 115 | if byte == self.query.as_bytes()[state] { 116 | return state + 1; 117 | } 118 | match self.mode { 119 | Mode::Prefix => NO_MATCH, 120 | Mode::Subsequence => state, 121 | } 122 | } 123 | 124 | fn can_match(&self, &state: &usize) -> bool { 125 | state != NO_MATCH 126 | } 127 | 128 | fn will_always_match(&self, &state: &usize) -> bool { 129 | state == self.query.len() 130 | } 131 | } 132 | 133 | #[cfg(test)] 134 | mod tests { 135 | use super::*; 136 | use std::iter; 137 | 138 | const STARS: &[&str] = &[ 139 | "agena", 140 | "agreetor", 141 | "algerib", 142 | "anektor", 143 | "antares", 144 | "arcturus", 145 | "canopus", 146 | "capella", 147 | "duendin", 148 | "golubin", 149 | "lalandry", 150 | "spica", 151 | "vega", 152 | ]; 153 | 154 | fn check( 155 | q: SymbolQuery, 156 | expected: &[&str] 157 | ) { 158 | let map = fst::Map::from_iter(STARS.iter() 159 | .enumerate() 160 | .map(|(i, &s)| (s, i as u64))) 161 | .unwrap(); 162 | let stream = q.build_stream(iter::once(&map)); 163 | let actual = q.search_stream(stream, |acc, iv| acc.push(STARS[iv.value as usize])); 164 | assert_eq!(expected, actual.as_slice()); 165 | } 166 | 167 | #[test] 168 | fn test_automaton() { 169 | check(SymbolQuery::prefix("an"), &[ 170 | "anektor", "antares", 171 | ]); 172 | 173 | check(SymbolQuery::subsequence("an"), &[ 174 | "agena", "anektor", "antares", "canopus", "lalandry" 175 | ]); 176 | 177 | check(SymbolQuery::subsequence("an").limit(2), &[ 178 | "agena", "anektor", 179 | ]); 180 | check(SymbolQuery::subsequence("an").limit(2).greater_than("anektor"), &[ 181 | "antares", "canopus", 182 | ]); 183 | check(SymbolQuery::subsequence("an").limit(2).greater_than("canopus"), &[ 184 | "lalandry", 185 | ]); 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /src/raw.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The RLS Project Developers. 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | use {AnalysisLoader, Blacklist}; 10 | use json; 11 | use listings::{DirectoryListing, ListingKind}; 12 | pub use data::{CratePreludeData, Def, DefKind, GlobalCrateId as CrateId, Import, 13 | Ref, Relation, RelationKind, SigElement, Signature, SpanData}; 14 | use data::Analysis; 15 | use data::config::Config; 16 | 17 | use std::collections::HashMap; 18 | use std::fs::File; 19 | use std::io::{self, Read}; 20 | use std::path::{Path, PathBuf}; 21 | use std::time::{Instant, SystemTime}; 22 | 23 | #[derive(Debug)] 24 | pub struct Crate { 25 | pub id: CrateId, 26 | pub analysis: Analysis, 27 | pub timestamp: SystemTime, 28 | pub path: Option, 29 | pub path_rewrite: Option, 30 | } 31 | 32 | impl Crate { 33 | pub fn new(analysis: Analysis, timestamp: SystemTime, path: Option, path_rewrite: Option) -> Crate { 34 | Crate { 35 | id: analysis.prelude.as_ref().unwrap().crate_id.clone(), 36 | analysis, 37 | timestamp, 38 | path, 39 | path_rewrite, 40 | } 41 | } 42 | } 43 | 44 | /// Reads raw analysis data for non-blacklisted crates from files in directories 45 | /// pointed by `loader`. 46 | pub fn read_analysis_from_files( 47 | loader: &L, 48 | crate_timestamps: HashMap, 49 | crate_blacklist: Blacklist, 50 | ) -> Vec { 51 | let mut result = vec![]; 52 | 53 | loader.search_directories() 54 | .iter() 55 | .inspect(|dir| trace!("Considering analysis files at {}", dir.path.display())) 56 | .filter_map(|dir| DirectoryListing::from_path(&dir.path).ok().map(|list| (dir, list))) 57 | .for_each(|(dir, listing)| { 58 | let t = Instant::now(); 59 | 60 | for l in listing.files { 61 | info!("Considering {:?}", l); 62 | if let ListingKind::File(ref time) = l.kind { 63 | if ignore_data(&l.name, crate_blacklist) { 64 | continue; 65 | } 66 | 67 | let path = dir.path.join(&l.name); 68 | let is_fresh = crate_timestamps.get(&path).map_or(true, |t| time > t); 69 | if is_fresh { 70 | read_crate_data(&path).map(|analysis| { 71 | result.push(Crate::new(analysis, *time, Some(path), dir.prefix_rewrite.clone())); 72 | }); 73 | } 74 | } 75 | } 76 | 77 | let d = t.elapsed(); 78 | info!( 79 | "reading {} crates from {} in {}.{:09}s", 80 | result.len(), 81 | dir.path.display(), 82 | d.as_secs(), 83 | d.subsec_nanos() 84 | ); 85 | }); 86 | 87 | result 88 | } 89 | 90 | fn ignore_data(file_name: &str, crate_blacklist: Blacklist) -> bool { 91 | crate_blacklist.iter() 92 | .any(|name| file_name.starts_with(&format!("lib{}-", name))) 93 | } 94 | 95 | fn read_file_contents(path: &Path) -> io::Result { 96 | let mut file = File::open(&path)?; 97 | let mut buf = String::new(); 98 | file.read_to_string(&mut buf)?; 99 | Ok(buf) 100 | } 101 | 102 | /// Attempts to read and deserialize `Analysis` data from a JSON file at `path`, 103 | /// returns `Some(data)` on success. 104 | fn read_crate_data(path: &Path) -> Option { 105 | trace!("read_crate_data {:?}", path); 106 | let t = Instant::now(); 107 | 108 | let buf = read_file_contents(path).or_else(|err| { 109 | warn!("couldn't read file: {}", err); 110 | Err(err) 111 | }).ok()?; 112 | let s = ::rustc_serialize::json::decode(&buf).or_else(|err| { 113 | warn!("deserialisation error: {:?}", err); 114 | json::parse(&buf).map(|parsed| { 115 | if let json::JsonValue::Object(obj) = parsed { 116 | let expected = Some(json::JsonValue::from(Analysis::new(Config::default()).version)); 117 | let actual = obj.get("version").map(|v| v.clone()); 118 | if expected != actual { 119 | warn!("Data file version mismatch; expected {:?} but got {:?}", 120 | expected, actual); 121 | } 122 | } else { 123 | warn!("Data file didn't have a JSON object at the root"); 124 | } 125 | }).map_err(|err| { 126 | warn!("Data file was not valid JSON: {:?}", err); 127 | }).ok(); 128 | 129 | Err(err) 130 | }).ok()?; 131 | 132 | let d = t.elapsed(); 133 | info!( 134 | "reading {:?} {}.{:09}s", 135 | path, 136 | d.as_secs(), 137 | d.subsec_nanos() 138 | ); 139 | 140 | s 141 | } 142 | 143 | pub fn name_space_for_def_kind(dk: DefKind) -> char { 144 | match dk { 145 | DefKind::Enum | 146 | DefKind::Struct | 147 | DefKind::Union | 148 | DefKind::Type | 149 | DefKind::ExternType | 150 | DefKind::Trait => 't', 151 | DefKind::ForeignFunction | 152 | DefKind::ForeignStatic | 153 | DefKind::Function | 154 | DefKind::Method | 155 | DefKind::Mod | 156 | DefKind::Local | 157 | DefKind::Static | 158 | DefKind::Const | 159 | DefKind::Tuple | 160 | DefKind::TupleVariant | 161 | DefKind::StructVariant | 162 | DefKind::Field => 'v', 163 | DefKind::Macro => 'm', 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /test_data/hello/save-analysis/hello.json: -------------------------------------------------------------------------------- 1 | {"config":{"output_file":null,"full_docs":false,"pub_only":false,"distro_crate":false,"signatures":false,"borrow_data":false,"reachable_only":false},"prelude":{"crate_id":{"name":"hello","disambiguator":[4972498070786205651,10752139000545052689]},"crate_root":"src","external_crates":[{"file_name":"/home/xanewok/repos/rls-analysis/test_data/hello/src/main.rs","num":11,"id":{"name":"panic_unwind","disambiguator":[14724309074517047858,14081363051482221763]}},{"file_name":"/home/xanewok/repos/rls-analysis/test_data/hello/src/main.rs","num":8,"id":{"name":"unwind","disambiguator":[16962421678491010609,14144564669002769638]}},{"file_name":"/home/xanewok/repos/rls-analysis/test_data/hello/src/main.rs","num":5,"id":{"name":"std_unicode","disambiguator":[7825379778752978812,3737998437093158016]}},{"file_name":"/home/xanewok/repos/rls-analysis/test_data/hello/src/main.rs","num":2,"id":{"name":"core","disambiguator":[2034893687031163843,15475795989519470532]}},{"file_name":"/home/xanewok/repos/rls-analysis/test_data/hello/src/main.rs","num":10,"id":{"name":"alloc_jemalloc","disambiguator":[16728898169015843293,537719064825112735]}},{"file_name":"/home/xanewok/repos/rls-analysis/test_data/hello/src/main.rs","num":7,"id":{"name":"libc","disambiguator":[10024553366994624393,7659320522938082018]}},{"file_name":"/home/xanewok/repos/rls-analysis/test_data/hello/src/main.rs","num":4,"id":{"name":"alloc","disambiguator":[6987473938317122452,6651568688483122068]}},{"file_name":"/home/xanewok/repos/rls-analysis/test_data/hello/src/main.rs","num":1,"id":{"name":"std","disambiguator":[16894929902530602639,5439452766102853002]}},{"file_name":"/home/xanewok/repos/rls-analysis/test_data/hello/src/main.rs","num":9,"id":{"name":"compiler_builtins","disambiguator":[15243808009585947056,16380432114833907945]}},{"file_name":"/home/xanewok/repos/rls-analysis/test_data/hello/src/main.rs","num":6,"id":{"name":"alloc_system","disambiguator":[9386991845804871092,6259921119180170237]}},{"file_name":"/home/xanewok/repos/rls-analysis/test_data/hello/src/main.rs","num":3,"id":{"name":"rand","disambiguator":[17798033069558174552,12679496062386314490]}}],"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":0,"byte_end":112,"line_start":1,"line_end":8,"column_start":1,"column_end":2}},"imports":[],"defs":[{"kind":"Mod","id":{"krate":0,"index":0},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":0,"byte_end":112,"line_start":1,"line_end":8,"column_start":1,"column_end":2},"name":"","qualname":"::","value":"src/main.rs","parent":null,"children":[{"krate":0,"index":1},{"krate":0,"index":2},{"krate":0,"index":3},{"krate":0,"index":4}],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Function","id":{"krate":0,"index":3},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":3,"byte_end":14,"line_start":1,"line_end":1,"column_start":4,"column_end":15},"name":"print_hello","qualname":"::print_hello","value":"fn () -> ()","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Local","id":{"krate":0,"index":4294967287},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":27,"byte_end":31,"line_start":2,"line_end":2,"column_start":9,"column_end":13},"name":"name","qualname":"name$8","value":"&str","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Function","id":{"krate":0,"index":4},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":83,"byte_end":87,"line_start":6,"line_end":6,"column_start":4,"column_end":8},"name":"main","qualname":"::main","value":"fn () -> ()","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]}],"impls":[],"refs":[{"kind":"Mod","span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":0,"byte_end":0,"line_start":1,"line_end":1,"column_start":1,"column_end":1},"ref_id":{"krate":4294967295,"index":4294967295}},{"kind":"Mod","span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":0,"byte_end":0,"line_start":1,"line_end":1,"column_start":1,"column_end":1},"ref_id":{"krate":4294967295,"index":4294967295}},{"kind":"Mod","span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":0,"byte_end":0,"line_start":1,"line_end":1,"column_start":1,"column_end":1},"ref_id":{"krate":4294967295,"index":4294967295}},{"kind":"Variable","span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":70,"byte_end":74,"line_start":3,"line_end":3,"column_start":28,"column_end":32},"ref_id":{"krate":0,"index":4294967287}},{"kind":"Variable","span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":70,"byte_end":74,"line_start":3,"line_end":3,"column_start":28,"column_end":32},"ref_id":{"krate":0,"index":4294967269}},{"kind":"Function","span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":70,"byte_end":74,"line_start":3,"line_end":3,"column_start":28,"column_end":32},"ref_id":{"krate":2,"index":3443}},{"kind":"Type","span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":70,"byte_end":74,"line_start":3,"line_end":3,"column_start":28,"column_end":32},"ref_id":{"krate":4294967295,"index":4294967295}},{"kind":"Mod","span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":70,"byte_end":74,"line_start":3,"line_end":3,"column_start":28,"column_end":32},"ref_id":{"krate":4294967295,"index":4294967295}},{"kind":"Mod","span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":70,"byte_end":74,"line_start":3,"line_end":3,"column_start":28,"column_end":32},"ref_id":{"krate":4294967295,"index":4294967295}},{"kind":"Function","span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":96,"byte_end":107,"line_start":7,"line_end":7,"column_start":5,"column_end":16},"ref_id":{"krate":0,"index":3}}],"macro_refs":[{"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":47,"byte_end":76,"line_start":3,"line_end":3,"column_start":5,"column_end":34},"qualname":"println","callee_span":{"file_name":[47,104,111,109,101,47,120,97,110,101,119,111,107,47,114,101,112,111,115,47,114,117,115,116,47,115,114,99,47,108,105,98,115,116,100,47,109,97,99,114,111,115,46,114,115],"byte_start":25155,"byte_end":25328,"line_start":150,"line_end":154,"column_start":1,"column_end":2}}],"relations":[]} -------------------------------------------------------------------------------- /test_data/rename/save-analysis/rename.json: -------------------------------------------------------------------------------- 1 | {"config":{"output_file":null,"full_docs":false,"pub_only":false,"reachable_only":false,"distro_crate":false,"signatures":false,"borrow_data":false},"prelude":{"crate_id":{"name":"rename","disambiguator":[15344473257692267285,11526290613969210121]},"crate_root":"src","external_crates":[{"file_name":"/Users/nick/version-controlled/rls-analysis/test_data/rename/src/main.rs","num":1,"id":{"name":"std","disambiguator":[14432511533341295636,4311052241033655891]}},{"file_name":"/Users/nick/version-controlled/rls-analysis/test_data/rename/src/main.rs","num":2,"id":{"name":"core","disambiguator":[17072911384636793184,16051064601402656485]}},{"file_name":"/Users/nick/version-controlled/rls-analysis/test_data/rename/src/main.rs","num":3,"id":{"name":"compiler_builtins","disambiguator":[13525339190555708102,1830656834648964929]}},{"file_name":"/Users/nick/version-controlled/rls-analysis/test_data/rename/src/main.rs","num":4,"id":{"name":"alloc","disambiguator":[17198736606968675642,14275352771659048254]}},{"file_name":"/Users/nick/version-controlled/rls-analysis/test_data/rename/src/main.rs","num":5,"id":{"name":"alloc_system","disambiguator":[2091716200026081704,15823106656297828688]}},{"file_name":"/Users/nick/version-controlled/rls-analysis/test_data/rename/src/main.rs","num":6,"id":{"name":"libc","disambiguator":[13088542877910744519,14493954966318922730]}},{"file_name":"/Users/nick/version-controlled/rls-analysis/test_data/rename/src/main.rs","num":7,"id":{"name":"unwind","disambiguator":[15985174238589507576,3749380134813561016]}},{"file_name":"/Users/nick/version-controlled/rls-analysis/test_data/rename/src/main.rs","num":8,"id":{"name":"alloc_jemalloc","disambiguator":[3024287792016865132,17683646904702389714]}},{"file_name":"/Users/nick/version-controlled/rls-analysis/test_data/rename/src/main.rs","num":9,"id":{"name":"panic_unwind","disambiguator":[17521573399390905579,17496626875244828075]}}],"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":0,"byte_end":169,"line_start":1,"line_end":16,"column_start":1,"column_end":13}},"imports":[{"kind":"Use","ref_id":{"krate":0,"index":10},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":70,"byte_end":73,"line_start":7,"line_end":7,"column_start":12,"column_end":15},"alias_span":null,"name":"qux","value":"","parent":{"krate":0,"index":12}},{"kind":"Use","ref_id":{"krate":0,"index":8},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":86,"byte_end":89,"line_start":8,"line_end":8,"column_start":12,"column_end":15},"alias_span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":93,"byte_end":96,"line_start":8,"line_end":8,"column_start":19,"column_end":22},"name":"baz","value":"","parent":{"krate":0,"index":12}}],"defs":[{"kind":"Mod","id":{"krate":0,"index":0},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":0,"byte_end":169,"line_start":1,"line_end":16,"column_start":1,"column_end":13},"name":"","qualname":"::","value":"src/main.rs","parent":null,"children":[{"krate":0,"index":2},{"krate":0,"index":4},{"krate":0,"index":6},{"krate":0,"index":12},{"krate":0,"index":20}],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Mod","id":{"krate":0,"index":6},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":4,"byte_end":5,"line_start":1,"line_end":1,"column_start":5,"column_end":6},"name":"a","qualname":"::a","value":"src/main.rs","parent":null,"children":[{"krate":0,"index":8},{"krate":0,"index":10}],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Function","id":{"krate":0,"index":8},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":19,"byte_end":22,"line_start":2,"line_end":2,"column_start":12,"column_end":15},"name":"bar","qualname":"::a::bar","value":"fn () -> ()","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Function","id":{"krate":0,"index":10},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":39,"byte_end":42,"line_start":3,"line_end":3,"column_start":12,"column_end":15},"name":"qux","qualname":"::a::qux","value":"fn () -> ()","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Mod","id":{"krate":0,"index":12},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":55,"byte_end":56,"line_start":6,"line_end":6,"column_start":5,"column_end":6},"name":"b","qualname":"::b","value":"src/main.rs","parent":null,"children":[{"krate":0,"index":14},{"krate":0,"index":16},{"krate":0,"index":18}],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Function","id":{"krate":0,"index":18},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":110,"byte_end":113,"line_start":10,"line_end":10,"column_start":12,"column_end":15},"name":"foo","qualname":"::b::foo","value":"fn () -> ()","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Function","id":{"krate":0,"index":20},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":160,"byte_end":164,"line_start":16,"line_end":16,"column_start":4,"column_end":8},"name":"main","qualname":"::main","value":"fn () -> ()","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]}],"impls":[],"refs":[{"kind":"Mod","span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":0,"byte_end":0,"line_start":1,"line_end":1,"column_start":1,"column_end":1},"ref_id":{"krate":4294967295,"index":4294967295}},{"kind":"Mod","span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":0,"byte_end":0,"line_start":1,"line_end":1,"column_start":1,"column_end":1},"ref_id":{"krate":4294967295,"index":4294967295}},{"kind":"Mod","span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":0,"byte_end":0,"line_start":1,"line_end":1,"column_start":1,"column_end":1},"ref_id":{"krate":4294967295,"index":4294967295}},{"kind":"Mod","span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":67,"byte_end":68,"line_start":7,"line_end":7,"column_start":9,"column_end":10},"ref_id":{"krate":4294967295,"index":4294967295}},{"kind":"Mod","span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":83,"byte_end":84,"line_start":8,"line_end":8,"column_start":9,"column_end":10},"ref_id":{"krate":4294967295,"index":4294967295}},{"kind":"Function","span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":126,"byte_end":129,"line_start":11,"line_end":11,"column_start":9,"column_end":12},"ref_id":{"krate":0,"index":10}},{"kind":"Function","span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":141,"byte_end":144,"line_start":12,"line_end":12,"column_start":9,"column_end":12},"ref_id":{"krate":0,"index":8}}],"macro_refs":[],"relations":[]} -------------------------------------------------------------------------------- /test_data/rust-analysis/libpanic_abort-627bb601930ec2f6.json: -------------------------------------------------------------------------------- 1 | {"config":{"output_file":null,"full_docs":false,"pub_only":true,"reachable_only":false,"distro_crate":true,"signatures":false,"borrow_data":false},"prelude":{"crate_id":{"name":"panic_abort","disambiguator":[15223374454472530332,2683361841453404253]},"crate_root":"libpanic_abort","external_crates":[{"file_name":"/Users/travis/build/rust-lang/rust/src/libpanic_abort/lib.rs","num":1,"id":{"name":"compiler_builtins","disambiguator":[12047234932576597458,5077187143126647032]}},{"file_name":"/Users/travis/build/rust-lang/rust/src/libpanic_abort/lib.rs","num":2,"id":{"name":"core","disambiguator":[12641647969103297473,10130382509811922120]}},{"file_name":"/Users/travis/build/rust-lang/rust/src/libpanic_abort/lib.rs","num":3,"id":{"name":"libc","disambiguator":[10677312091366318875,12914270607935649197]}}],"span":{"file_name":[108,105,98,112,97,110,105,99,95,97,98,111,114,116,47,108,105,98,46,114,115],"byte_start":467,"byte_end":5820,"line_start":11,"line_end":135,"column_start":1,"column_end":2}},"imports":[],"defs":[{"kind":"Mod","id":{"krate":0,"index":0},"span":{"file_name":[108,105,98,112,97,110,105,99,95,97,98,111,114,116,47,108,105,98,46,114,115],"byte_start":467,"byte_end":5820,"line_start":11,"line_end":135,"column_start":1,"column_end":2},"name":"","qualname":"::","value":"libpanic_abort/lib.rs","parent":null,"children":[{"krate":0,"index":2},{"krate":0,"index":4},{"krate":0,"index":6},{"krate":0,"index":8},{"krate":0,"index":10},{"krate":0,"index":16}],"decl_id":null,"docs":" Implementation of Rust panics via process aborts","sig":null,"attributes":[{"value":"no_std","span":{"file_name":[108,105,98,112,97,110,105,99,95,97,98,111,114,116,47,108,105,98,46,114,115],"byte_start":675,"byte_end":685,"line_start":16,"line_end":16,"column_start":1,"column_end":11}},{"value":"unstable(feature = \"panic_abort\", issue = \"32837\")","span":{"file_name":[108,105,98,112,97,110,105,99,95,97,98,111,114,116,47,108,105,98,46,114,115],"byte_start":686,"byte_end":740,"line_start":17,"line_end":17,"column_start":1,"column_end":55}},{"value":"panic_runtime","span":{"file_name":[108,105,98,112,97,110,105,99,95,97,98,111,114,116,47,108,105,98,46,114,115],"byte_start":1034,"byte_end":1051,"line_start":22,"line_end":22,"column_start":1,"column_end":18}},{"value":"allow(unused_features)","span":{"file_name":[108,105,98,112,97,110,105,99,95,97,98,111,114,116,47,108,105,98,46,114,115],"byte_start":1052,"byte_end":1078,"line_start":23,"line_end":23,"column_start":1,"column_end":27}},{"value":"feature(core_intrinsics)","span":{"file_name":[108,105,98,112,97,110,105,99,95,97,98,111,114,116,47,108,105,98,46,114,115],"byte_start":1080,"byte_end":1108,"line_start":25,"line_end":25,"column_start":1,"column_end":29}},{"value":"feature(libc)","span":{"file_name":[108,105,98,112,97,110,105,99,95,97,98,111,114,116,47,108,105,98,46,114,115],"byte_start":1109,"byte_end":1126,"line_start":26,"line_end":26,"column_start":1,"column_end":18}},{"value":"feature(panic_runtime)","span":{"file_name":[108,105,98,112,97,110,105,99,95,97,98,111,114,116,47,108,105,98,46,114,115],"byte_start":1127,"byte_end":1153,"line_start":27,"line_end":27,"column_start":1,"column_end":27}},{"value":"feature(staged_api)","span":{"file_name":[108,105,98,112,97,110,105,99,95,97,98,111,114,116,47,108,105,98,46,114,115],"byte_start":1154,"byte_end":1177,"line_start":28,"line_end":28,"column_start":1,"column_end":24}},{"value":"feature(rustc_attrs)","span":{"file_name":[108,105,98,112,97,110,105,99,95,97,98,111,114,116,47,108,105,98,46,114,115],"byte_start":1178,"byte_end":1202,"line_start":29,"line_end":29,"column_start":1,"column_end":25}}]},{"kind":"Function","id":{"krate":0,"index":8},"span":{"file_name":[108,105,98,112,97,110,105,99,95,97,98,111,114,116,47,108,105,98,46,114,115],"byte_start":1398,"byte_end":1422,"line_start":35,"line_end":35,"column_start":22,"column_end":46},"name":"__rust_maybe_catch_panic","qualname":"::__rust_maybe_catch_panic","value":"fn (f: fn(*mut u8), data: *mut u8, _data_ptr: *mut usize, _vtable_ptr: *mut usize) -> u32","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[{"value":"no_mangle","span":{"file_name":[108,105,98,112,97,110,105,99,95,97,98,111,114,116,47,108,105,98,46,114,115],"byte_start":1335,"byte_end":1347,"line_start":33,"line_end":33,"column_start":1,"column_end":13}},{"value":"rustc_std_internal_symbol","span":{"file_name":[108,105,98,112,97,110,105,99,95,97,98,111,114,116,47,108,105,98,46,114,115],"byte_start":1348,"byte_end":1376,"line_start":34,"line_end":34,"column_start":1,"column_end":29}}]},{"kind":"Function","id":{"krate":0,"index":10},"span":{"file_name":[108,105,98,112,97,110,105,99,95,97,98,111,114,116,47,108,105,98,46,114,115],"byte_start":2315,"byte_end":2333,"line_start":55,"line_end":55,"column_start":22,"column_end":40},"name":"__rust_start_panic","qualname":"::__rust_start_panic","value":"fn (_data: usize, _vtable: usize) -> u32","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[{"value":"no_mangle","span":{"file_name":[108,105,98,112,97,110,105,99,95,97,98,111,114,116,47,108,105,98,46,114,115],"byte_start":2252,"byte_end":2264,"line_start":53,"line_end":53,"column_start":1,"column_end":13}},{"value":"rustc_std_internal_symbol","span":{"file_name":[108,105,98,112,97,110,105,99,95,97,98,111,114,116,47,108,105,98,46,114,115],"byte_start":2265,"byte_end":2293,"line_start":54,"line_end":54,"column_start":1,"column_end":29}}]},{"kind":"Mod","id":{"krate":0,"index":16},"span":{"file_name":[108,105,98,112,97,110,105,99,95,97,98,111,114,116,47,108,105,98,46,114,115],"byte_start":4270,"byte_end":4283,"line_start":98,"line_end":98,"column_start":9,"column_end":22},"name":"personalities","qualname":"::personalities","value":"libpanic_abort/lib.rs","parent":null,"children":[{"krate":0,"index":18}],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Function","id":{"krate":0,"index":18},"span":{"file_name":[108,105,98,112,97,110,105,99,95,97,98,111,114,116,47,108,105,98,46,114,115],"byte_start":4445,"byte_end":4464,"line_start":103,"line_end":103,"column_start":19,"column_end":38},"name":"rust_eh_personality","qualname":"::personalities::rust_eh_personality","value":"fn () -> ()","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[{"value":"no_mangle","span":{"file_name":[108,105,98,112,97,110,105,99,95,97,98,111,114,116,47,108,105,98,46,114,115],"byte_start":4290,"byte_end":4302,"line_start":99,"line_end":99,"column_start":5,"column_end":17}},{"value":"cfg(not(all(target_os = \"windows\",\n target_env = \"gnu\",\n target_arch = \"x86_64\")))","span":{"file_name":[108,105,98,112,97,110,105,99,95,97,98,111,114,116,47,108,105,98,46,114,115],"byte_start":4307,"byte_end":4426,"line_start":100,"line_end":102,"column_start":5,"column_end":45}}]}],"impls":[],"refs":[],"macro_refs":[],"relations":[]} -------------------------------------------------------------------------------- /test_data/rust-analysis/liballoc_system-efb53e76be37f014.json: -------------------------------------------------------------------------------- 1 | {"config":{"output_file":null,"full_docs":false,"pub_only":true,"reachable_only":false,"distro_crate":true,"signatures":false,"borrow_data":false},"prelude":{"crate_id":{"name":"alloc_system","disambiguator":[12248884017658358091,17580744942517357114]},"crate_root":"liballoc_system","external_crates":[{"file_name":"/Users/travis/build/rust-lang/rust/src/liballoc_system/lib.rs","num":1,"id":{"name":"compiler_builtins","disambiguator":[12047234932576597458,5077187143126647032]}},{"file_name":"/Users/travis/build/rust-lang/rust/src/liballoc_system/lib.rs","num":2,"id":{"name":"core","disambiguator":[12641647969103297473,10130382509811922120]}},{"file_name":"/Users/travis/build/rust-lang/rust/src/liballoc_system/lib.rs","num":3,"id":{"name":"libc","disambiguator":[10677312091366318875,12914270607935649197]}}],"span":{"file_name":[108,105,98,97,108,108,111,99,95,115,121,115,116,101,109,47,108,105,98,46,114,115],"byte_start":467,"byte_end":15125,"line_start":11,"line_end":428,"column_start":1,"column_end":31}},"imports":[],"defs":[{"kind":"Mod","id":{"krate":0,"index":0},"span":{"file_name":[108,105,98,97,108,108,111,99,95,115,121,115,116,101,109,47,108,105,98,46,114,115],"byte_start":467,"byte_end":15125,"line_start":11,"line_end":428,"column_start":1,"column_end":31},"name":"","qualname":"::","value":"liballoc_system/lib.rs","parent":null,"children":[{"krate":0,"index":2},{"krate":0,"index":4},{"krate":0,"index":6},{"krate":0,"index":8},{"krate":0,"index":10},{"krate":0,"index":22},{"krate":0,"index":24},{"krate":0,"index":26},{"krate":0,"index":38},{"krate":0,"index":56},{"krate":0,"index":86},{"krate":0,"index":88}],"decl_id":null,"docs":"","sig":null,"attributes":[{"value":"no_std","span":{"file_name":[108,105,98,97,108,108,111,99,95,115,121,115,116,101,109,47,108,105,98,46,114,115],"byte_start":467,"byte_end":477,"line_start":11,"line_end":11,"column_start":1,"column_end":11}},{"value":"allow(unused_attributes)","span":{"file_name":[108,105,98,97,108,108,111,99,95,115,121,115,116,101,109,47,108,105,98,46,114,115],"byte_start":478,"byte_end":506,"line_start":12,"line_end":12,"column_start":1,"column_end":29}},{"value":"unstable(feature = \"alloc_system\",\n reason =\n \"this library is unlikely to be stabilized in its current form or name\",\n issue = \"32838\")","span":{"file_name":[108,105,98,97,108,108,111,99,95,115,121,115,116,101,109,47,108,105,98,46,114,115],"byte_start":507,"byte_end":692,"line_start":13,"line_end":16,"column_start":1,"column_end":30}},{"value":"feature(global_allocator)","span":{"file_name":[108,105,98,97,108,108,111,99,95,115,121,115,116,101,109,47,108,105,98,46,114,115],"byte_start":693,"byte_end":722,"line_start":17,"line_end":17,"column_start":1,"column_end":30}},{"value":"feature(allocator_api)","span":{"file_name":[108,105,98,97,108,108,111,99,95,115,121,115,116,101,109,47,108,105,98,46,114,115],"byte_start":723,"byte_end":749,"line_start":18,"line_end":18,"column_start":1,"column_end":27}},{"value":"feature(core_intrinsics)","span":{"file_name":[108,105,98,97,108,108,111,99,95,115,121,115,116,101,109,47,108,105,98,46,114,115],"byte_start":750,"byte_end":778,"line_start":19,"line_end":19,"column_start":1,"column_end":29}},{"value":"feature(staged_api)","span":{"file_name":[108,105,98,97,108,108,111,99,95,115,121,115,116,101,109,47,108,105,98,46,114,115],"byte_start":779,"byte_end":802,"line_start":20,"line_end":20,"column_start":1,"column_end":24}},{"value":"feature(rustc_attrs)","span":{"file_name":[108,105,98,97,108,108,111,99,95,115,121,115,116,101,109,47,108,105,98,46,114,115],"byte_start":803,"byte_end":827,"line_start":21,"line_end":21,"column_start":1,"column_end":25}},{"value":"feature(libc)","span":{"file_name":[108,105,98,97,108,108,111,99,95,115,121,115,116,101,109,47,108,105,98,46,114,115],"byte_start":896,"byte_end":910,"line_start":22,"line_end":22,"column_start":69,"column_end":83}},{"value":"rustc_alloc_kind = \"lib\"","span":{"file_name":[108,105,98,97,108,108,111,99,95,115,121,115,116,101,109,47,108,105,98,46,114,115],"byte_start":912,"byte_end":940,"line_start":23,"line_end":23,"column_start":1,"column_end":29}}]},{"kind":"Struct","id":{"krate":0,"index":24},"span":{"file_name":[108,105,98,97,108,108,111,99,95,115,121,115,116,101,109,47,108,105,98,46,114,115],"byte_start":1778,"byte_end":1784,"line_start":48,"line_end":48,"column_start":12,"column_end":18},"name":"System","qualname":"::System","value":"","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[{"value":"unstable(feature = \"allocator_api\", issue = \"32838\")","span":{"file_name":[108,105,98,97,108,108,111,99,95,115,121,115,116,101,109,47,108,105,98,46,114,115],"byte_start":1711,"byte_end":1766,"line_start":47,"line_end":47,"column_start":1,"column_end":56}}]}],"impls":[{"id":0,"kind":"Direct","span":{"file_name":[108,105,98,97,108,108,111,99,95,115,121,115,116,101,109,47,108,105,98,46,114,115],"byte_start":1865,"byte_end":1871,"line_start":51,"line_end":51,"column_start":23,"column_end":29},"value":"","parent":null,"children":[{"krate":0,"index":28},{"krate":0,"index":30},{"krate":0,"index":32},{"krate":0,"index":34},{"krate":0,"index":36}],"docs":"","sig":null,"attributes":[]},{"id":1,"kind":"Inherent","span":{"file_name":[108,105,98,97,108,108,111,99,95,115,121,115,116,101,109,47,108,105,98,46,114,115],"byte_start":3990,"byte_end":3996,"line_start":119,"line_end":119,"column_start":17,"column_end":23},"value":"","parent":null,"children":[{"krate":0,"index":54}],"docs":"","sig":null,"attributes":[]},{"id":2,"kind":"Direct","span":{"file_name":[108,105,98,97,108,108,111,99,95,115,121,115,116,101,109,47,108,105,98,46,114,115],"byte_start":5002,"byte_end":5008,"line_start":147,"line_end":147,"column_start":33,"column_end":39},"value":"","parent":null,"children":[{"krate":0,"index":76},{"krate":0,"index":78},{"krate":0,"index":80},{"krate":0,"index":82}],"docs":"","sig":null,"attributes":[]}],"refs":[],"macro_refs":[],"relations":[{"span":{"file_name":[108,105,98,97,108,108,111,99,95,115,121,115,116,101,109,47,108,105,98,46,114,115],"byte_start":1865,"byte_end":1871,"line_start":51,"line_end":51,"column_start":23,"column_end":29},"kind":{"variant":"Impl","fields":[0]},"from":{"krate":0,"index":24},"to":{"krate":2,"index":8386}},{"span":{"file_name":[108,105,98,97,108,108,111,99,95,115,121,115,116,101,109,47,108,105,98,46,114,115],"byte_start":3990,"byte_end":3996,"line_start":119,"line_end":119,"column_start":17,"column_end":23},"kind":{"variant":"Impl","fields":[1]},"from":{"krate":0,"index":24},"to":{"krate":4294967295,"index":4294967295}},{"span":{"file_name":[108,105,98,97,108,108,111,99,95,115,121,115,116,101,109,47,108,105,98,46,114,115],"byte_start":5002,"byte_end":5008,"line_start":147,"line_end":147,"column_start":33,"column_end":39},"kind":{"variant":"Impl","fields":[2]},"from":{"krate":0,"index":24},"to":{"krate":2,"index":8374}}]} -------------------------------------------------------------------------------- /src/loader.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The RLS Project Developers. 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | //! Defines an `AnalysisLoader` trait, which allows to specify directories 10 | //! from which save-analysis JSON files can be read. Also supplies a 11 | //! default implementation `CargoAnalysisLoader` for Cargo-emitted save-analysis 12 | //! files. 13 | 14 | use std::env; 15 | use std::ffi::OsStr; 16 | use std::fmt; 17 | use std::path::{Path, PathBuf}; 18 | use std::process::Command; 19 | 20 | use AnalysisHost; 21 | 22 | #[derive(Debug)] 23 | pub struct CargoAnalysisLoader { 24 | pub path_prefix: Option, 25 | pub target: Target, 26 | } 27 | 28 | #[derive(Debug, new)] 29 | pub struct SearchDirectory { 30 | pub path: PathBuf, 31 | // The directory searched must have spans re-written to be based on a new 32 | // path prefix. This happens for example when the std lib crates are compiled 33 | // on the Rust CI, but live in the user's sysroot directory, this adjustment 34 | // (which happens in `lower_span`) means we have the new source location. 35 | pub prefix_rewrite: Option, 36 | } 37 | 38 | impl CargoAnalysisLoader { 39 | pub fn new(target: Target) -> CargoAnalysisLoader { 40 | CargoAnalysisLoader { 41 | path_prefix: None, 42 | target, 43 | } 44 | } 45 | } 46 | 47 | /// Allows to specify from where and which analysis files will be considered 48 | /// when reloading data to lower. 49 | pub trait AnalysisLoader: Sized { 50 | fn needs_hard_reload(&self, path_prefix: &Path) -> bool; 51 | fn fresh_host(&self) -> AnalysisHost; 52 | fn set_path_prefix(&mut self, path_prefix: &Path); 53 | fn abs_path_prefix(&self) -> Option; 54 | /// Returns every directory in which analysis files are to be considered. 55 | fn search_directories(&self) -> Vec; 56 | } 57 | 58 | impl AnalysisLoader for CargoAnalysisLoader { 59 | fn needs_hard_reload(&self, path_prefix: &Path) -> bool { 60 | self.path_prefix.as_ref().map_or(true, |p| p != path_prefix) 61 | } 62 | 63 | fn fresh_host(&self) -> AnalysisHost { 64 | AnalysisHost::new_with_loader(CargoAnalysisLoader { 65 | path_prefix: self.path_prefix.clone(), 66 | .. CargoAnalysisLoader::new(self.target) 67 | }) 68 | } 69 | 70 | fn set_path_prefix(&mut self, path_prefix: &Path) { 71 | self.path_prefix = Some(path_prefix.to_owned()); 72 | } 73 | 74 | fn abs_path_prefix(&self) -> Option { 75 | self.path_prefix.as_ref() 76 | .map(|s| Path::new(s).canonicalize().unwrap().to_owned()) 77 | } 78 | 79 | fn search_directories(&self) -> Vec { 80 | let path_prefix = self.path_prefix.as_ref().unwrap(); 81 | let target = self.target.to_string(); 82 | 83 | let deps_path = path_prefix 84 | .join("target") 85 | .join("rls") 86 | .join(&target) 87 | .join("deps") 88 | .join("save-analysis"); 89 | // FIXME sys_root_path allows to break out of 'sandbox' - is that Ok? 90 | // FIXME libs_path and src_path both assume the default `libdir = "lib"`. 91 | let sys_root_path = sys_root_path(); 92 | let target_triple = extract_target_triple(sys_root_path.as_path()); 93 | let libs_path = sys_root_path 94 | .join("lib") 95 | .join("rustlib") 96 | .join(&target_triple) 97 | .join("analysis"); 98 | 99 | let src_path = sys_root_path 100 | .join("lib") 101 | .join("rustlib") 102 | .join("src") 103 | .join("rust"); 104 | 105 | vec![ 106 | SearchDirectory::new(libs_path, Some(src_path)), 107 | SearchDirectory::new(deps_path, None), 108 | ] 109 | } 110 | } 111 | 112 | fn extract_target_triple(sys_root_path: &Path) -> String { 113 | // First try to get the triple from the rustc version output, 114 | // otherwise fall back on the rustup-style toolchain path. 115 | // FIXME: Both methods assume that the target is the host triple, 116 | // which isn't the case for cross-compilation (rust-lang/rls#309). 117 | extract_rustc_host_triple() 118 | .unwrap_or_else(|| extract_rustup_target_triple(sys_root_path)) 119 | } 120 | 121 | fn extract_rustc_host_triple() -> Option { 122 | let rustc = env::var("RUSTC").unwrap_or(String::from("rustc")); 123 | let verbose_version = Command::new(rustc) 124 | .arg("--verbose") 125 | .arg("--version") 126 | .output() 127 | .ok() 128 | .and_then(|out| String::from_utf8(out.stdout).ok())?; 129 | 130 | // Extracts the triple from a line like `host: x86_64-unknown-linux-gnu` 131 | verbose_version 132 | .lines() 133 | .find(|line| line.starts_with("host: ")) 134 | .and_then(|host| host.split_whitespace().nth(1)) 135 | .map(String::from) 136 | } 137 | 138 | // FIXME: This can fail when using a custom toolchain in rustup (often linked to 139 | // `/$rust_repo/build/$target/stage2`) 140 | fn extract_rustup_target_triple(sys_root_path: &Path) -> String { 141 | // Extracts nightly-x86_64-pc-windows-msvc from 142 | // $HOME/.rustup/toolchains/nightly-x86_64-pc-windows-msvc 143 | let toolchain = sys_root_path 144 | .iter() 145 | .last() 146 | .and_then(OsStr::to_str) 147 | .expect("extracting toolchain failed"); 148 | // Extracts x86_64-pc-windows-msvc from nightly-x86_64-pc-windows-pc 149 | let triple = toolchain 150 | .splitn(2, '-') 151 | .last() 152 | .map(String::from) 153 | .expect("extracting triple failed"); 154 | triple 155 | } 156 | 157 | fn sys_root_path() -> PathBuf { 158 | env::var("SYSROOT") 159 | .ok() 160 | .map(PathBuf::from) 161 | .or_else(|| { 162 | Command::new(env::var("RUSTC").unwrap_or(String::from("rustc"))) 163 | .arg("--print") 164 | .arg("sysroot") 165 | .output() 166 | .ok() 167 | .and_then(|out| String::from_utf8(out.stdout).ok()) 168 | .map(|s| PathBuf::from(s.trim())) 169 | }) 170 | .expect("need to specify SYSROOT or RUSTC env vars, or rustc must be in PATH") 171 | } 172 | 173 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] 174 | pub enum Target { 175 | Release, 176 | Debug, 177 | } 178 | 179 | impl fmt::Display for Target { 180 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 181 | match *self { 182 | Target::Release => write!(f, "release"), 183 | Target::Debug => write!(f, "debug"), 184 | } 185 | } 186 | } 187 | 188 | #[cfg(test)] 189 | mod tests { 190 | use std::path::Path; 191 | use super::*; 192 | 193 | #[test] 194 | fn windows_path() { 195 | let path = Path::new( 196 | r#"C:\Users\user\.rustup\toolchains\nightly-x86_64-pc-windows-msvc"#, 197 | ); 198 | assert_eq!( 199 | extract_rustup_target_triple(path), 200 | String::from("x86_64-pc-windows-msvc") 201 | ); 202 | } 203 | 204 | #[test] 205 | fn unix_path() { 206 | let path = Path::new( 207 | "/home/user/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu", 208 | ); 209 | assert_eq!( 210 | extract_rustup_target_triple(path), 211 | String::from("x86_64-unknown-linux-gnu") 212 | ); 213 | } 214 | 215 | #[test] 216 | fn target_triple() { 217 | let sys_root_path = sys_root_path(); 218 | let target_triple = extract_target_triple(&sys_root_path); 219 | let target_path = sys_root_path 220 | .join("lib") 221 | .join("rustlib") 222 | .join(&target_triple); 223 | assert!(target_path.is_dir(), "{:?} is not a directory!", target_path); 224 | } 225 | } 226 | -------------------------------------------------------------------------------- /test_data/rust-analysis/liballoc_jemalloc-67da9297e5607113.json: -------------------------------------------------------------------------------- 1 | {"config":{"output_file":null,"full_docs":false,"pub_only":true,"reachable_only":false,"distro_crate":true,"signatures":false,"borrow_data":false},"prelude":{"crate_id":{"name":"alloc_jemalloc","disambiguator":[17994208587689535795,10583317287541686664]},"crate_root":"liballoc_jemalloc","external_crates":[{"file_name":"/Users/travis/build/rust-lang/rust/src/liballoc_jemalloc/lib.rs","num":1,"id":{"name":"compiler_builtins","disambiguator":[12047234932576597458,5077187143126647032]}},{"file_name":"/Users/travis/build/rust-lang/rust/src/liballoc_jemalloc/lib.rs","num":2,"id":{"name":"core","disambiguator":[12641647969103297473,10130382509811922120]}},{"file_name":"/Users/travis/build/rust-lang/rust/src/liballoc_jemalloc/lib.rs","num":3,"id":{"name":"alloc_system","disambiguator":[12248884017658358091,17580744942517357114]}},{"file_name":"/Users/travis/build/rust-lang/rust/src/liballoc_jemalloc/lib.rs","num":4,"id":{"name":"libc","disambiguator":[10677312091366318875,12914270607935649197]}}],"span":{"file_name":[108,105,98,97,108,108,111,99,95,106,101,109,97,108,108,111,99,47,108,105,98,46,114,115],"byte_start":467,"byte_end":5348,"line_start":11,"line_end":140,"column_start":1,"column_end":2}},"imports":[{"kind":"GlobUse","ref_id":null,"span":{"file_name":[108,105,98,97,108,108,111,99,95,106,101,109,97,108,108,111,99,47,108,105,98,46,114,115],"byte_start":1059,"byte_end":1060,"line_start":30,"line_end":30,"column_start":19,"column_end":20},"name":"*","value":"","parent":{"krate":0,"index":0}}],"defs":[{"kind":"Mod","id":{"krate":0,"index":0},"span":{"file_name":[108,105,98,97,108,108,111,99,95,106,101,109,97,108,108,111,99,47,108,105,98,46,114,115],"byte_start":467,"byte_end":5348,"line_start":11,"line_end":140,"column_start":1,"column_end":2},"name":"","qualname":"::","value":"liballoc_jemalloc/lib.rs","parent":null,"children":[{"krate":0,"index":2},{"krate":0,"index":4},{"krate":0,"index":6},{"krate":0,"index":8},{"krate":0,"index":10},{"krate":0,"index":12},{"krate":0,"index":14}],"decl_id":null,"docs":"","sig":null,"attributes":[{"value":"no_std","span":{"file_name":[108,105,98,97,108,108,111,99,95,106,101,109,97,108,108,111,99,47,108,105,98,46,114,115],"byte_start":467,"byte_end":477,"line_start":11,"line_end":11,"column_start":1,"column_end":11}},{"value":"allow(unused_attributes)","span":{"file_name":[108,105,98,97,108,108,111,99,95,106,101,109,97,108,108,111,99,47,108,105,98,46,114,115],"byte_start":478,"byte_end":506,"line_start":12,"line_end":12,"column_start":1,"column_end":29}},{"value":"unstable(feature = \"alloc_jemalloc\",\n reason =\n \"this library is unlikely to be stabilized in its current form or name\",\n issue = \"27783\")","span":{"file_name":[108,105,98,97,108,108,111,99,95,106,101,109,97,108,108,111,99,47,108,105,98,46,114,115],"byte_start":507,"byte_end":694,"line_start":13,"line_end":16,"column_start":1,"column_end":30}},{"value":"feature(alloc_system)","span":{"file_name":[108,105,98,97,108,108,111,99,95,106,101,109,97,108,108,111,99,47,108,105,98,46,114,115],"byte_start":695,"byte_end":720,"line_start":17,"line_end":17,"column_start":1,"column_end":26}},{"value":"feature(libc)","span":{"file_name":[108,105,98,97,108,108,111,99,95,106,101,109,97,108,108,111,99,47,108,105,98,46,114,115],"byte_start":721,"byte_end":738,"line_start":18,"line_end":18,"column_start":1,"column_end":18}},{"value":"feature(linkage)","span":{"file_name":[108,105,98,97,108,108,111,99,95,106,101,109,97,108,108,111,99,47,108,105,98,46,114,115],"byte_start":739,"byte_end":759,"line_start":19,"line_end":19,"column_start":1,"column_end":21}},{"value":"feature(staged_api)","span":{"file_name":[108,105,98,97,108,108,111,99,95,106,101,109,97,108,108,111,99,47,108,105,98,46,114,115],"byte_start":760,"byte_end":783,"line_start":20,"line_end":20,"column_start":1,"column_end":24}},{"value":"feature(rustc_attrs)","span":{"file_name":[108,105,98,97,108,108,111,99,95,106,101,109,97,108,108,111,99,47,108,105,98,46,114,115],"byte_start":784,"byte_end":808,"line_start":21,"line_end":21,"column_start":1,"column_end":25}},{"value":"feature(allocator_api)","span":{"file_name":[108,105,98,97,108,108,111,99,95,106,101,109,97,108,108,111,99,47,108,105,98,46,114,115],"byte_start":911,"byte_end":934,"line_start":23,"line_end":23,"column_start":34,"column_end":57}},{"value":"rustc_alloc_kind = \"exe\"","span":{"file_name":[108,105,98,97,108,108,111,99,95,106,101,109,97,108,108,111,99,47,108,105,98,46,114,115],"byte_start":936,"byte_end":964,"line_start":24,"line_end":24,"column_start":1,"column_end":29}}]},{"kind":"Function","id":{"krate":0,"index":38},"span":{"file_name":[108,105,98,97,108,108,111,99,95,106,101,109,97,108,108,111,99,47,108,105,98,46,114,115],"byte_start":3888,"byte_end":3899,"line_start":97,"line_end":97,"column_start":26,"column_end":37},"name":"__rde_alloc","qualname":"::contents::__rde_alloc","value":"fn (size: usize, align: usize) -> *mut u8","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[{"value":"no_mangle","span":{"file_name":[108,105,98,97,108,108,111,99,95,106,101,109,97,108,108,111,99,47,108,105,98,46,114,115],"byte_start":3817,"byte_end":3829,"line_start":95,"line_end":95,"column_start":5,"column_end":17}},{"value":"rustc_std_internal_symbol","span":{"file_name":[108,105,98,97,108,108,111,99,95,106,101,109,97,108,108,111,99,47,108,105,98,46,114,115],"byte_start":3834,"byte_end":3862,"line_start":96,"line_end":96,"column_start":5,"column_end":33}}]},{"kind":"Function","id":{"krate":0,"index":40},"span":{"file_name":[108,105,98,97,108,108,111,99,95,106,101,109,97,108,108,111,99,47,108,105,98,46,114,115],"byte_start":4144,"byte_end":4153,"line_start":105,"line_end":105,"column_start":26,"column_end":35},"name":"__rde_oom","qualname":"::contents::__rde_oom","value":"fn () -> !","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[{"value":"no_mangle","span":{"file_name":[108,105,98,97,108,108,111,99,95,106,101,109,97,108,108,111,99,47,108,105,98,46,114,115],"byte_start":4073,"byte_end":4085,"line_start":103,"line_end":103,"column_start":5,"column_end":17}},{"value":"rustc_std_internal_symbol","span":{"file_name":[108,105,98,97,108,108,111,99,95,106,101,109,97,108,108,111,99,47,108,105,98,46,114,115],"byte_start":4090,"byte_end":4118,"line_start":104,"line_end":104,"column_start":5,"column_end":33}}]},{"kind":"Function","id":{"krate":0,"index":42},"span":{"file_name":[108,105,98,97,108,108,111,99,95,106,101,109,97,108,108,111,99,47,108,105,98,46,114,115],"byte_start":4266,"byte_end":4279,"line_start":111,"line_end":111,"column_start":26,"column_end":39},"name":"__rde_dealloc","qualname":"::contents::__rde_dealloc","value":"fn (ptr: *mut u8, size: usize, align: usize) -> ()","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[{"value":"no_mangle","span":{"file_name":[108,105,98,97,108,108,111,99,95,106,101,109,97,108,108,111,99,47,108,105,98,46,114,115],"byte_start":4195,"byte_end":4207,"line_start":109,"line_end":109,"column_start":5,"column_end":17}},{"value":"rustc_std_internal_symbol","span":{"file_name":[108,105,98,97,108,108,111,99,95,106,101,109,97,108,108,111,99,47,108,105,98,46,114,115],"byte_start":4212,"byte_end":4240,"line_start":110,"line_end":110,"column_start":5,"column_end":33}}]},{"kind":"Function","id":{"krate":0,"index":44},"span":{"file_name":[108,105,98,97,108,108,111,99,95,106,101,109,97,108,108,111,99,47,108,105,98,46,114,115],"byte_start":4583,"byte_end":4596,"line_start":120,"line_end":120,"column_start":26,"column_end":39},"name":"__rde_realloc","qualname":"::contents::__rde_realloc","value":"fn (ptr: *mut u8, _old_size: usize, align: usize, new_size: usize) -> *mut u8","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[{"value":"no_mangle","span":{"file_name":[108,105,98,97,108,108,111,99,95,106,101,109,97,108,108,111,99,47,108,105,98,46,114,115],"byte_start":4512,"byte_end":4524,"line_start":118,"line_end":118,"column_start":5,"column_end":17}},{"value":"rustc_std_internal_symbol","span":{"file_name":[108,105,98,97,108,108,111,99,95,106,101,109,97,108,108,111,99,47,108,105,98,46,114,115],"byte_start":4529,"byte_end":4557,"line_start":119,"line_end":119,"column_start":5,"column_end":33}}]},{"kind":"Function","id":{"krate":0,"index":46},"span":{"file_name":[108,105,98,97,108,108,111,99,95,106,101,109,97,108,108,111,99,47,108,105,98,46,114,115],"byte_start":5012,"byte_end":5030,"line_start":131,"line_end":131,"column_start":26,"column_end":44},"name":"__rde_alloc_zeroed","qualname":"::contents::__rde_alloc_zeroed","value":"fn (size: usize, align: usize) -> *mut u8","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[{"value":"no_mangle","span":{"file_name":[108,105,98,97,108,108,111,99,95,106,101,109,97,108,108,111,99,47,108,105,98,46,114,115],"byte_start":4941,"byte_end":4953,"line_start":129,"line_end":129,"column_start":5,"column_end":17}},{"value":"rustc_std_internal_symbol","span":{"file_name":[108,105,98,97,108,108,111,99,95,106,101,109,97,108,108,111,99,47,108,105,98,46,114,115],"byte_start":4958,"byte_end":4986,"line_start":130,"line_end":130,"column_start":5,"column_end":33}}]}],"impls":[],"refs":[],"macro_refs":[],"relations":[]} -------------------------------------------------------------------------------- /test_data/types/save-analysis/types-e743a203eefaed5b.json: -------------------------------------------------------------------------------- 1 | {"config":{"output_file":null,"full_docs":false,"pub_only":false,"distro_crate":false,"signatures":false,"borrow_data":false,"reachable_only":false},"prelude":{"crate_id":{"name":"types","disambiguator":[10593865102013156894,6545784844525900726]},"crate_root":"src","external_crates":[{"file_name":"/Users/nick/version-controlled/rls-analysis/test_data/types/src/main.rs","num":11,"id":{"name":"panic_unwind","disambiguator":[1470886469274646872,4913849771986626543]}},{"file_name":"/Users/nick/version-controlled/rls-analysis/test_data/types/src/main.rs","num":8,"id":{"name":"unwind","disambiguator":[11475427707654510054,16563176118568445864]}},{"file_name":"/Users/nick/version-controlled/rls-analysis/test_data/types/src/main.rs","num":5,"id":{"name":"std_unicode","disambiguator":[10645611813973175225,10891693520051835349]}},{"file_name":"/Users/nick/version-controlled/rls-analysis/test_data/types/src/main.rs","num":2,"id":{"name":"core","disambiguator":[1700093346002481410,17403001446876545793]}},{"file_name":"/Users/nick/version-controlled/rls-analysis/test_data/types/src/main.rs","num":10,"id":{"name":"alloc_jemalloc","disambiguator":[6550104761824210885,8729109358135419265]}},{"file_name":"/Users/nick/version-controlled/rls-analysis/test_data/types/src/main.rs","num":7,"id":{"name":"libc","disambiguator":[13431244914785307380,7723876973215078197]}},{"file_name":"/Users/nick/version-controlled/rls-analysis/test_data/types/src/main.rs","num":4,"id":{"name":"alloc","disambiguator":[2026920037113101974,1543435218536837487]}},{"file_name":"/Users/nick/version-controlled/rls-analysis/test_data/types/src/main.rs","num":1,"id":{"name":"std","disambiguator":[15284331701182504962,16311859152430154224]}},{"file_name":"/Users/nick/version-controlled/rls-analysis/test_data/types/src/main.rs","num":9,"id":{"name":"compiler_builtins","disambiguator":[565570356387864648,5119338295999353077]}},{"file_name":"/Users/nick/version-controlled/rls-analysis/test_data/types/src/main.rs","num":6,"id":{"name":"alloc_system","disambiguator":[13009355466220192247,12059247838711315142]}},{"file_name":"/Users/nick/version-controlled/rls-analysis/test_data/types/src/main.rs","num":3,"id":{"name":"rand","disambiguator":[17988324536833200149,7984823588437013118]}}],"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":0,"byte_end":419,"line_start":1,"line_end":32,"column_start":1,"column_end":2}},"imports":[],"defs":[{"kind":"Mod","id":{"krate":0,"index":0},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":0,"byte_end":419,"line_start":1,"line_end":32,"column_start":1,"column_end":2},"name":"","qualname":"::","value":"src/main.rs","parent":null,"children":[{"krate":0,"index":1},{"krate":0,"index":2},{"krate":0,"index":3},{"krate":0,"index":4},{"krate":0,"index":5},{"krate":0,"index":8},{"krate":0,"index":10},{"krate":0,"index":11},{"krate":0,"index":13}],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Struct","id":{"krate":0,"index":3},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":7,"byte_end":10,"line_start":1,"line_end":1,"column_start":8,"column_end":11},"name":"Foo","qualname":"::Foo","value":"Foo { f }","parent":null,"children":[{"krate":0,"index":2147483657}],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Field","id":{"krate":0,"index":2147483657},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":17,"byte_end":18,"line_start":2,"line_end":2,"column_start":5,"column_end":6},"name":"f","qualname":"::Foo::f","value":"u32","parent":{"krate":0,"index":3},"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Function","id":{"krate":0,"index":4},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":31,"byte_end":35,"line_start":5,"line_end":5,"column_start":4,"column_end":8},"name":"main","qualname":"::main","value":"fn () -> ()","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Local","id":{"krate":0,"index":4294967282},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":48,"byte_end":49,"line_start":6,"line_end":6,"column_start":9,"column_end":10},"name":"x","qualname":"x$13","value":"Foo","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Local","id":{"krate":0,"index":4294967272},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":97,"byte_end":98,"line_start":10,"line_end":10,"column_start":8,"column_end":9},"name":"x","qualname":"::foo::x","value":"Foo","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Function","id":{"krate":0,"index":5},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":93,"byte_end":96,"line_start":10,"line_end":10,"column_start":4,"column_end":7},"name":"foo","qualname":"::foo","value":"fn (x: Foo) -> Foo","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Local","id":{"krate":0,"index":4294967267},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":122,"byte_end":134,"line_start":11,"line_end":11,"column_start":9,"column_end":21},"name":"test_binding","qualname":"test_binding$28","value":"bool","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Const","id":{"krate":0,"index":6},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":153,"byte_end":163,"line_start":12,"line_end":12,"column_start":11,"column_end":21},"name":"TEST_CONST","qualname":"::foo::TEST_CONST","value":"bool","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Static","id":{"krate":0,"index":7},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":189,"byte_end":200,"line_start":13,"line_end":13,"column_start":12,"column_end":23},"name":"TEST_STATIC","qualname":"::foo::TEST_STATIC","value":"u32","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Mod","id":{"krate":0,"index":8},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":233,"byte_end":244,"line_start":17,"line_end":17,"column_start":5,"column_end":16},"name":"test_module","qualname":"::test_module","value":"src/main.rs","parent":null,"children":[{"krate":0,"index":9}],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Type","id":{"krate":0,"index":9},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":256,"byte_end":264,"line_start":18,"line_end":18,"column_start":10,"column_end":18},"name":"TestType","qualname":"::test_module::TestType","value":"u32","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Union","id":{"krate":0,"index":10},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":281,"byte_end":290,"line_start":21,"line_end":21,"column_start":7,"column_end":16},"name":"TestUnion","qualname":"::TestUnion","value":"TestUnion { f1 }","parent":null,"children":[{"krate":0,"index":2147483658}],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Field","id":{"krate":0,"index":2147483658},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":297,"byte_end":299,"line_start":22,"line_end":22,"column_start":5,"column_end":7},"name":"f1","qualname":"::TestUnion::f1","value":"u32","parent":{"krate":0,"index":10},"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Trait","id":{"krate":0,"index":11},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":314,"byte_end":323,"line_start":25,"line_end":25,"column_start":7,"column_end":16},"name":"TestTrait","qualname":"::TestTrait","value":"TestTrait","parent":null,"children":[{"krate":0,"index":12}],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Method","id":{"krate":0,"index":12},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":333,"byte_end":344,"line_start":26,"line_end":26,"column_start":8,"column_end":19},"name":"test_method","qualname":"::TestTrait::test_method","value":"fn (&self) -> ()","parent":{"krate":0,"index":11},"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"TupleVariant","id":{"krate":0,"index":2147483659},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":375,"byte_end":387,"line_start":30,"line_end":30,"column_start":5,"column_end":17},"name":"TupleVariant","qualname":"::FooEnum::TupleVariant","value":"FooEnum::TupleVariant","parent":{"krate":0,"index":13},"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"StructVariant","id":{"krate":0,"index":2147483660},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":393,"byte_end":406,"line_start":31,"line_end":31,"column_start":5,"column_end":18},"name":"StructVariant","qualname":"::FooEnum::StructVariant","value":"FooEnum::StructVariant { x }","parent":{"krate":0,"index":13},"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Field","id":{"krate":0,"index":2147483661},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":409,"byte_end":410,"line_start":31,"line_end":31,"column_start":21,"column_end":22},"name":"x","qualname":"::FooEnum::StructVariant::x","value":"u8","parent":{"krate":0,"index":2147483660},"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Enum","id":{"krate":0,"index":13},"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":361,"byte_end":368,"line_start":29,"line_end":29,"column_start":6,"column_end":13},"name":"FooEnum","qualname":"::FooEnum","value":"FooEnum::{TupleVariant, StructVariant}","parent":null,"children":[{"krate":0,"index":2147483659},{"krate":0,"index":2147483660}],"decl_id":null,"docs":"","sig":null,"attributes":[]}],"impls":[],"refs":[{"kind":"Mod","span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":0,"byte_end":0,"line_start":1,"line_end":1,"column_start":1,"column_end":1},"ref_id":{"krate":4294967295,"index":4294967295}},{"kind":"Mod","span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":0,"byte_end":0,"line_start":1,"line_end":1,"column_start":1,"column_end":1},"ref_id":{"krate":4294967295,"index":4294967295}},{"kind":"Mod","span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":0,"byte_end":0,"line_start":1,"line_end":1,"column_start":1,"column_end":1},"ref_id":{"krate":4294967295,"index":4294967295}},{"kind":"Type","span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":52,"byte_end":55,"line_start":6,"line_end":6,"column_start":13,"column_end":16},"ref_id":{"krate":0,"index":3}},{"kind":"Variable","span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":58,"byte_end":59,"line_start":6,"line_end":6,"column_start":19,"column_end":20},"ref_id":{"krate":0,"index":2147483657}},{"kind":"Type","span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":78,"byte_end":81,"line_start":7,"line_end":7,"column_start":12,"column_end":15},"ref_id":{"krate":0,"index":3}},{"kind":"Variable","span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":84,"byte_end":85,"line_start":7,"line_end":7,"column_start":18,"column_end":19},"ref_id":{"krate":0,"index":4294967282}},{"kind":"Type","span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":100,"byte_end":103,"line_start":10,"line_end":10,"column_start":11,"column_end":14},"ref_id":{"krate":0,"index":3}},{"kind":"Type","span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":108,"byte_end":111,"line_start":10,"line_end":10,"column_start":19,"column_end":22},"ref_id":{"krate":0,"index":3}}],"macro_refs":[{"span":{"file_name":[115,114,99,47,109,97,105,110,46,114,115],"byte_start":216,"byte_end":225,"line_start":14,"line_end":14,"column_start":5,"column_end":14},"qualname":"panic","callee_span":{"file_name":[47,85,115,101,114,115,47,116,114,97,118,105,115,47,98,117,105,108,100,47,114,117,115,116,45,108,97,110,103,47,114,117,115,116,47,115,114,99,47,108,105,98,115,116,100,47,109,97,99,114,111,115,46,114,115],"byte_start":23059,"byte_end":23445,"line_start":64,"line_end":75,"column_start":1,"column_end":2}}],"relations":[]} -------------------------------------------------------------------------------- /src/analysis.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The RLS Project Developers. 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | use std::collections::{HashMap, HashSet}; 10 | use std::path::{Path, PathBuf}; 11 | use std::time::SystemTime; 12 | use std::iter; 13 | use fst; 14 | 15 | use {Id, Span, SymbolQuery}; 16 | use raw::{CrateId, DefKind}; 17 | 18 | /// This is the main database that contains all the collected symbol information, 19 | /// such as definitions, their mapping between spans, hierarchy and so on, 20 | /// organized in a per-crate fashion. 21 | #[derive(Debug)] 22 | crate struct Analysis { 23 | /// Contains lowered data with global inter-crate `Id`s per each crate. 24 | pub per_crate: HashMap, 25 | 26 | // This is a bit of a hack and should be considered temporary. A def has an 27 | // entry if there exists an import of the def which aliases it. We use this 28 | // for find_all_refs with unique spans to ensure that clients don't rename a 29 | // definition when they only mean to rename an alias. 30 | // 31 | // In the future we should handle imports, in particular aliasing ones, more 32 | // explicitly and then this can be removed. 33 | crate aliased_imports: HashSet, 34 | 35 | // Maps a crate names to the crate ids for all crates with that name. 36 | crate crate_names: HashMap>, 37 | 38 | pub doc_url_base: String, 39 | pub src_url_base: String, 40 | } 41 | 42 | #[derive(Debug)] 43 | pub struct PerCrateAnalysis { 44 | // Map span to id of def (either because it is the span of the def, or of 45 | // the def for the ref). 46 | pub def_id_for_span: HashMap, 47 | pub defs: HashMap, 48 | pub defs_per_file: HashMap>, 49 | pub children: HashMap>, 50 | pub def_names: HashMap>, 51 | 52 | // Index of all symbols that powers the search. 53 | // See `SymbolQuery`. 54 | pub def_fst: fst::Map, 55 | pub def_fst_values: Vec>, 56 | 57 | pub ref_spans: HashMap>, 58 | pub globs: HashMap, 59 | pub impls: HashMap>, 60 | 61 | pub root_id: Option, 62 | pub timestamp: SystemTime, 63 | pub path: Option, 64 | // All definitions in this crate will include the global_crate_num. See 65 | // lowering::id_from_compiler_id for details of how. 66 | // global_crate_num is not available until after lowering. 67 | pub global_crate_num: u32, 68 | } 69 | 70 | #[derive(Debug, Clone)] 71 | pub enum Ref { 72 | // The common case - a reference to a single definition. 73 | Id(Id), 74 | // Two defs contribute to a single reference, occurs in the field name 75 | // shorthand, maybe other places. 76 | Double(Id, Id), 77 | // Multiple ids, we record only the first def we found, plus a count of defs. 78 | // Should only happen due to generated code which has not been well-filtered 79 | // by the compiler. 80 | Multi(Id, usize), 81 | } 82 | 83 | impl Ref { 84 | pub fn some_id(&self) -> Id { 85 | match *self { 86 | Ref::Id(id) => id, 87 | Ref::Double(id, _) => id, 88 | Ref::Multi(id, _) => id, 89 | } 90 | } 91 | 92 | pub fn add_id(&self, def_id: Id) -> Ref { 93 | match *self { 94 | Ref::Id(id) => Ref::Double(id, def_id), 95 | Ref::Double(id, _) => Ref::Multi(id, 3), 96 | Ref::Multi(id, n) => Ref::Multi(id, n + 1), 97 | } 98 | } 99 | } 100 | 101 | #[derive(Debug, Clone)] 102 | pub struct Def { 103 | pub kind: DefKind, 104 | pub span: Span, 105 | pub name: String, 106 | pub qualname: String, 107 | pub distro_crate: bool, 108 | pub parent: Option, 109 | pub value: String, 110 | pub docs: String, 111 | // pub sig: Option, 112 | } 113 | 114 | #[derive(Debug, Clone)] 115 | pub struct Signature { 116 | pub span: Span, 117 | pub text: String, 118 | pub ident_start: u32, 119 | pub ident_end: u32, 120 | pub defs: Vec, 121 | pub refs: Vec, 122 | } 123 | 124 | #[derive(Debug, Clone)] 125 | pub struct SigElement { 126 | pub id: Id, 127 | pub start: usize, 128 | pub end: usize, 129 | } 130 | 131 | #[derive(Debug)] 132 | pub struct Glob { 133 | pub value: String, 134 | } 135 | 136 | 137 | impl PerCrateAnalysis { 138 | pub fn new(timestamp: SystemTime, path: Option) -> PerCrateAnalysis { 139 | let empty_fst = 140 | fst::Map::from_iter(iter::empty::<(String, u64)>()).unwrap(); 141 | PerCrateAnalysis { 142 | def_id_for_span: HashMap::new(), 143 | defs: HashMap::new(), 144 | defs_per_file: HashMap::new(), 145 | children: HashMap::new(), 146 | def_names: HashMap::new(), 147 | def_fst: empty_fst, 148 | def_fst_values: Vec::new(), 149 | ref_spans: HashMap::new(), 150 | globs: HashMap::new(), 151 | impls: HashMap::new(), 152 | root_id: None, 153 | timestamp, 154 | path, 155 | global_crate_num: 0, 156 | } 157 | } 158 | 159 | // Returns true if there is a def in this crate with the same crate-local id 160 | // and span as `def`. 161 | crate fn has_congruent_def(&self, local_id: u32, span: &Span) -> bool { 162 | let id = Id::from_crate_and_local(self.global_crate_num, local_id); 163 | match self.defs.get(&id) { 164 | Some(existing) => span == &existing.span, 165 | None => false, 166 | } 167 | } 168 | } 169 | 170 | impl Analysis { 171 | pub fn new() -> Analysis { 172 | Analysis { 173 | per_crate: HashMap::new(), 174 | aliased_imports: HashSet::new(), 175 | crate_names: HashMap::new(), 176 | // TODO don't hardcode these 177 | doc_url_base: "https://doc.rust-lang.org/nightly".to_owned(), 178 | src_url_base: "https://github.com/rust-lang/rust/blob/master".to_owned(), 179 | } 180 | } 181 | 182 | pub fn timestamps(&self) -> HashMap { 183 | self.per_crate 184 | .values() 185 | .filter(|c| c.path.is_some()) 186 | .map(|c| (c.path.as_ref().unwrap().clone(), c.timestamp.clone())) 187 | .collect() 188 | } 189 | 190 | pub fn update(&mut self, crate_id: CrateId, per_crate: PerCrateAnalysis) { 191 | self.per_crate.insert(crate_id, per_crate); 192 | } 193 | 194 | pub fn has_def(&self, id: Id) -> bool { 195 | self.per_crate.values().any(|c| c.defs.contains_key(&id)) 196 | } 197 | 198 | pub fn for_each_crate(&self, f: F) -> Option 199 | where 200 | F: Fn(&PerCrateAnalysis) -> Option, 201 | { 202 | let mut result = vec![]; 203 | for per_crate in self.per_crate.values() { 204 | if let Some(t) = f(per_crate) { 205 | result.push(t); 206 | } 207 | } 208 | 209 | // This assertion is sometimes helpful for debugging, but also can cause 210 | // problems where otherwise there are none. 211 | // FIXME - might be worth investigating some common causes. 212 | // assert!( 213 | // result.len() <= 1, 214 | // "error in for_each_crate, found {} results, expected 0 or 1", 215 | // result.len(), 216 | // ); 217 | let temp = result.drain(..).next(); 218 | temp // stupid NLL bug 219 | } 220 | 221 | pub fn for_all_crates(&self, f: F) -> Vec 222 | where 223 | F: Fn(&PerCrateAnalysis) -> Option>, 224 | { 225 | let mut result = vec![]; 226 | for per_crate in self.per_crate.values() { 227 | if let Some(this_crate) = f(per_crate) { 228 | result.extend(this_crate); 229 | } 230 | } 231 | 232 | result 233 | } 234 | 235 | pub fn def_id_for_span(&self, span: &Span) -> Option { 236 | self.ref_for_span(span).map(|r| r.some_id()) 237 | } 238 | 239 | pub fn ref_for_span(&self, span: &Span) -> Option { 240 | self.for_each_crate(|c| c.def_id_for_span.get(span).map(|r| r.clone())) 241 | } 242 | 243 | // Like def_id_for_span, but will only return a def_id if it is in the same 244 | // crate. 245 | pub fn local_def_id_for_span(&self, span: &Span) -> Option { 246 | self.for_each_crate(|c| { 247 | c.def_id_for_span 248 | .get(span) 249 | .map(|r| r.some_id()) 250 | .and_then(|id| if c.defs.contains_key(&id) { 251 | Some(id) 252 | } else { 253 | None 254 | }) 255 | }) 256 | } 257 | 258 | pub fn with_defs(&self, id: Id, f: F) -> Option 259 | where 260 | F: Fn(&Def) -> T, 261 | { 262 | self.for_each_crate(|c| c.defs.get(&id).map(&f)) 263 | } 264 | 265 | pub fn with_defs_and_then(&self, id: Id, f: F) -> Option 266 | where 267 | F: Fn(&Def) -> Option, 268 | { 269 | self.for_each_crate(|c| c.defs.get(&id).and_then(&f)) 270 | } 271 | 272 | pub fn with_globs(&self, span: &Span, f: F) -> Option 273 | where 274 | F: Fn(&Glob) -> T, 275 | { 276 | self.for_each_crate(|c| c.globs.get(span).map(&f)) 277 | } 278 | 279 | pub fn for_each_child(&self, id: Id, mut f: F) -> Option> 280 | where 281 | F: FnMut(Id, &Def) -> T, 282 | { 283 | for per_crate in self.per_crate.values() { 284 | if let Some(children) = per_crate.children.get(&id) { 285 | return Some( 286 | children 287 | .iter() 288 | .filter_map(|id| { 289 | let def = per_crate.defs.get(id); 290 | if def.is_none() { 291 | info!("def not found for {}", id); 292 | } 293 | def.map(|def| f(*id, def)) 294 | }) 295 | .collect(), 296 | ); 297 | } 298 | } 299 | 300 | Some(vec![]) 301 | } 302 | 303 | pub fn with_ref_spans(&self, id: Id, f: F) -> Option 304 | where 305 | F: Fn(&Vec) -> Option, 306 | { 307 | self.for_each_crate(|c| c.ref_spans.get(&id).and_then(&f)) 308 | } 309 | 310 | pub fn with_defs_per_file(&self, file: &Path, f: F) -> Option 311 | where 312 | F: Fn(&Vec) -> T, 313 | { 314 | self.for_each_crate(|c| c.defs_per_file.get(file).map(&f)) 315 | } 316 | 317 | pub fn query_defs(&self, query: SymbolQuery) -> Vec { 318 | let mut crates = Vec::with_capacity(self.per_crate.len()); 319 | let stream = query.build_stream( 320 | self.per_crate.values().map(|c| { 321 | crates.push(c); 322 | &c.def_fst 323 | }) 324 | ); 325 | 326 | query.search_stream(stream, |acc, e| { 327 | let c = &crates[e.index]; 328 | let ids = &c.def_fst_values[e.value as usize]; 329 | acc.extend( 330 | ids.iter().flat_map(|id| c.defs.get(id)).cloned() 331 | ); 332 | }) 333 | } 334 | 335 | pub fn with_def_names(&self, name: &str, f: F) -> Vec 336 | where 337 | F: Fn(&Vec) -> Vec, 338 | { 339 | self.for_all_crates(|c| c.def_names.get(name).map(&f)) 340 | } 341 | } 342 | -------------------------------------------------------------------------------- /src/test/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The RLS Project Developers. 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | use {AnalysisHost, AnalysisLoader}; 10 | use loader::SearchDirectory; 11 | use raw::DefKind; 12 | 13 | use std::collections::HashSet; 14 | use std::path::{Path, PathBuf}; 15 | 16 | #[cfg(test)] 17 | extern crate env_logger; 18 | 19 | #[derive(Clone, new)] 20 | struct TestAnalysisLoader { 21 | path: PathBuf, 22 | } 23 | 24 | impl AnalysisLoader for TestAnalysisLoader { 25 | fn needs_hard_reload(&self, _path_prefix: &Path) -> bool { 26 | true 27 | } 28 | 29 | fn fresh_host(&self) -> AnalysisHost { 30 | AnalysisHost::new_with_loader(self.clone()) 31 | } 32 | 33 | fn set_path_prefix(&mut self, _path_prefix: &Path) {} 34 | 35 | fn abs_path_prefix(&self) -> Option { 36 | panic!(); 37 | } 38 | 39 | fn search_directories(&self) -> Vec { 40 | vec![SearchDirectory::new(self.path.clone(), None)] 41 | } 42 | } 43 | 44 | #[test] 45 | fn doc_urls_resolve_correctly() { 46 | let host = AnalysisHost::new_with_loader(TestAnalysisLoader::new( 47 | Path::new("test_data/rust-analysis").to_owned(), 48 | )); 49 | host.reload( 50 | Path::new("test_data/rust-analysis"), 51 | Path::new("test_data/rust-analysis"), 52 | ).unwrap(); 53 | 54 | fn assert_url_for_type>>( 55 | host: &AnalysisHost, 56 | type_: &str, 57 | qualname: S, 58 | url: &str, 59 | ) { 60 | let qualname = qualname.into(); 61 | let ids = host.search_for_id(type_).unwrap(); 62 | let defs: Vec<_> = ids.into_iter() 63 | .map(|id| host.get_def(id).unwrap()) 64 | .filter(|def| { 65 | qualname.is_none() || def.qualname == qualname.unwrap() 66 | }) 67 | .collect(); 68 | trace!("{}: {:#?}", type_, defs); 69 | assert_eq!(defs.len(), 1); 70 | assert_eq!(host.doc_url(&defs[0].span), Ok(url.into())); 71 | } 72 | 73 | // FIXME This test cannot work for some values 74 | // Primitives like i64. i64 is shown with type mod but requires name "primitive". 75 | // All methods (instead of trait methods, see as_mut), seem to only be available for generic qualname 76 | // Unions like ManuallyDrop are not in the analysis file, just methods implemented for them or methods using them 77 | 78 | assert_url_for_type( 79 | &host, 80 | "MAIN_SEPARATOR", 81 | None, 82 | "https://doc.rust-lang.org/nightly/std/path/MAIN_SEPARATOR.v.html", 83 | ); 84 | // the parent has a qualname which is not represented in the usage, the ip part 85 | assert_url_for_type( 86 | &host, 87 | "Ipv4Addr", 88 | None, 89 | "https://doc.rust-lang.org/nightly/std/net/ip/Ipv4Addr.t.html", 90 | ); 91 | assert_url_for_type( 92 | &host, 93 | "VarError", 94 | None, 95 | "https://doc.rust-lang.org/nightly/std/env/VarError.t.html", 96 | ); 97 | assert_url_for_type( 98 | &host, 99 | "NotPresent", 100 | None, 101 | "https://doc.rust-lang.org/nightly/std/env/VarError.t.html#NotPresent.v", 102 | ); 103 | assert_url_for_type( 104 | &host, 105 | "Result", 106 | "std::thread::Result", 107 | "https://doc.rust-lang.org/nightly/std/thread/Result.t.html", 108 | ); 109 | assert_url_for_type( 110 | &host, 111 | "args", 112 | "std::env::args", 113 | "https://doc.rust-lang.org/nightly/std/env/args.v.html", 114 | ); 115 | assert_url_for_type( 116 | &host, 117 | "AsciiExt", 118 | None, 119 | "https://doc.rust-lang.org/nightly/std/ascii/AsciiExt.t.html", 120 | ); 121 | assert_url_for_type( 122 | &host, 123 | "is_ascii", 124 | "std::ascii::AsciiExt::is_ascii", 125 | "https://doc.rust-lang.org/nightly/std/ascii/AsciiExt.t.html#is_ascii.v", 126 | ); 127 | assert_url_for_type( 128 | &host, 129 | "status", 130 | "std::process::Output::status", 131 | "https://doc.rust-lang.org/nightly/std/process/Output.t.html#status.v", 132 | ); 133 | assert_url_for_type( 134 | &host, 135 | "copy", 136 | "std::fs::copy", 137 | "https://doc.rust-lang.org/nightly/std/fs/copy.v.html", 138 | ); 139 | // prelude and fs are both mod, but the parent once has a trailing / and once not 140 | assert_url_for_type( 141 | &host, 142 | "prelude", 143 | "std::io::prelude", 144 | "https://doc.rust-lang.org/nightly/std/io/prelude/", 145 | ); 146 | assert_url_for_type( 147 | &host, 148 | "fs", 149 | "std::fs", 150 | "https://doc.rust-lang.org/nightly/std/fs/", 151 | ); 152 | } 153 | 154 | #[test] 155 | fn smoke() { 156 | // Read in test data and lower it, check we don't crash. 157 | let host = AnalysisHost::new_with_loader(TestAnalysisLoader::new( 158 | Path::new("test_data/rls-analysis").to_owned(), 159 | )); 160 | host.reload( 161 | Path::new("test_data/rls-analysis"), 162 | Path::new("test_data/rls-analysis"), 163 | ).unwrap(); 164 | } 165 | 166 | #[test] 167 | fn test_hello() { 168 | // Simple program, a somewhat thorough test that we have all the defs and refs we expect. 169 | let host = AnalysisHost::new_with_loader(TestAnalysisLoader::new( 170 | Path::new("test_data/hello/save-analysis").to_owned(), 171 | )); 172 | host.reload( 173 | Path::new("test_data/hello"), 174 | Path::new("test_data/hello"), 175 | ).unwrap(); 176 | 177 | let ids = host.search_for_id("print_hello").unwrap(); 178 | assert_eq!(ids.len(), 1); 179 | let id = ids[0]; 180 | let def = host.get_def(id).unwrap(); 181 | assert_eq!(def.name, "print_hello"); 182 | assert_eq!(def.kind, DefKind::Function); 183 | let refs = host.find_all_refs_by_id(id).unwrap(); 184 | assert_eq!(refs.len(), 2); 185 | assert_eq!(refs[0].file, Path::new("test_data/hello/src/main.rs")); 186 | assert_eq!(refs[0].range.row_start.0, 0); 187 | assert_eq!(refs[1].file, Path::new("test_data/hello/src/main.rs")); 188 | assert_eq!(refs[1].range.row_start.0, 6); 189 | let refs = host.search("print_hello").unwrap(); 190 | assert_eq!(refs.len(), 2); 191 | assert_eq!(refs[0].file, Path::new("test_data/hello/src/main.rs")); 192 | assert_eq!(refs[0].range.row_start.0, 0); 193 | assert_eq!(refs[1].file, Path::new("test_data/hello/src/main.rs")); 194 | assert_eq!(refs[1].range.row_start.0, 6); 195 | 196 | let ids = host.search_for_id("main").unwrap(); 197 | assert_eq!(ids.len(), 1); 198 | let id = ids[0]; 199 | let def = host.get_def(id).unwrap(); 200 | assert_eq!(def.name, "main"); 201 | assert_eq!(def.kind, DefKind::Function); 202 | let refs = host.find_all_refs_by_id(id).unwrap(); 203 | assert_eq!(refs.len(), 1); 204 | assert_eq!(refs[0].file, Path::new("test_data/hello/src/main.rs")); 205 | assert_eq!(refs[0].range.row_start.0, 5); 206 | let refs = host.search("main").unwrap(); 207 | assert_eq!(refs.len(), 1); 208 | assert_eq!(refs[0].file, Path::new("test_data/hello/src/main.rs")); 209 | assert_eq!(refs[0].range.row_start.0, 5); 210 | 211 | let ids = host.search_for_id("name").unwrap(); 212 | assert_eq!(ids.len(), 1); 213 | let id = ids[0]; 214 | let def = host.get_def(id).unwrap(); 215 | assert_eq!(def.name, "name"); 216 | assert_eq!(def.kind, DefKind::Local); 217 | let refs = host.find_all_refs_by_id(id).unwrap(); 218 | assert_eq!(refs.len(), 2); 219 | assert_eq!(refs[0].file, Path::new("test_data/hello/src/main.rs")); 220 | assert_eq!(refs[0].range.row_start.0, 1); 221 | assert_eq!(refs[1].file, Path::new("test_data/hello/src/main.rs")); 222 | assert_eq!(refs[1].range.row_start.0, 2); 223 | let refs = host.search("name").unwrap(); 224 | assert_eq!(refs.len(), 2); 225 | assert_eq!(refs[0].file, Path::new("test_data/hello/src/main.rs")); 226 | assert_eq!(refs[0].range.row_start.0, 1); 227 | assert_eq!(refs[1].file, Path::new("test_data/hello/src/main.rs")); 228 | assert_eq!(refs[1].range.row_start.0, 2); 229 | 230 | let defs = host.matching_defs("print_hello").unwrap(); 231 | assert_eq!(defs.len(), 1); 232 | let hello_def = &defs[0]; 233 | assert_eq!(hello_def.name, "print_hello"); 234 | assert_eq!(hello_def.kind, DefKind::Function); 235 | assert_eq!(hello_def.span.range.row_start.0, 0); 236 | 237 | let defs = host.matching_defs("main").unwrap(); 238 | assert_eq!(defs.len(), 1); 239 | let main_def = &defs[0]; 240 | assert_eq!(main_def.name, "main"); 241 | assert_eq!(main_def.kind, DefKind::Function); 242 | assert_eq!(main_def.span.range.row_start.0, 5); 243 | 244 | let defs = host.matching_defs("name").unwrap(); 245 | assert_eq!(defs.len(), 1); 246 | let matching_def = &defs[0]; 247 | assert_eq!(matching_def.name, "name"); 248 | assert_eq!(matching_def.kind, DefKind::Local); 249 | assert_eq!(matching_def.span.range.row_start.0, 1); 250 | 251 | assert_eq!(host.matching_defs("goodbye").unwrap().len(), 0); 252 | assert_eq!(host.matching_defs("mäin").unwrap().len(), 0); 253 | 254 | let pri_matches = host.matching_defs("pri").unwrap(); 255 | let print_hello_matches = host.matching_defs("print_hello").unwrap(); 256 | assert_eq!(1, pri_matches.len()); 257 | assert_eq!(1, print_hello_matches.len()); 258 | let pri_f = &pri_matches[0]; 259 | let print_hello_f = &print_hello_matches[0]; 260 | assert_eq!(pri_f.name, print_hello_f.name); 261 | assert_eq!(pri_f.kind, print_hello_f.kind); 262 | 263 | let all_matches = host.matching_defs("") 264 | .unwrap() 265 | .iter() 266 | .map(|d| d.name.to_owned()) 267 | .collect::>(); 268 | 269 | let expected_matches = ["main", "name", "print_hello"] 270 | .iter() 271 | .map(|&m| String::from(m)) 272 | .collect::>(); 273 | assert_eq!(all_matches, expected_matches); 274 | } 275 | 276 | // TODO 277 | // check span functions 278 | // check complex programs 279 | 280 | #[test] 281 | fn test_types() { 282 | fn assert_type( 283 | host: &AnalysisHost, 284 | name: &str, 285 | def_kind: DefKind, 286 | expect_lines: &[u32], 287 | ) { 288 | let ids = host.search_for_id(name).unwrap(); 289 | println!("name: {}", name); 290 | assert_eq!(ids.len(), 1); 291 | 292 | let id = ids[0]; 293 | let def = host.get_def(id).unwrap(); 294 | assert_eq!(def.name, name); 295 | assert_eq!(def.kind, def_kind); 296 | 297 | let refs = host.find_all_refs_by_id(id).unwrap(); 298 | assert_eq!(refs.len(), expect_lines.len()); 299 | 300 | for (i, start) in expect_lines.iter().enumerate() { 301 | assert_eq!(refs[i].file, Path::new("test_data/types/src/main.rs")); 302 | assert_eq!(refs[i].range.row_start.0 + 1, *start); 303 | } 304 | } 305 | 306 | let host = AnalysisHost::new_with_loader(TestAnalysisLoader::new( 307 | Path::new("test_data/types/save-analysis").to_owned(), 308 | )); 309 | host.reload(Path::new("test_data/types"), Path::new("test_data/types")) 310 | .unwrap(); 311 | 312 | assert_type(&host, "Foo", DefKind::Struct, &[1, 6, 7, 10, 10]); 313 | assert_type(&host, "f", DefKind::Field, &[2, 6]); 314 | assert_type(&host, "main", DefKind::Function, &[5]); 315 | assert_type(&host, "test_binding", DefKind::Local, &[11]); 316 | assert_type(&host, "TEST_CONST", DefKind::Const, &[12]); 317 | assert_type(&host, "TEST_STATIC", DefKind::Static, &[13]); 318 | assert_type(&host, "test_module", DefKind::Mod, &[17]); 319 | assert_type(&host, "TestType", DefKind::Type, &[18]); 320 | assert_type(&host, "TestUnion", DefKind::Union, &[21]); 321 | assert_type(&host, "TestTrait", DefKind::Trait, &[25]); 322 | assert_type(&host, "test_method", DefKind::Method, &[26]); 323 | assert_type(&host, "FooEnum", DefKind::Enum, &[29]); 324 | assert_type(&host, "TupleVariant", DefKind::TupleVariant, &[30]); 325 | assert_type(&host, "StructVariant", DefKind::StructVariant, &[31]); 326 | 327 | let t_matches = host.matching_defs("t").unwrap(); 328 | let t_names = t_matches.iter().map(|m| m.name.to_owned()).collect::>(); 329 | let expected_t_names = ["TEST_CONST", "TEST_STATIC", "TestTrait", "TestType", "TestUnion", 330 | "TupleVariant", "test_binding", "test_method", "test_module"] 331 | .iter() 332 | .map(|&n| String::from(n)) 333 | .collect::>(); 334 | 335 | assert_eq!(t_names, expected_t_names); 336 | 337 | let upper_matches = host.matching_defs("FOOENUM").unwrap(); 338 | let lower_matches = host.matching_defs("fooenum").unwrap(); 339 | assert_eq!(upper_matches[0].name, "FooEnum"); 340 | assert_eq!(lower_matches[0].name, "FooEnum"); 341 | } 342 | 343 | #[test] 344 | fn test_child_count() { 345 | let host = AnalysisHost::new_with_loader(TestAnalysisLoader::new( 346 | Path::new("test_data/types/save-analysis").to_owned(), 347 | )); 348 | host.reload(Path::new("test_data/types"), Path::new("test_data/types")) 349 | .unwrap(); 350 | 351 | let ids = host.search_for_id("Foo").unwrap(); 352 | let id = ids[0]; 353 | assert_eq!(host.for_each_child_def(id, |id, _| id).unwrap().len(), 1); 354 | } 355 | 356 | #[test] 357 | fn test_self() { 358 | let host = AnalysisHost::new_with_loader(TestAnalysisLoader::new( 359 | Path::new("test_data/exprs/save-analysis").to_owned(), 360 | )); 361 | host.reload(Path::new("test_data/exprs"), Path::new("test_data/exprs")) 362 | .unwrap(); 363 | 364 | let spans = host.search("self").unwrap(); 365 | assert_eq!(spans.len(), 2); 366 | let def = host.goto_def(&spans[1]); 367 | assert_eq!(def.unwrap(), spans[0]); 368 | } 369 | 370 | #[test] 371 | fn test_extern_fn() { 372 | let host = AnalysisHost::new_with_loader(TestAnalysisLoader::new( 373 | Path::new("test_data/exprs/save-analysis").to_owned(), 374 | )); 375 | host.reload(Path::new("test_data/exprs"), Path::new("test_data/exprs")) 376 | .unwrap(); 377 | 378 | let spans = host.search("foo").unwrap(); 379 | assert_eq!(spans.len(), 2); 380 | let def = host.goto_def(&spans[1]); 381 | assert_eq!(def.unwrap(), spans[0]); 382 | } 383 | 384 | #[test] 385 | fn test_all_ref_unique() { 386 | let host = AnalysisHost::new_with_loader(TestAnalysisLoader::new( 387 | Path::new("test_data/rename/save-analysis").to_owned(), 388 | )); 389 | host.reload(Path::new("test_data/rename"), Path::new("test_data/rename")) 390 | .unwrap(); 391 | 392 | let spans = host.search("bar").unwrap(); 393 | assert_eq!(spans.len(), 4); 394 | let refs = host.find_all_refs(&spans[3], true, true); 395 | assert_eq!(refs.unwrap().len(), 0); 396 | 397 | let spans = host.search("qux").unwrap(); 398 | assert_eq!(spans.len(), 3); 399 | let refs = host.find_all_refs(&spans[2], true, true); 400 | assert_eq!(refs.unwrap().len(), 3); 401 | } 402 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "aho-corasick" 5 | version = "0.6.9" 6 | source = "registry+https://github.com/rust-lang/crates.io-index" 7 | dependencies = [ 8 | "memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 9 | ] 10 | 11 | [[package]] 12 | name = "atty" 13 | version = "0.2.11" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | dependencies = [ 16 | "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", 17 | "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 18 | "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 19 | ] 20 | 21 | [[package]] 22 | name = "byteorder" 23 | version = "1.3.1" 24 | source = "registry+https://github.com/rust-lang/crates.io-index" 25 | 26 | [[package]] 27 | name = "cfg-if" 28 | version = "0.1.6" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | 31 | [[package]] 32 | name = "derive-new" 33 | version = "0.5.6" 34 | source = "registry+https://github.com/rust-lang/crates.io-index" 35 | dependencies = [ 36 | "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", 37 | "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", 38 | "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", 39 | ] 40 | 41 | [[package]] 42 | name = "either" 43 | version = "1.5.0" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | 46 | [[package]] 47 | name = "env_logger" 48 | version = "0.5.13" 49 | source = "registry+https://github.com/rust-lang/crates.io-index" 50 | dependencies = [ 51 | "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", 52 | "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 53 | "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 54 | "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 55 | "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", 56 | ] 57 | 58 | [[package]] 59 | name = "fst" 60 | version = "0.3.3" 61 | source = "registry+https://github.com/rust-lang/crates.io-index" 62 | dependencies = [ 63 | "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 64 | ] 65 | 66 | [[package]] 67 | name = "humantime" 68 | version = "1.2.0" 69 | source = "registry+https://github.com/rust-lang/crates.io-index" 70 | dependencies = [ 71 | "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 72 | ] 73 | 74 | [[package]] 75 | name = "itertools" 76 | version = "0.7.11" 77 | source = "registry+https://github.com/rust-lang/crates.io-index" 78 | dependencies = [ 79 | "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", 80 | ] 81 | 82 | [[package]] 83 | name = "json" 84 | version = "0.11.13" 85 | source = "registry+https://github.com/rust-lang/crates.io-index" 86 | 87 | [[package]] 88 | name = "lazy_static" 89 | version = "1.2.0" 90 | source = "registry+https://github.com/rust-lang/crates.io-index" 91 | 92 | [[package]] 93 | name = "libc" 94 | version = "0.2.48" 95 | source = "registry+https://github.com/rust-lang/crates.io-index" 96 | 97 | [[package]] 98 | name = "log" 99 | version = "0.4.6" 100 | source = "registry+https://github.com/rust-lang/crates.io-index" 101 | dependencies = [ 102 | "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", 103 | ] 104 | 105 | [[package]] 106 | name = "memchr" 107 | version = "2.1.3" 108 | source = "registry+https://github.com/rust-lang/crates.io-index" 109 | dependencies = [ 110 | "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", 111 | "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", 112 | ] 113 | 114 | [[package]] 115 | name = "proc-macro2" 116 | version = "0.4.27" 117 | source = "registry+https://github.com/rust-lang/crates.io-index" 118 | dependencies = [ 119 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 120 | ] 121 | 122 | [[package]] 123 | name = "quick-error" 124 | version = "1.2.2" 125 | source = "registry+https://github.com/rust-lang/crates.io-index" 126 | 127 | [[package]] 128 | name = "quote" 129 | version = "0.6.11" 130 | source = "registry+https://github.com/rust-lang/crates.io-index" 131 | dependencies = [ 132 | "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", 133 | ] 134 | 135 | [[package]] 136 | name = "redox_syscall" 137 | version = "0.1.51" 138 | source = "registry+https://github.com/rust-lang/crates.io-index" 139 | 140 | [[package]] 141 | name = "redox_termios" 142 | version = "0.1.1" 143 | source = "registry+https://github.com/rust-lang/crates.io-index" 144 | dependencies = [ 145 | "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", 146 | ] 147 | 148 | [[package]] 149 | name = "regex" 150 | version = "1.1.0" 151 | source = "registry+https://github.com/rust-lang/crates.io-index" 152 | dependencies = [ 153 | "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", 154 | "memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 155 | "regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", 156 | "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 157 | "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 158 | ] 159 | 160 | [[package]] 161 | name = "regex-syntax" 162 | version = "0.6.5" 163 | source = "registry+https://github.com/rust-lang/crates.io-index" 164 | dependencies = [ 165 | "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 166 | ] 167 | 168 | [[package]] 169 | name = "rls-analysis" 170 | version = "0.16.12" 171 | dependencies = [ 172 | "derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", 173 | "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", 174 | "fst 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 175 | "itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)", 176 | "json 0.11.13 (registry+https://github.com/rust-lang/crates.io-index)", 177 | "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 178 | "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 179 | "rls-data 0.18.2 (registry+https://github.com/rust-lang/crates.io-index)", 180 | "rls-span 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", 181 | "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", 182 | ] 183 | 184 | [[package]] 185 | name = "rls-data" 186 | version = "0.18.2" 187 | source = "registry+https://github.com/rust-lang/crates.io-index" 188 | dependencies = [ 189 | "rls-span 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", 190 | "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", 191 | ] 192 | 193 | [[package]] 194 | name = "rls-span" 195 | version = "0.4.1" 196 | source = "registry+https://github.com/rust-lang/crates.io-index" 197 | dependencies = [ 198 | "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", 199 | ] 200 | 201 | [[package]] 202 | name = "rustc-serialize" 203 | version = "0.3.24" 204 | source = "registry+https://github.com/rust-lang/crates.io-index" 205 | 206 | [[package]] 207 | name = "syn" 208 | version = "0.15.26" 209 | source = "registry+https://github.com/rust-lang/crates.io-index" 210 | dependencies = [ 211 | "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", 212 | "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", 213 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 214 | ] 215 | 216 | [[package]] 217 | name = "termcolor" 218 | version = "1.0.4" 219 | source = "registry+https://github.com/rust-lang/crates.io-index" 220 | dependencies = [ 221 | "wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 222 | ] 223 | 224 | [[package]] 225 | name = "termion" 226 | version = "1.5.1" 227 | source = "registry+https://github.com/rust-lang/crates.io-index" 228 | dependencies = [ 229 | "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", 230 | "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", 231 | "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 232 | ] 233 | 234 | [[package]] 235 | name = "thread_local" 236 | version = "0.3.6" 237 | source = "registry+https://github.com/rust-lang/crates.io-index" 238 | dependencies = [ 239 | "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 240 | ] 241 | 242 | [[package]] 243 | name = "ucd-util" 244 | version = "0.1.3" 245 | source = "registry+https://github.com/rust-lang/crates.io-index" 246 | 247 | [[package]] 248 | name = "unicode-xid" 249 | version = "0.1.0" 250 | source = "registry+https://github.com/rust-lang/crates.io-index" 251 | 252 | [[package]] 253 | name = "utf8-ranges" 254 | version = "1.0.2" 255 | source = "registry+https://github.com/rust-lang/crates.io-index" 256 | 257 | [[package]] 258 | name = "winapi" 259 | version = "0.3.6" 260 | source = "registry+https://github.com/rust-lang/crates.io-index" 261 | dependencies = [ 262 | "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 263 | "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 264 | ] 265 | 266 | [[package]] 267 | name = "winapi-i686-pc-windows-gnu" 268 | version = "0.4.0" 269 | source = "registry+https://github.com/rust-lang/crates.io-index" 270 | 271 | [[package]] 272 | name = "winapi-util" 273 | version = "0.1.2" 274 | source = "registry+https://github.com/rust-lang/crates.io-index" 275 | dependencies = [ 276 | "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 277 | ] 278 | 279 | [[package]] 280 | name = "winapi-x86_64-pc-windows-gnu" 281 | version = "0.4.0" 282 | source = "registry+https://github.com/rust-lang/crates.io-index" 283 | 284 | [[package]] 285 | name = "wincolor" 286 | version = "1.0.1" 287 | source = "registry+https://github.com/rust-lang/crates.io-index" 288 | dependencies = [ 289 | "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 290 | "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 291 | ] 292 | 293 | [metadata] 294 | "checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e" 295 | "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" 296 | "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" 297 | "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" 298 | "checksum derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6ca414e896ae072546f4d789f452daaecf60ddee4c9df5dc6d5936d769e3d87c" 299 | "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" 300 | "checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38" 301 | "checksum fst 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "db72126ca7dff566cdbbdd54af44668c544897d9d3862b198141f176f1238bdf" 302 | "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" 303 | "checksum itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0d47946d458e94a1b7bcabbf6521ea7c037062c81f534615abcad76e84d4970d" 304 | "checksum json 0.11.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9ad0485404155f45cce53a40d4b2d6ac356418300daed05273d9e26f91c390be" 305 | "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" 306 | "checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047" 307 | "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" 308 | "checksum memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e1dd4eaac298c32ce07eb6ed9242eda7d82955b9170b7d6db59b2e02cc63fcb8" 309 | "checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" 310 | "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" 311 | "checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" 312 | "checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" 313 | "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" 314 | "checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f" 315 | "checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861" 316 | "checksum rls-data 0.18.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5f80b84551b32e26affaf7f12374913b5061730c0dcd185d9e8fa5a15e36e65c" 317 | "checksum rls-span 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "33d66f1d6c6ccd5c98029f162544131698f6ebb61d8c697681cac409dcd08805" 318 | "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" 319 | "checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9" 320 | "checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" 321 | "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" 322 | "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" 323 | "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" 324 | "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" 325 | "checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" 326 | "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" 327 | "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 328 | "checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" 329 | "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 330 | "checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" 331 | -------------------------------------------------------------------------------- /src/lowering.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The RLS Project Developers. 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | //! For processing the raw save-analysis data from rustc into the rls 10 | //! in-memory representation. 11 | 12 | use analysis::{Def, Glob, PerCrateAnalysis, Ref}; 13 | use data; 14 | use raw::{self, RelationKind, CrateId, DefKind}; 15 | use {AResult, AnalysisHost, Id, Span, NULL}; 16 | use loader::AnalysisLoader; 17 | use util; 18 | 19 | use span; 20 | 21 | use std::collections::{HashSet, HashMap}; 22 | use std::collections::hash_map::Entry; 23 | use std::iter::Extend; 24 | use std::path::{Path, PathBuf}; 25 | use std::time::Instant; 26 | use std::u32; 27 | 28 | use fst; 29 | use itertools::Itertools; 30 | 31 | // f is a function used to record the lowered crate into analysis. 32 | pub fn lower( 33 | raw_analysis: Vec, 34 | base_dir: &Path, 35 | analysis: &AnalysisHost, 36 | mut f: F, 37 | ) -> AResult<()> 38 | where 39 | F: FnMut(&AnalysisHost, PerCrateAnalysis, CrateId) -> AResult<()>, 40 | L: AnalysisLoader, 41 | { 42 | let rss = util::get_resident().unwrap_or(0); 43 | let t_start = Instant::now(); 44 | 45 | // Keep a queue of crates that we are yet to overwrite as part of the lowering 46 | // process (to know which already-existing defs we can overwrite and lower) 47 | let mut invalidated_crates: Vec<_> = raw_analysis.iter().map(|c| c.id.clone()).collect(); 48 | 49 | for c in raw_analysis { 50 | let t_start = Instant::now(); 51 | 52 | let (per_crate, id) = CrateReader::read_crate(analysis, c, base_dir, &invalidated_crates); 53 | invalidated_crates.retain(|elem| *elem != id); 54 | 55 | let time = t_start.elapsed(); 56 | info!( 57 | "Lowering {} in {:.2}s", 58 | format!("{} ({:?})", id.name, id.disambiguator), 59 | time.as_secs() as f64 + time.subsec_nanos() as f64 / 1_000_000_000.0 60 | ); 61 | info!(" defs: {}", per_crate.defs.len()); 62 | info!(" refs: {}", per_crate.ref_spans.len()); 63 | info!(" globs: {}", per_crate.globs.len()); 64 | 65 | f(analysis, per_crate, id)?; 66 | } 67 | 68 | let time = t_start.elapsed(); 69 | let rss = util::get_resident().unwrap_or(0) as isize - rss as isize; 70 | info!( 71 | "Total lowering time: {:.2}s", 72 | time.as_secs() as f64 + time.subsec_nanos() as f64 / 1_000_000_000.0 73 | ); 74 | info!("Diff in rss: {:.2}KB", rss as f64 / 1000.0); 75 | 76 | Ok(()) 77 | } 78 | 79 | fn lower_span(raw_span: &raw::SpanData, base_dir: &Path, path_rewrite: &Option) -> Span { 80 | let file_name = &raw_span.file_name; 81 | 82 | // Go from relative to absolute paths. 83 | let file_name = if let &Some(ref prefix) = path_rewrite { 84 | // Invariant: !file_name.is_absolute() 85 | // We don't assert this because better to have an incorrect span than to 86 | // panic. 87 | let prefix = &Path::new(prefix); 88 | prefix.join(file_name) 89 | } else if file_name.is_absolute() { 90 | file_name.to_owned() 91 | } else { 92 | base_dir.join(file_name) 93 | }; 94 | 95 | // Rustc uses 1-indexed rows and columns, the RLS uses 0-indexed. 96 | span::Span::new( 97 | raw_span.line_start.zero_indexed(), 98 | raw_span.line_end.zero_indexed(), 99 | raw_span.column_start.zero_indexed(), 100 | raw_span.column_end.zero_indexed(), 101 | file_name, 102 | ) 103 | } 104 | 105 | /// Responsible for processing the raw `data::Analysis`, including translating 106 | /// from local crate ids to global crate ids, and creating lowered 107 | /// `PerCrateAnalysis`. 108 | struct CrateReader<'a> { 109 | /// This is effectively a map from local crate id -> global crate id, where 110 | /// local crate id are indices 0...external_crate_count. 111 | crate_map: Vec, 112 | base_dir: PathBuf, 113 | crate_name: String, 114 | path_rewrite: Option, 115 | crate_homonyms: Vec, 116 | /// List of crates that are invalidated (replaced) as part of the current 117 | /// lowering process. These will be overriden and their definitions should 118 | /// not be taken into account when checking if we need to ignore duplicated 119 | /// item. 120 | invalidated_crates: &'a [CrateId], 121 | } 122 | 123 | impl<'a> CrateReader<'a> { 124 | fn from_prelude( 125 | mut prelude: raw::CratePreludeData, 126 | master_crate_map: &mut HashMap, 127 | base_dir: &Path, 128 | path_rewrite: Option, 129 | invalidated_crates: &'a [CrateId], 130 | ) -> CrateReader<'a> { 131 | fn fetch_crate_index(map: &mut HashMap, 132 | id: CrateId) -> u32 { 133 | let next = map.len() as u32; 134 | *map.entry(id).or_insert(next) 135 | } 136 | // When reading a local crate and its external crates, we need to: 137 | // 1. Update a global crate id map if we encounter any new crate 138 | // 2. Prepare a local crate id -> global crate id map, so we can easily 139 | // map those when lowering symbols with local crate ids into global registry 140 | // It's worth noting, that we assume that local crate id is 0, whereas 141 | // the external crates will have num in 1..count contiguous range. 142 | let crate_id = prelude.crate_id; 143 | trace!("building crate map for {:?}", crate_id); 144 | let index = fetch_crate_index(master_crate_map, crate_id.clone()); 145 | let mut crate_map = vec![index]; 146 | trace!(" {} -> {}", crate_id.name, master_crate_map[&crate_id]); 147 | 148 | prelude.external_crates.sort_by(|a, b| a.num.cmp(&b.num)); 149 | for c in prelude.external_crates { 150 | assert!(c.num == crate_map.len() as u32); 151 | let index = fetch_crate_index(master_crate_map, c.id.clone()); 152 | crate_map.push(index); 153 | trace!(" {} -> {}", c.id.name, master_crate_map[&c.id]); 154 | } 155 | 156 | CrateReader { 157 | crate_map, 158 | base_dir: base_dir.to_owned(), 159 | crate_homonyms: master_crate_map.keys().filter(|cid| cid.name == crate_id.name).cloned().collect(), 160 | crate_name: crate_id.name, 161 | path_rewrite, 162 | invalidated_crates, 163 | } 164 | } 165 | 166 | /// Lowers a given `raw::Crate` into `AnalysisHost`. 167 | fn read_crate( 168 | project_analysis: &AnalysisHost, 169 | krate: raw::Crate, 170 | base_dir: &Path, 171 | invalidated_crates: &[CrateId], 172 | ) -> (PerCrateAnalysis, CrateId) { 173 | let reader = CrateReader::from_prelude( 174 | krate.analysis.prelude.unwrap(), 175 | &mut project_analysis.master_crate_map.lock().unwrap(), 176 | base_dir, 177 | krate.path_rewrite, 178 | invalidated_crates, 179 | ); 180 | 181 | let mut per_crate = PerCrateAnalysis::new(krate.timestamp, krate.path); 182 | 183 | let is_distro_crate = krate.analysis.config.distro_crate; 184 | reader.read_defs(krate.analysis.defs, &mut per_crate, is_distro_crate, project_analysis); 185 | reader.read_imports(krate.analysis.imports, &mut per_crate, project_analysis); 186 | reader.read_refs(krate.analysis.refs, &mut per_crate, project_analysis); 187 | reader.read_impls(krate.analysis.relations, &mut per_crate, project_analysis); 188 | per_crate.global_crate_num = reader.crate_map[0]; 189 | 190 | { 191 | let analysis = &mut project_analysis.analysis.lock().unwrap(); 192 | analysis.as_mut() 193 | .unwrap() 194 | .crate_names 195 | .entry(krate.id.name.clone()) 196 | .or_insert_with(|| vec![]) 197 | .push(krate.id.clone()); 198 | } 199 | 200 | (per_crate, krate.id) 201 | } 202 | 203 | fn read_imports( 204 | &self, 205 | imports: Vec, 206 | analysis: &mut PerCrateAnalysis, 207 | project_analysis: &AnalysisHost, 208 | ) { 209 | for i in imports { 210 | let span = lower_span(&i.span, &self.base_dir, &self.path_rewrite); 211 | if !i.value.is_empty() { 212 | // A glob import. 213 | if !self.has_congruent_glob(&span, project_analysis) { 214 | let glob = Glob { value: i.value }; 215 | trace!("record glob {:?} {:?}", span, glob); 216 | analysis.globs.insert(span, glob); 217 | } 218 | } else if let Some(ref ref_id) = i.ref_id { 219 | // Import where we know the referred def. 220 | let def_id = self.id_from_compiler_id(ref_id); 221 | self.record_ref(def_id, span, analysis, project_analysis); 222 | if let Some(alias_span) = i.alias_span { 223 | let alias_span = lower_span(&alias_span, &self.base_dir, &self.path_rewrite); 224 | self.record_ref(def_id, alias_span, analysis, project_analysis); 225 | let mut analysis = project_analysis.analysis.lock().unwrap(); 226 | analysis.as_mut().unwrap().aliased_imports.insert(def_id); 227 | } 228 | } 229 | } 230 | } 231 | 232 | fn record_ref( 233 | &self, 234 | def_id: Id, 235 | span: Span, 236 | analysis: &mut PerCrateAnalysis, 237 | project_analysis: &AnalysisHost, 238 | ) { 239 | if def_id != NULL && (project_analysis.has_def(def_id) || analysis.defs.contains_key(&def_id)) { 240 | trace!("record_ref {:?} {}", span, def_id); 241 | match analysis.def_id_for_span.entry(span.clone()) { 242 | Entry::Occupied(mut oe) => { 243 | let new = oe.get().add_id(def_id); 244 | oe.insert(new); 245 | } 246 | Entry::Vacant(ve) => { 247 | ve.insert(Ref::Id(def_id)); 248 | } 249 | } 250 | analysis 251 | .ref_spans 252 | .entry(def_id) 253 | .or_insert_with(|| vec![]) 254 | .push(span); 255 | } 256 | } 257 | 258 | // We are sometimes asked to analyze the same crate twice. This can happen due to duplicate data, 259 | // but more frequently is due to compiling it twice with different Cargo targets (e.g., bin and test). 260 | // In that case there will be two crates with the same names, but different disambiguators. We 261 | // want to ensure that we only record defs once, even if the defintion is in multiple crates. 262 | // So we compare the crate-local id and span and skip any subsequent defs which match already 263 | // present defs. 264 | fn has_congruent_def(&self, local_id: u32, span: &Span, project_analysis: &AnalysisHost) -> bool { 265 | self.has_congruent_item(project_analysis, |per_crate| per_crate.has_congruent_def(local_id, span)) 266 | } 267 | 268 | fn has_congruent_glob(&self, span: &Span, project_analysis: &AnalysisHost) -> bool { 269 | self.has_congruent_item(project_analysis, |per_crate| per_crate.globs.contains_key(span)) 270 | } 271 | 272 | fn has_congruent_item(&self, project_analysis: &AnalysisHost, pred: P) -> bool 273 | where 274 | L: AnalysisLoader, 275 | P: Fn(&PerCrateAnalysis) -> bool, 276 | { 277 | if self.crate_homonyms.is_empty() { 278 | return false; 279 | } 280 | 281 | let project_analysis = project_analysis.analysis.lock().unwrap(); 282 | let project_analysis = project_analysis.as_ref().unwrap(); 283 | 284 | // Don't take into account crates that we are about to replace as part 285 | // of the lowering. This often happens when we reload definitions for 286 | // the same crate. Naturally most of the definitions will stay the same 287 | // for incremental changes but will be overwritten - don't ignore them! 288 | let homonyms_to_consider = self 289 | .crate_homonyms 290 | .iter() 291 | .filter(|c| !self.invalidated_crates.contains(c)); 292 | 293 | homonyms_to_consider 294 | .filter_map(|ch| project_analysis.per_crate.get(ch)) 295 | .any(pred) 296 | } 297 | 298 | fn read_defs( 299 | &self, 300 | defs: Vec, 301 | analysis: &mut PerCrateAnalysis, 302 | distro_crate: bool, 303 | project_analysis: &AnalysisHost, 304 | ) { 305 | let mut defs_to_index = Vec::new(); 306 | for d in defs { 307 | if bad_span(&d.span, d.kind == DefKind::Mod) { 308 | continue; 309 | } 310 | let span = lower_span(&d.span, &self.base_dir, &self.path_rewrite); 311 | if self.has_congruent_def(d.id.index, &span, project_analysis) { 312 | trace!("read_defs: has_congruent_def({}, {:?}), skipping", d.id.index, span); 313 | continue; 314 | } 315 | 316 | let id = self.id_from_compiler_id(&d.id); 317 | if id != NULL && !analysis.defs.contains_key(&id) { 318 | let file_name = span.file.clone(); 319 | analysis 320 | .defs_per_file 321 | .entry(file_name) 322 | .or_insert_with(|| vec![]) 323 | .push(id); 324 | let decl_id = match d.decl_id { 325 | Some(ref decl_id) => { 326 | let def_id = self.id_from_compiler_id(decl_id); 327 | analysis 328 | .ref_spans 329 | .entry(def_id) 330 | .or_insert_with(|| vec![]) 331 | .push(span.clone()); 332 | Ref::Id(def_id) 333 | } 334 | None => Ref::Id(id), 335 | }; 336 | match analysis.def_id_for_span.entry(span.clone()) { 337 | Entry::Occupied(_) => { 338 | debug!("def already exists at span: {:?} {:?}", span, d); 339 | } 340 | Entry::Vacant(ve) => { 341 | ve.insert(decl_id); 342 | } 343 | } 344 | 345 | analysis 346 | .def_names 347 | .entry(d.name.clone()) 348 | .or_insert_with(|| vec![]) 349 | .push(id); 350 | 351 | // NOTE not every Def will have a name, e.g. test_data/hello/src/main is analyzed with an implicit module 352 | // that's fine, but no need to index in def_trie 353 | if d.name != "" { 354 | defs_to_index.push((d.name.to_lowercase(), id)); 355 | } 356 | 357 | let parent = d.parent.map(|id| self.id_from_compiler_id(&id)); 358 | if let Some(parent) = parent { 359 | let children = analysis 360 | .children 361 | .entry(parent) 362 | .or_insert_with(HashSet::new); 363 | children.insert(id); 364 | } 365 | if !d.children.is_empty() { 366 | let children_for_id = analysis.children.entry(id).or_insert_with(HashSet::new); 367 | children_for_id 368 | .extend(d.children.iter().map(|id| self.id_from_compiler_id(id))); 369 | } 370 | 371 | let def = Def { 372 | kind: d.kind, 373 | span: span, 374 | name: d.name, 375 | value: d.value, 376 | qualname: format!("{}{}", self.crate_name, d.qualname), 377 | distro_crate, 378 | parent: parent, 379 | docs: d.docs, 380 | // sig: d.sig.map(|ref s| self.lower_sig(s, &self.base_dir)), 381 | }; 382 | trace!( 383 | "record def: {:?}/{:?} ({}): {:?}", 384 | id, 385 | d.id, 386 | self.crate_map[d.id.krate as usize], 387 | def 388 | ); 389 | 390 | if d.kind == super::raw::DefKind::Mod && def.name == "" { 391 | assert!(analysis.root_id.is_none()); 392 | analysis.root_id = Some(id); 393 | } 394 | 395 | analysis.defs.insert(id, def); 396 | } 397 | } 398 | 399 | let (def_fst, def_fst_values) = build_index(defs_to_index); 400 | analysis.def_fst = def_fst; 401 | analysis.def_fst_values = def_fst_values; 402 | 403 | // We must now run a pass over the defs setting parents, because 404 | // save-analysis often omits parent info. 405 | for (parent, children) in &analysis.children { 406 | for c in children { 407 | analysis 408 | .defs 409 | .get_mut(c) 410 | .map(|def| def.parent = Some(*parent)); 411 | } 412 | } 413 | } 414 | 415 | fn read_refs( 416 | &self, 417 | refs: Vec, 418 | analysis: &mut PerCrateAnalysis, 419 | project_analysis: &AnalysisHost, 420 | ) { 421 | for r in refs { 422 | if r.span.file_name.to_str().map(|s| s.ends_with('>')).unwrap_or(true) { 423 | continue; 424 | } 425 | let def_id = self.id_from_compiler_id(&r.ref_id); 426 | let span = lower_span(&r.span, &self.base_dir, &self.path_rewrite); 427 | self.record_ref(def_id, span, analysis, project_analysis); 428 | } 429 | } 430 | 431 | fn read_impls( 432 | &self, 433 | relations: Vec, 434 | analysis: &mut PerCrateAnalysis, 435 | project_analysis: &AnalysisHost, 436 | ) { 437 | for r in relations { 438 | match r.kind { 439 | RelationKind::Impl { .. } => {} 440 | _ => continue, 441 | } 442 | let self_id = self.id_from_compiler_id(&r.from); 443 | let trait_id = self.id_from_compiler_id(&r.to); 444 | let span = lower_span(&r.span, &self.base_dir, &self.path_rewrite); 445 | if self_id != NULL { 446 | if let Some(self_id) = abs_ref_id(self_id, analysis, project_analysis) { 447 | trace!("record impl for self type {:?} {}", span, self_id); 448 | analysis 449 | .impls 450 | .entry(self_id) 451 | .or_insert_with(|| vec![]) 452 | .push(span.clone()); 453 | } 454 | } 455 | if trait_id != NULL { 456 | if let Some(trait_id) = abs_ref_id(trait_id, analysis, project_analysis) { 457 | trace!("record impl for trait {:?} {}", span, trait_id); 458 | analysis 459 | .impls 460 | .entry(trait_id) 461 | .or_insert_with(|| vec![]) 462 | .push(span); 463 | } 464 | } 465 | } 466 | } 467 | 468 | // fn lower_sig(&self, raw_sig: &raw::Signature, base_dir: &Path) -> Signature { 469 | // Signature { 470 | // span: lower_span(&raw_sig.span, base_dir, &self.path_rewrite), 471 | // text: raw_sig.text.clone(), 472 | // ident_start: raw_sig.ident_start as u32, 473 | // ident_end: raw_sig.ident_end as u32, 474 | // defs: raw_sig.defs.iter().map(|se| self.lower_sig_element(se)).collect(), 475 | // refs: raw_sig.refs.iter().map(|se| self.lower_sig_element(se)).collect(), 476 | // } 477 | // } 478 | 479 | // fn lower_sig_element(&self, raw_se: &raw::SigElement) -> SigElement { 480 | // SigElement { 481 | // id: self.id_from_compiler_id(&raw_se.id), 482 | // start: raw_se.start, 483 | // end: raw_se.end, 484 | // } 485 | // } 486 | 487 | /// Recreates resulting crate-local (`u32`, `u32`) id from compiler 488 | /// to a global `u64` `Id`, mapping from a local to global crate id. 489 | fn id_from_compiler_id(&self, id: &data::Id) -> Id { 490 | if id.krate == u32::MAX || id.index == u32::MAX { 491 | return NULL; 492 | } 493 | 494 | let krate = self.crate_map[id.krate as usize]; 495 | Id::from_crate_and_local(krate, id.index) 496 | } 497 | } 498 | 499 | fn abs_ref_id( 500 | id: Id, 501 | analysis: &PerCrateAnalysis, 502 | project_analysis: &AnalysisHost, 503 | ) -> Option { 504 | if project_analysis.has_def(id) || analysis.defs.contains_key(&id) { 505 | return Some(id); 506 | } 507 | 508 | // TODO 509 | None 510 | } 511 | 512 | fn build_index(mut defs: Vec<(String, Id)>) -> (fst::Map, Vec>) { 513 | defs.sort_by(|(n1, _), (n2, _)| n1.cmp(n2)); 514 | let by_name = defs.into_iter().group_by(|(n, _)| n.clone()); 515 | 516 | let mut values: Vec> = Vec::new(); 517 | let fst = { 518 | let defs = by_name.into_iter().enumerate().map(|(i, (name, defs))| { 519 | values.push(defs.map(|(_, id)| id).collect()); 520 | (name, i as u64) 521 | }); 522 | fst::Map::from_iter(defs).expect("defs are sorted by lowercase name") 523 | }; 524 | (fst, values) 525 | } 526 | 527 | fn bad_span(span: &raw::SpanData, is_mod: bool) -> bool { 528 | span.file_name.to_str().map(|s| s.ends_with('>')).unwrap_or(true) || 529 | (!is_mod && 530 | span.byte_start == 0 && 531 | span.byte_end == 0) 532 | } 533 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The RLS Project Developers. 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | #![feature(type_ascription)] 10 | #![feature(crate_visibility_modifier)] 11 | 12 | #[macro_use] 13 | extern crate derive_new; 14 | #[macro_use] 15 | extern crate log; 16 | extern crate rls_data as data; 17 | extern crate rls_span as span; 18 | extern crate rustc_serialize; 19 | extern crate fst; 20 | extern crate itertools; 21 | extern crate json; 22 | 23 | mod analysis; 24 | mod raw; 25 | mod loader; 26 | mod lowering; 27 | mod listings; 28 | mod util; 29 | mod symbol_query; 30 | #[cfg(test)] 31 | mod test; 32 | 33 | pub use analysis::{Def, Ref}; 34 | use analysis::Analysis; 35 | pub use raw::{name_space_for_def_kind, read_analysis_from_files, CrateId, DefKind}; 36 | pub use loader::{AnalysisLoader, CargoAnalysisLoader, SearchDirectory, Target}; 37 | pub use symbol_query::SymbolQuery; 38 | 39 | use std::collections::HashMap; 40 | use std::path::{Path, PathBuf}; 41 | use std::sync::Mutex; 42 | use std::time::{Instant, SystemTime}; 43 | use std::u64; 44 | 45 | #[derive(Debug)] 46 | pub struct AnalysisHost { 47 | analysis: Mutex>, 48 | master_crate_map: Mutex>, 49 | loader: Mutex, 50 | } 51 | 52 | pub type AResult = Result; 53 | 54 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] 55 | pub enum AError { 56 | MutexPoison, 57 | Unclassified, 58 | } 59 | 60 | #[derive(Debug, Clone)] 61 | pub struct SymbolResult { 62 | pub id: Id, 63 | pub name: String, 64 | pub kind: raw::DefKind, 65 | pub span: Span, 66 | pub parent: Option, 67 | } 68 | 69 | impl SymbolResult { 70 | fn new(id: Id, def: &Def) -> SymbolResult { 71 | SymbolResult { 72 | id, 73 | name: def.name.clone(), 74 | span: def.span.clone(), 75 | kind: def.kind, 76 | parent: def.parent, 77 | } 78 | } 79 | } 80 | 81 | pub type Span = span::Span; 82 | 83 | /// A common identifier for definitions, references etc. This is effectively a 84 | /// `DefId` with globally unique crate number (instead of a compiler generated 85 | /// crate-local number). 86 | #[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, new)] 87 | pub struct Id(u64); 88 | 89 | impl Id { 90 | fn from_crate_and_local(crate_id: u32, local_id: u32) -> Id { 91 | // Use global crate number for high order bits, 92 | // then index for least significant bits. 93 | Id(((crate_id as u64) << 32) | (local_id as u64)) 94 | } 95 | } 96 | 97 | /// Used to indicate a missing index in the Id. 98 | pub const NULL: Id = Id(u64::MAX); 99 | 100 | type Blacklist<'a> = &'a [&'static str]; 101 | 102 | macro_rules! clone_field { 103 | ($field: ident) => { |x| x.$field.clone() } 104 | } 105 | 106 | macro_rules! def_span { 107 | ($analysis: expr, $id: expr) => { 108 | $analysis.with_defs_and_then($id, |def| Some(def.span.clone())) 109 | } 110 | } 111 | 112 | impl AnalysisHost { 113 | pub fn new(target: Target) -> AnalysisHost { 114 | AnalysisHost { 115 | analysis: Mutex::new(None), 116 | master_crate_map: Mutex::new(HashMap::new()), 117 | loader: Mutex::new(CargoAnalysisLoader::new(target)), 118 | } 119 | } 120 | } 121 | 122 | impl AnalysisHost { 123 | pub fn new_with_loader(loader: L) -> Self { 124 | Self { 125 | analysis: Mutex::new(None), 126 | master_crate_map: Mutex::new(HashMap::new()), 127 | loader: Mutex::new(loader), 128 | } 129 | } 130 | 131 | /// Reloads given data passed in `analysis`. This will first check and read 132 | /// on-disk data (just like `reload`). It then imports the data we're 133 | /// passing in directly. 134 | pub fn reload_from_analysis( 135 | &self, 136 | analysis: Vec, 137 | path_prefix: &Path, 138 | base_dir: &Path, 139 | blacklist: Blacklist, 140 | ) -> AResult<()> { 141 | self.reload_with_blacklist(path_prefix, base_dir, blacklist)?; 142 | 143 | let crates: Vec<_> = analysis.into_iter() 144 | .map(|analysis| raw::Crate::new(analysis, SystemTime::now(), None, None)) 145 | .collect(); 146 | 147 | lowering::lower( 148 | crates, 149 | base_dir, 150 | self, 151 | |host, per_crate, id| { 152 | let mut a = host.analysis.lock()?; 153 | a.as_mut().unwrap().update(id, per_crate); 154 | Ok(()) 155 | }, 156 | ) 157 | } 158 | 159 | pub fn reload(&self, path_prefix: &Path, base_dir: &Path) -> AResult<()> { 160 | self.reload_with_blacklist(path_prefix, base_dir, &[]) 161 | } 162 | 163 | pub fn reload_with_blacklist( 164 | &self, 165 | path_prefix: &Path, 166 | base_dir: &Path, 167 | blacklist: Blacklist, 168 | ) -> AResult<()> { 169 | trace!( 170 | "reload_with_blacklist {:?} {:?} {:?}", 171 | path_prefix, 172 | base_dir, 173 | blacklist 174 | ); 175 | let empty = self.analysis.lock()?.is_none(); 176 | if empty || self.loader.lock()?.needs_hard_reload(path_prefix) { 177 | return self.hard_reload_with_blacklist(path_prefix, base_dir, blacklist); 178 | } 179 | 180 | let timestamps = self.analysis.lock()?.as_ref().unwrap().timestamps(); 181 | let raw_analysis = { 182 | let loader = self.loader.lock()?; 183 | read_analysis_from_files(&*loader, timestamps, blacklist) 184 | }; 185 | 186 | lowering::lower(raw_analysis, base_dir, self, |host, per_crate, id| { 187 | let mut a = host.analysis.lock()?; 188 | a.as_mut().unwrap().update(id, per_crate); 189 | Ok(()) 190 | }) 191 | } 192 | 193 | /// Reloads the entire project's analysis data. 194 | pub fn hard_reload(&self, path_prefix: &Path, base_dir: &Path) -> AResult<()> { 195 | self.hard_reload_with_blacklist(path_prefix, base_dir, &[]) 196 | } 197 | 198 | pub fn hard_reload_with_blacklist( 199 | &self, 200 | path_prefix: &Path, 201 | base_dir: &Path, 202 | blacklist: Blacklist, 203 | ) -> AResult<()> { 204 | trace!("hard_reload {:?} {:?}", path_prefix, base_dir); 205 | // We're going to create a dummy AnalysisHost that we will fill with data, 206 | // then once we're done, we'll swap its data into self. 207 | let mut fresh_host = self.loader.lock()?.fresh_host(); 208 | fresh_host.analysis = Mutex::new(Some(Analysis::new())); 209 | 210 | { 211 | let mut fresh_loader = fresh_host.loader.lock().unwrap(); 212 | fresh_loader.set_path_prefix(path_prefix); // TODO: Needed? 213 | 214 | let raw_analysis = read_analysis_from_files(&*fresh_loader, 215 | HashMap::new(), 216 | blacklist); 217 | lowering::lower(raw_analysis, base_dir, &fresh_host, |host, per_crate, id| { 218 | let mut a = host.analysis.lock()?; 219 | a.as_mut().unwrap().update(id, per_crate); 220 | Ok(()) 221 | })?; 222 | } 223 | 224 | // To guarantee a consistent state and no corruption in case an error 225 | // happens during reloading, we need to swap data with a dummy host in 226 | // a single atomic step. We can't lock and swap every member at a time, 227 | // as this can possibly lead to inconsistent state, but now this can possibly 228 | // deadlock, which isn't that good. Ideally we should have guaranteed 229 | // exclusive access to AnalysisHost as a whole to perform a reliable swap. 230 | macro_rules! swap_mutex_fields { 231 | ($($name:ident),*) => { 232 | // First, we need exclusive access to every field before swapping 233 | $(let mut $name = self.$name.lock()?;)* 234 | // Then, we can swap every field 235 | $(*$name = fresh_host.$name.into_inner().unwrap();)* 236 | }; 237 | } 238 | 239 | swap_mutex_fields!(analysis, master_crate_map, loader); 240 | 241 | Ok(()) 242 | } 243 | 244 | /// Note that `self.has_def()` =/> `self.goto_def().is_ok()`, since if the 245 | /// Def is in an api crate, there is no reasonable Span to jump to. 246 | pub fn has_def(&self, id: Id) -> bool { 247 | match self.analysis.lock() { 248 | Ok(a) => a.as_ref().unwrap().has_def(id), 249 | _ => false, 250 | } 251 | } 252 | 253 | pub fn get_def(&self, id: Id) -> AResult { 254 | self.with_analysis(|a| a.with_defs(id, |def| def.clone())) 255 | } 256 | 257 | pub fn goto_def(&self, span: &Span) -> AResult { 258 | self.with_analysis(|a| a.def_id_for_span(span).and_then(|id| def_span!(a, id))) 259 | } 260 | 261 | pub fn for_each_child_def(&self, id: Id, f: F) -> AResult> 262 | where 263 | F: FnMut(Id, &Def) -> T, 264 | { 265 | self.with_analysis(|a| a.for_each_child(id, f)) 266 | } 267 | 268 | pub fn def_parents(&self, id: Id) -> AResult> { 269 | self.with_analysis(|a| { 270 | let mut result = vec![]; 271 | let mut next = id; 272 | loop { 273 | match a.with_defs_and_then(next, |def| { 274 | def.parent 275 | .and_then(|p| a.with_defs(p, |def| (p, def.name.clone()))) 276 | }) { 277 | Some((id, name)) => { 278 | result.insert(0, (id, name)); 279 | next = id; 280 | } 281 | None => { 282 | return Some(result); 283 | } 284 | } 285 | } 286 | }) 287 | } 288 | 289 | /// Returns the name of each crate in the program and the id of the root 290 | /// module of that crate. 291 | pub fn def_roots(&self) -> AResult> { 292 | self.with_analysis(|a| { 293 | Some( 294 | a.per_crate 295 | .iter() 296 | .filter_map(|(crate_id, data)| { 297 | data.root_id.map(|id| (id, crate_id.name.clone())) 298 | }) 299 | .collect() 300 | ) 301 | }) 302 | } 303 | 304 | pub fn id(&self, span: &Span) -> AResult { 305 | self.with_analysis(|a| a.def_id_for_span(span)) 306 | } 307 | 308 | /// Like id, but will only return a value if it is in the same crate as span. 309 | pub fn crate_local_id(&self, span: &Span) -> AResult { 310 | self.with_analysis(|a| a.local_def_id_for_span(span)) 311 | } 312 | 313 | // `include_decl` means the declaration will be included as the first result. 314 | // `force_unique_spans` means that if any reference is a reference to multiple 315 | // defs, then we return an empty vector (in which case, even if include_decl 316 | // is true, the result will be empty). 317 | // Note that for large numbers of refs, if `force_unique_spans` is true, then 318 | // this function might take significantly longer to execute. 319 | pub fn find_all_refs(&self, span: &Span, include_decl: bool, force_unique_spans: bool) -> AResult> { 320 | let t_start = Instant::now(); 321 | let result = self.with_analysis(|a| { 322 | a.def_id_for_span(span).map(|id| { 323 | if force_unique_spans && a.aliased_imports.contains(&id) { 324 | return vec![]; 325 | } 326 | let decl = if include_decl { 327 | def_span!(a, id) 328 | } else { 329 | None 330 | }; 331 | let refs = a.with_ref_spans(id, |refs| { 332 | if force_unique_spans { 333 | for r in refs.iter() { 334 | match a.ref_for_span(r) { 335 | Some(Ref::Id(_)) => {}, 336 | _ => return None, 337 | } 338 | } 339 | } 340 | Some(refs.clone()) 341 | }); 342 | refs.map(|refs| { 343 | decl.into_iter() 344 | .chain(refs.into_iter()) 345 | .collect::>() 346 | }).unwrap_or_else(|| vec![]) 347 | }) 348 | }); 349 | 350 | let time = t_start.elapsed(); 351 | info!( 352 | "find_all_refs: {}s", 353 | time.as_secs() as f64 + time.subsec_nanos() as f64 / 1_000_000_000.0 354 | ); 355 | result 356 | } 357 | 358 | pub fn show_type(&self, span: &Span) -> AResult { 359 | self.with_analysis(|a| { 360 | a.def_id_for_span(span) 361 | .and_then(|id| a.with_defs(id, clone_field!(value))) 362 | .or_else(|| a.with_globs(span, clone_field!(value))) 363 | }) 364 | } 365 | 366 | pub fn docs(&self, span: &Span) -> AResult { 367 | self.with_analysis(|a| { 368 | a.def_id_for_span(span) 369 | .and_then(|id| a.with_defs(id, clone_field!(docs))) 370 | }) 371 | } 372 | 373 | /// Finds Defs with names that starting with (ignoring case) `stem` 374 | pub fn matching_defs(&self, stem: &str) -> AResult> { 375 | self.query_defs(SymbolQuery::prefix(stem)) 376 | } 377 | 378 | pub fn query_defs(&self, query: SymbolQuery) -> AResult> { 379 | let t_start = Instant::now(); 380 | let result = self.with_analysis(move |a| { 381 | let defs = a.query_defs(query); 382 | info!("query_defs {:?}", &defs); 383 | Some(defs) 384 | }); 385 | 386 | let time = t_start.elapsed(); 387 | info!( 388 | "query_defs: {}", 389 | time.as_secs() as f64 + time.subsec_nanos() as f64 / 1_000_000_000.0 390 | ); 391 | 392 | result 393 | } 394 | 395 | /// Search for a symbol name, returns a list of spans matching defs and refs 396 | /// for that name. 397 | pub fn search(&self, name: &str) -> AResult> { 398 | let t_start = Instant::now(); 399 | let result = self.with_analysis(|a| { 400 | Some(a.with_def_names(name, |defs| { 401 | info!("defs: {:?}", defs); 402 | defs.into_iter() 403 | .flat_map(|id| { 404 | a.with_ref_spans(*id, |refs| { 405 | Some(def_span!(a, *id) 406 | .into_iter() 407 | .chain(refs.iter().cloned()) 408 | .collect::>()) 409 | }).or_else(|| def_span!(a, *id).map(|s| vec![s])) 410 | .unwrap_or_else(Vec::new) 411 | .into_iter() 412 | }) 413 | .collect(): Vec 414 | })) 415 | }); 416 | 417 | let time = t_start.elapsed(); 418 | info!( 419 | "search: {}s", 420 | time.as_secs() as f64 + time.subsec_nanos() as f64 / 1_000_000_000.0 421 | ); 422 | result 423 | } 424 | 425 | // TODO refactor search and find_all_refs to use this 426 | // Includes all references and the def, the def is always first. 427 | pub fn find_all_refs_by_id(&self, id: Id) -> AResult> { 428 | let t_start = Instant::now(); 429 | let result = self.with_analysis(|a| { 430 | a.with_ref_spans(id, |refs| { 431 | Some(def_span!(a, id) 432 | .into_iter() 433 | .chain(refs.iter().cloned()) 434 | .collect::>()) 435 | }).or_else(|| def_span!(a, id).map(|s| vec![s])) 436 | }); 437 | 438 | let time = t_start.elapsed(); 439 | info!( 440 | "find_all_refs_by_id: {}s", 441 | time.as_secs() as f64 + time.subsec_nanos() as f64 / 1_000_000_000.0 442 | ); 443 | result 444 | } 445 | 446 | pub fn find_impls(&self, id: Id) -> AResult> { 447 | self.with_analysis(|a| { 448 | Some(a.for_all_crates(|c| c.impls.get(&id).cloned())) 449 | }) 450 | } 451 | 452 | /// Search for a symbol name, returning a list of def_ids for that name. 453 | pub fn search_for_id(&self, name: &str) -> AResult> { 454 | self.with_analysis(|a| Some(a.with_def_names(name, |defs| defs.clone()))) 455 | } 456 | 457 | pub fn symbols(&self, file_name: &Path) -> AResult> { 458 | self.with_analysis(|a| { 459 | a.with_defs_per_file(file_name, |ids| { 460 | ids.iter() 461 | .map(|id| { 462 | a.with_defs(*id, |def| SymbolResult::new(*id, def)).unwrap() 463 | }) 464 | .collect() 465 | }) 466 | }) 467 | } 468 | 469 | pub fn doc_url(&self, span: &Span) -> AResult { 470 | // e.g., https://doc.rust-lang.org/nightly/std/string/String.t.html 471 | self.with_analysis(|a| { 472 | a.def_id_for_span(span).and_then(|id| { 473 | a.with_defs_and_then(id, |def| AnalysisHost::::mk_doc_url(def, a)) 474 | }) 475 | }) 476 | } 477 | 478 | // e.g., https://github.com/rust-lang/rust/blob/master/src/liballoc/string.rs#L261-L263 479 | pub fn src_url(&self, span: &Span) -> AResult { 480 | // FIXME would be nice not to do this every time. 481 | let path_prefix = self.loader.lock().unwrap().abs_path_prefix(); 482 | 483 | self.with_analysis(|a| { 484 | a.def_id_for_span(span).and_then(|id| { 485 | a.with_defs_and_then(id, |def| { 486 | AnalysisHost::::mk_src_url(def, path_prefix.as_ref(), a) 487 | }) 488 | }) 489 | }) 490 | } 491 | 492 | fn with_analysis(&self, f: F) -> AResult 493 | where 494 | F: FnOnce(&Analysis) -> Option, 495 | { 496 | let a = self.analysis.lock()?; 497 | if let Some(ref a) = *a { 498 | f(a).ok_or(AError::Unclassified) 499 | } else { 500 | Err(AError::Unclassified) 501 | } 502 | } 503 | 504 | fn mk_doc_url(def: &Def, analysis: &Analysis) -> Option { 505 | if !def.distro_crate { 506 | return None; 507 | } 508 | 509 | if def.parent.is_none() && def.qualname.contains('<') { 510 | debug!( 511 | "mk_doc_url, bailing, found generic qualname: `{}`", 512 | def.qualname 513 | ); 514 | return None; 515 | } 516 | 517 | match def.parent { 518 | Some(p) => { 519 | analysis.with_defs(p, |parent| match def.kind { 520 | DefKind::Field | DefKind::Method | DefKind::Tuple | 521 | DefKind::TupleVariant | DefKind::StructVariant => { 522 | let ns = name_space_for_def_kind(def.kind); 523 | let mut res = AnalysisHost::::mk_doc_url(parent, analysis) 524 | .unwrap_or_else(|| "".into()); 525 | res.push_str(&format!("#{}.{}", def.name, ns)); 526 | res 527 | } 528 | DefKind::Mod => { 529 | let parent_qualpath = parent.qualname.replace("::", "/"); 530 | format!( 531 | "{}/{}/{}/", 532 | analysis.doc_url_base, 533 | parent_qualpath.trim_end_matches('/'), 534 | def.name, 535 | ) 536 | } 537 | _ => { 538 | let parent_qualpath = parent.qualname.replace("::", "/"); 539 | let ns = name_space_for_def_kind(def.kind); 540 | format!( 541 | "{}/{}/{}.{}.html", 542 | analysis.doc_url_base, 543 | parent_qualpath, 544 | def.name, 545 | ns, 546 | ) 547 | } 548 | }) 549 | } 550 | None => { 551 | let qualpath = def.qualname.replace("::", "/"); 552 | let ns = name_space_for_def_kind(def.kind); 553 | Some(format!( 554 | "{}/{}.{}.html", 555 | analysis.doc_url_base, 556 | qualpath, 557 | ns, 558 | )) 559 | } 560 | } 561 | } 562 | 563 | fn mk_src_url(def: &Def, path_prefix: Option<&PathBuf>, analysis: &Analysis) -> Option { 564 | if !def.distro_crate { 565 | return None; 566 | } 567 | 568 | let file_path = &def.span.file; 569 | let file_path = file_path.strip_prefix(path_prefix?).ok()?; 570 | 571 | Some(format!( 572 | "{}/{}#L{}-L{}", 573 | analysis.src_url_base, 574 | file_path.to_str().unwrap(), 575 | def.span.range.row_start.one_indexed().0, 576 | def.span.range.row_end.one_indexed().0 577 | )) 578 | } 579 | } 580 | 581 | impl ::std::fmt::Display for Id { 582 | fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { 583 | self.0.fmt(f) 584 | } 585 | } 586 | 587 | impl ::std::error::Error for AError { 588 | fn description(&self) -> &str { 589 | match *self { 590 | AError::MutexPoison => "poison error in a mutex (usually a secondary error)", 591 | AError::Unclassified => "unknown error", 592 | } 593 | } 594 | } 595 | 596 | impl ::std::fmt::Display for AError { 597 | fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { 598 | write!(f, "{}", ::std::error::Error::description(self)) 599 | } 600 | } 601 | 602 | impl From<::std::sync::PoisonError> for AError { 603 | fn from(_: ::std::sync::PoisonError) -> AError { 604 | AError::MutexPoison 605 | } 606 | } 607 | -------------------------------------------------------------------------------- /test_data/rust-analysis/libpanic_unwind-4da7cb5dd1fef0c2.json: -------------------------------------------------------------------------------- 1 | {"config":{"output_file":null,"full_docs":false,"pub_only":true,"reachable_only":false,"distro_crate":true,"signatures":false,"borrow_data":false},"prelude":{"crate_id":{"name":"panic_unwind","disambiguator":[1643721027292504100,10916951709470146856]},"crate_root":"libpanic_unwind","external_crates":[{"file_name":"/Users/travis/build/rust-lang/rust/src/libpanic_unwind/lib.rs","num":1,"id":{"name":"compiler_builtins","disambiguator":[12047234932576597458,5077187143126647032]}},{"file_name":"/Users/travis/build/rust-lang/rust/src/libpanic_unwind/lib.rs","num":2,"id":{"name":"core","disambiguator":[12641647969103297473,10130382509811922120]}},{"file_name":"/Users/travis/build/rust-lang/rust/src/libpanic_unwind/lib.rs","num":3,"id":{"name":"alloc","disambiguator":[7492281898511940165,14124905697399198535]}},{"file_name":"/Users/travis/build/rust-lang/rust/src/libpanic_unwind/lib.rs","num":4,"id":{"name":"libc","disambiguator":[10677312091366318875,12914270607935649197]}},{"file_name":"/Users/travis/build/rust-lang/rust/src/libpanic_unwind/lib.rs","num":5,"id":{"name":"unwind","disambiguator":[13357724146610223715,10513570149384825499]}}],"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,108,105,98,46,114,115],"byte_start":467,"byte_end":4052,"line_start":11,"line_end":120,"column_start":1,"column_end":2}},"imports":[],"defs":[{"kind":"Mod","id":{"krate":0,"index":0},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,108,105,98,46,114,115],"byte_start":467,"byte_end":4052,"line_start":11,"line_end":120,"column_start":1,"column_end":2},"name":"","qualname":"::","value":"libpanic_unwind/lib.rs","parent":null,"children":[{"krate":0,"index":2},{"krate":0,"index":4},{"krate":0,"index":6},{"krate":0,"index":8},{"krate":0,"index":10},{"krate":0,"index":12},{"krate":0,"index":14},{"krate":0,"index":16},{"krate":0,"index":18},{"krate":0,"index":20},{"krate":0,"index":62},{"krate":0,"index":130},{"krate":0,"index":132}],"decl_id":null,"docs":" Implementation of panics via stack unwinding","sig":null,"attributes":[{"value":"no_std","span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,108,105,98,46,114,115],"byte_start":1077,"byte_end":1087,"line_start":25,"line_end":25,"column_start":1,"column_end":11}},{"value":"unstable(feature = \"panic_unwind\", issue = \"32837\")","span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,108,105,98,46,114,115],"byte_start":1088,"byte_end":1143,"line_start":26,"line_end":26,"column_start":1,"column_end":56}},{"value":"feature(alloc)","span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,108,105,98,46,114,115],"byte_start":1438,"byte_end":1456,"line_start":32,"line_end":32,"column_start":1,"column_end":19}},{"value":"feature(core_intrinsics)","span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,108,105,98,46,114,115],"byte_start":1457,"byte_end":1485,"line_start":33,"line_end":33,"column_start":1,"column_end":29}},{"value":"feature(lang_items)","span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,108,105,98,46,114,115],"byte_start":1486,"byte_end":1509,"line_start":34,"line_end":34,"column_start":1,"column_end":24}},{"value":"feature(libc)","span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,108,105,98,46,114,115],"byte_start":1510,"byte_end":1527,"line_start":35,"line_end":35,"column_start":1,"column_end":18}},{"value":"feature(panic_unwind)","span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,108,105,98,46,114,115],"byte_start":1528,"byte_end":1553,"line_start":36,"line_end":36,"column_start":1,"column_end":26}},{"value":"feature(raw)","span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,108,105,98,46,114,115],"byte_start":1554,"byte_end":1570,"line_start":37,"line_end":37,"column_start":1,"column_end":17}},{"value":"feature(staged_api)","span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,108,105,98,46,114,115],"byte_start":1571,"byte_end":1594,"line_start":38,"line_end":38,"column_start":1,"column_end":24}},{"value":"feature(unwind_attributes)","span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,108,105,98,46,114,115],"byte_start":1595,"byte_end":1625,"line_start":39,"line_end":39,"column_start":1,"column_end":31}},{"value":"panic_runtime","span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,108,105,98,46,114,115],"byte_start":1675,"byte_end":1692,"line_start":42,"line_end":42,"column_start":1,"column_end":18}},{"value":"feature(panic_runtime)","span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,108,105,98,46,114,115],"byte_start":1693,"byte_end":1719,"line_start":43,"line_end":43,"column_start":1,"column_end":27}}]},{"kind":"Function","id":{"krate":0,"index":46},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,103,99,99,46,114,115],"byte_start":7082,"byte_end":7087,"line_start":73,"line_end":73,"column_start":15,"column_end":20},"name":"panic","qualname":"::imp::panic","value":"fn (data: Box) -> u32","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Function","id":{"krate":0,"index":50},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,103,99,99,46,114,115],"byte_start":7808,"byte_end":7815,"line_start":93,"line_end":93,"column_start":8,"column_end":15},"name":"payload","qualname":"::imp::payload","value":"fn () -> *mut u8","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Function","id":{"krate":0,"index":52},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,103,99,99,46,114,115],"byte_start":7868,"byte_end":7875,"line_start":97,"line_end":97,"column_start":15,"column_end":22},"name":"cleanup","qualname":"::imp::cleanup","value":"fn (ptr: *mut u8) -> Box","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Mod","id":{"krate":0,"index":64},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,101,104,46,114,115],"byte_start":0,"byte_end":0,"line_start":1,"line_end":1,"column_start":1,"column_end":1},"name":"eh","qualname":"::dwarf::eh","value":"libpanic_unwind/dwarf/eh.rs","parent":null,"children":[{"krate":0,"index":66},{"krate":0,"index":68},{"krate":0,"index":70},{"krate":0,"index":72},{"krate":0,"index":74},{"krate":0,"index":76},{"krate":0,"index":78},{"krate":0,"index":80},{"krate":0,"index":82},{"krate":0,"index":84},{"krate":0,"index":86},{"krate":0,"index":88},{"krate":0,"index":90},{"krate":0,"index":92},{"krate":0,"index":94},{"krate":0,"index":96},{"krate":0,"index":98},{"krate":0,"index":100},{"krate":0,"index":134},{"krate":0,"index":140},{"krate":0,"index":136},{"krate":0,"index":102},{"krate":0,"index":104},{"krate":0,"index":106},{"krate":0,"index":108},{"krate":0,"index":110},{"krate":0,"index":112}],"decl_id":null,"docs":" Parsing of GCC-style Language-Specific Data Area (LSDA)\n For details see:\n http://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-PDA/LSB-PDA/ehframechpt.html\n http://mentorembedded.github.io/cxx-abi/exceptions.pdf\n http://www.airs.com/blog/archives/460\n http://www.airs.com/blog/archives/464","sig":null,"attributes":[{"value":"allow(non_upper_case_globals)","span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,101,104,46,114,115],"byte_start":22095,"byte_end":22128,"line_start":21,"line_end":21,"column_start":1,"column_end":34}},{"value":"allow(unused)","span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,101,104,46,114,115],"byte_start":22129,"byte_end":22146,"line_start":22,"line_end":22,"column_start":1,"column_end":18}}]},{"kind":"Const","id":{"krate":0,"index":70},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,101,104,46,114,115],"byte_start":22198,"byte_end":22211,"line_start":27,"line_end":27,"column_start":11,"column_end":24},"name":"DW_EH_PE_omit","qualname":"::dwarf::eh::DW_EH_PE_omit","value":"u8","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Const","id":{"krate":0,"index":72},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,101,104,46,114,115],"byte_start":22234,"byte_end":22249,"line_start":28,"line_end":28,"column_start":11,"column_end":26},"name":"DW_EH_PE_absptr","qualname":"::dwarf::eh::DW_EH_PE_absptr","value":"u8","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Const","id":{"krate":0,"index":74},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,101,104,46,114,115],"byte_start":22273,"byte_end":22289,"line_start":30,"line_end":30,"column_start":11,"column_end":27},"name":"DW_EH_PE_uleb128","qualname":"::dwarf::eh::DW_EH_PE_uleb128","value":"u8","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Const","id":{"krate":0,"index":76},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,101,104,46,114,115],"byte_start":22312,"byte_end":22327,"line_start":31,"line_end":31,"column_start":11,"column_end":26},"name":"DW_EH_PE_udata2","qualname":"::dwarf::eh::DW_EH_PE_udata2","value":"u8","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Const","id":{"krate":0,"index":78},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,101,104,46,114,115],"byte_start":22350,"byte_end":22365,"line_start":32,"line_end":32,"column_start":11,"column_end":26},"name":"DW_EH_PE_udata4","qualname":"::dwarf::eh::DW_EH_PE_udata4","value":"u8","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Const","id":{"krate":0,"index":80},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,101,104,46,114,115],"byte_start":22388,"byte_end":22403,"line_start":33,"line_end":33,"column_start":11,"column_end":26},"name":"DW_EH_PE_udata8","qualname":"::dwarf::eh::DW_EH_PE_udata8","value":"u8","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Const","id":{"krate":0,"index":82},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,101,104,46,114,115],"byte_start":22426,"byte_end":22442,"line_start":34,"line_end":34,"column_start":11,"column_end":27},"name":"DW_EH_PE_sleb128","qualname":"::dwarf::eh::DW_EH_PE_sleb128","value":"u8","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Const","id":{"krate":0,"index":84},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,101,104,46,114,115],"byte_start":22465,"byte_end":22480,"line_start":35,"line_end":35,"column_start":11,"column_end":26},"name":"DW_EH_PE_sdata2","qualname":"::dwarf::eh::DW_EH_PE_sdata2","value":"u8","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Const","id":{"krate":0,"index":86},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,101,104,46,114,115],"byte_start":22503,"byte_end":22518,"line_start":36,"line_end":36,"column_start":11,"column_end":26},"name":"DW_EH_PE_sdata4","qualname":"::dwarf::eh::DW_EH_PE_sdata4","value":"u8","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Const","id":{"krate":0,"index":88},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,101,104,46,114,115],"byte_start":22541,"byte_end":22556,"line_start":37,"line_end":37,"column_start":11,"column_end":26},"name":"DW_EH_PE_sdata8","qualname":"::dwarf::eh::DW_EH_PE_sdata8","value":"u8","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Const","id":{"krate":0,"index":90},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,101,104,46,114,115],"byte_start":22580,"byte_end":22594,"line_start":39,"line_end":39,"column_start":11,"column_end":25},"name":"DW_EH_PE_pcrel","qualname":"::dwarf::eh::DW_EH_PE_pcrel","value":"u8","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Const","id":{"krate":0,"index":92},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,101,104,46,114,115],"byte_start":22617,"byte_end":22633,"line_start":40,"line_end":40,"column_start":11,"column_end":27},"name":"DW_EH_PE_textrel","qualname":"::dwarf::eh::DW_EH_PE_textrel","value":"u8","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Const","id":{"krate":0,"index":94},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,101,104,46,114,115],"byte_start":22656,"byte_end":22672,"line_start":41,"line_end":41,"column_start":11,"column_end":27},"name":"DW_EH_PE_datarel","qualname":"::dwarf::eh::DW_EH_PE_datarel","value":"u8","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Const","id":{"krate":0,"index":96},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,101,104,46,114,115],"byte_start":22695,"byte_end":22711,"line_start":42,"line_end":42,"column_start":11,"column_end":27},"name":"DW_EH_PE_funcrel","qualname":"::dwarf::eh::DW_EH_PE_funcrel","value":"u8","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Const","id":{"krate":0,"index":98},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,101,104,46,114,115],"byte_start":22734,"byte_end":22750,"line_start":43,"line_end":43,"column_start":11,"column_end":27},"name":"DW_EH_PE_aligned","qualname":"::dwarf::eh::DW_EH_PE_aligned","value":"u8","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Const","id":{"krate":0,"index":100},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,101,104,46,114,115],"byte_start":22774,"byte_end":22791,"line_start":45,"line_end":45,"column_start":11,"column_end":28},"name":"DW_EH_PE_indirect","qualname":"::dwarf::eh::DW_EH_PE_indirect","value":"u8","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Struct","id":{"krate":0,"index":134},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,101,104,46,114,115],"byte_start":22839,"byte_end":22848,"line_start":48,"line_end":48,"column_start":12,"column_end":21},"name":"EHContext","qualname":"::dwarf::eh::EHContext","value":"EHContext { ip, func_start, get_text_start, get_data_start }","parent":null,"children":[{"krate":0,"index":51},{"krate":0,"index":53},{"krate":0,"index":55},{"krate":0,"index":57}],"decl_id":null,"docs":"","sig":null,"attributes":[{"value":"rustc_copy_clone_marker","span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,101,104,46,114,115],"byte_start":22828,"byte_end":23124,"line_start":48,"line_end":53,"column_start":1,"column_end":2}}]},{"kind":"Field","id":{"krate":0,"index":51},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,101,104,46,114,115],"byte_start":22863,"byte_end":22865,"line_start":49,"line_end":49,"column_start":9,"column_end":11},"name":"ip","qualname":"::dwarf::eh::EHContext::ip","value":"usize","parent":{"krate":0,"index":134},"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Field","id":{"krate":0,"index":53},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,101,104,46,114,115],"byte_start":22913,"byte_end":22923,"line_start":50,"line_end":50,"column_start":9,"column_end":19},"name":"func_start","qualname":"::dwarf::eh::EHContext::func_start","value":"usize","parent":{"krate":0,"index":134},"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Field","id":{"krate":0,"index":55},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,101,104,46,114,115],"byte_start":22975,"byte_end":22989,"line_start":51,"line_end":51,"column_start":9,"column_end":23},"name":"get_text_start","qualname":"::dwarf::eh::EHContext::get_text_start","value":"&'a core::ops::Fn() -> usize + 'a","parent":{"krate":0,"index":134},"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Field","id":{"krate":0,"index":57},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,101,104,46,114,115],"byte_start":23053,"byte_end":23067,"line_start":52,"line_end":52,"column_start":9,"column_end":23},"name":"get_data_start","qualname":"::dwarf::eh::EHContext::get_data_start","value":"&'a core::ops::Fn() -> usize + 'a","parent":{"krate":0,"index":134},"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"TupleVariant","id":{"krate":0,"index":29},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,101,104,46,114,115],"byte_start":23150,"byte_end":23154,"line_start":56,"line_end":56,"column_start":5,"column_end":9},"name":"None","qualname":"::dwarf::eh::EHAction::None","value":"EHAction::None","parent":{"krate":0,"index":102},"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"TupleVariant","id":{"krate":0,"index":31},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,101,104,46,114,115],"byte_start":23160,"byte_end":23167,"line_start":57,"line_end":57,"column_start":5,"column_end":12},"name":"Cleanup","qualname":"::dwarf::eh::EHAction::Cleanup","value":"EHAction::Cleanup(usize)","parent":{"krate":0,"index":102},"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"TupleVariant","id":{"krate":0,"index":35},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,101,104,46,114,115],"byte_start":23180,"byte_end":23185,"line_start":58,"line_end":58,"column_start":5,"column_end":10},"name":"Catch","qualname":"::dwarf::eh::EHAction::Catch","value":"EHAction::Catch(usize)","parent":{"krate":0,"index":102},"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"TupleVariant","id":{"krate":0,"index":39},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,101,104,46,114,115],"byte_start":23198,"byte_end":23207,"line_start":59,"line_end":59,"column_start":5,"column_end":14},"name":"Terminate","qualname":"::dwarf::eh::EHAction::Terminate","value":"EHAction::Terminate","parent":{"krate":0,"index":102},"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Enum","id":{"krate":0,"index":102},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,101,104,46,114,115],"byte_start":23135,"byte_end":23143,"line_start":55,"line_end":55,"column_start":10,"column_end":18},"name":"EHAction","qualname":"::dwarf::eh::EHAction","value":"EHAction::{None, Cleanup, Catch, Terminate}","parent":null,"children":[{"krate":0,"index":29},{"krate":0,"index":31},{"krate":0,"index":35},{"krate":0,"index":39}],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Const","id":{"krate":0,"index":104},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,101,104,46,114,115],"byte_start":23222,"byte_end":23243,"line_start":62,"line_end":62,"column_start":11,"column_end":32},"name":"USING_SJLJ_EXCEPTIONS","qualname":"::dwarf::eh::USING_SJLJ_EXCEPTIONS","value":"bool","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Function","id":{"krate":0,"index":106},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,101,104,46,114,115],"byte_start":23318,"byte_end":23332,"line_start":64,"line_end":64,"column_start":15,"column_end":29},"name":"find_eh_action","qualname":"::dwarf::eh::find_eh_action","value":"fn (lsda: *const u8, context: &EHContext) -> Result","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Struct","id":{"krate":0,"index":116},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,109,111,100,46,114,115],"byte_start":18938,"byte_end":18949,"line_start":23,"line_end":23,"column_start":12,"column_end":23},"name":"DwarfReader","qualname":"::dwarf::DwarfReader","value":"DwarfReader { ptr }","parent":null,"children":[{"krate":0,"index":41}],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Field","id":{"krate":0,"index":41},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,109,111,100,46,114,115],"byte_start":18960,"byte_end":18963,"line_start":24,"line_end":24,"column_start":9,"column_end":12},"name":"ptr","qualname":"::dwarf::DwarfReader::ptr","value":"*const u8","parent":{"krate":0,"index":116},"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Method","id":{"krate":0,"index":122},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,109,111,100,46,114,115],"byte_start":19052,"byte_end":19055,"line_start":31,"line_end":31,"column_start":12,"column_end":15},"name":"new","qualname":"::new","value":"fn (ptr: *const u8) -> DwarfReader","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Method","id":{"krate":0,"index":124},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,109,111,100,46,114,115],"byte_start":19447,"byte_end":19451,"line_start":39,"line_end":39,"column_start":19,"column_end":23},"name":"read","qualname":"::read","value":"fn (&mut self) -> T","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Method","id":{"krate":0,"index":126},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,109,111,100,46,114,115],"byte_start":19750,"byte_end":19762,"line_start":47,"line_end":47,"column_start":19,"column_end":31},"name":"read_uleb128","qualname":"::read_uleb128","value":"fn (&mut self) -> u64","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Method","id":{"krate":0,"index":128},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,109,111,100,46,114,115],"byte_start":20129,"byte_end":20141,"line_start":62,"line_end":62,"column_start":19,"column_end":31},"name":"read_sleb128","qualname":"::read_sleb128","value":"fn (&mut self) -> i64","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[]},{"kind":"Function","id":{"krate":0,"index":130},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,108,105,98,46,114,115],"byte_start":3089,"byte_end":3113,"line_start":95,"line_end":95,"column_start":26,"column_end":50},"name":"__rust_maybe_catch_panic","qualname":"::__rust_maybe_catch_panic","value":"fn (f: fn(*mut u8), data: *mut u8, data_ptr: *mut usize, vtable_ptr: *mut usize) -> u32","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[{"value":"no_mangle","span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,108,105,98,46,114,115],"byte_start":3051,"byte_end":3063,"line_start":94,"line_end":94,"column_start":1,"column_end":13}}]},{"kind":"Function","id":{"krate":0,"index":132},"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,108,105,98,46,114,115],"byte_start":3872,"byte_end":3890,"line_start":115,"line_end":115,"column_start":26,"column_end":44},"name":"__rust_start_panic","qualname":"::__rust_start_panic","value":"fn (data: usize, vtable: usize) -> u32","parent":null,"children":[],"decl_id":null,"docs":"","sig":null,"attributes":[{"value":"no_mangle","span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,108,105,98,46,114,115],"byte_start":3815,"byte_end":3827,"line_start":113,"line_end":113,"column_start":1,"column_end":13}},{"value":"unwind(allowed)","span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,108,105,98,46,114,115],"byte_start":3828,"byte_end":3846,"line_start":114,"line_end":114,"column_start":1,"column_end":19}}]}],"impls":[{"id":0,"kind":"Inherent","span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,109,111,100,46,114,115],"byte_start":19027,"byte_end":19038,"line_start":30,"line_end":30,"column_start":6,"column_end":17},"value":"","parent":null,"children":[{"krate":0,"index":122},{"krate":0,"index":124},{"krate":0,"index":126},{"krate":0,"index":128}],"docs":"","sig":null,"attributes":[]}],"refs":[{"kind":"Mod","span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,109,111,100,46,114,115],"byte_start":18906,"byte_end":18908,"line_start":19,"line_end":19,"column_start":9,"column_end":11},"ref_id":{"krate":0,"index":64}}],"macro_refs":[],"relations":[{"span":{"file_name":[108,105,98,112,97,110,105,99,95,117,110,119,105,110,100,47,100,119,97,114,102,47,109,111,100,46,114,115],"byte_start":19027,"byte_end":19038,"line_start":30,"line_end":30,"column_start":6,"column_end":17},"kind":{"variant":"Impl","fields":[0]},"from":{"krate":0,"index":116},"to":{"krate":4294967295,"index":4294967295}}]} --------------------------------------------------------------------------------