]> git.lizzy.rs Git - rust.git/commitdiff
Merge #521
authorbors[bot] <bors[bot]@users.noreply.github.com>
Sun, 13 Jan 2019 12:04:33 +0000 (12:04 +0000)
committerbors[bot] <bors[bot]@users.noreply.github.com>
Sun, 13 Jan 2019 12:04:33 +0000 (12:04 +0000)
521: refresh docs r=matklad a=matklad

Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
12 files changed:
crates/ra_db/src/input.rs
crates/ra_hir/src/nameres/tests.rs
crates/ra_ide_api/src/goto_definition.rs
crates/ra_ide_api/src/hover.rs
crates/ra_ide_api/src/runnables.rs
crates/ra_lsp_server/src/cargo_target_spec.rs
crates/ra_lsp_server/src/main_loop/handlers.rs
crates/ra_lsp_server/src/server_world.rs
editors/code/src/commands/apply_source_change.ts
editors/code/src/commands/on_enter.ts
editors/code/src/commands/runnables.ts
editors/code/src/extension.ts

index 023183e2902980c54c50038c50d493b5c97a63c8..2b761ea0c447ca1e0891ee5d54ddce7a81e1975c 100644 (file)
@@ -53,6 +53,9 @@ pub struct CrateGraph {
     arena: FxHashMap<CrateId, CrateData>,
 }
 
+#[derive(Debug)]
+pub struct CyclicDependencies;
+
 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
 pub struct CrateId(pub u32);
 
@@ -94,12 +97,16 @@ pub fn add_crate_root(&mut self, file_id: FileId) -> CrateId {
         assert!(prev.is_none());
         crate_id
     }
-    pub fn add_dep(&mut self, from: CrateId, name: SmolStr, to: CrateId) {
-        let mut visited = FxHashSet::default();
-        if self.dfs_find(from, to, &mut visited) {
-            panic!("Cycle dependencies found.")
+    pub fn add_dep(
+        &mut self,
+        from: CrateId,
+        name: SmolStr,
+        to: CrateId,
+    ) -> Result<(), CyclicDependencies> {
+        if self.dfs_find(from, to, &mut FxHashSet::default()) {
+            return Err(CyclicDependencies);
         }
-        self.arena.get_mut(&from).unwrap().add_dep(name, to)
+        Ok(self.arena.get_mut(&from).unwrap().add_dep(name, to))
     }
     pub fn is_empty(&self) -> bool {
         self.arena.is_empty()
@@ -139,35 +146,6 @@ fn dfs_find(&self, target: CrateId, from: CrateId, visited: &mut FxHashSet<Crate
     }
 }
 
-#[cfg(test)]
-mod tests {
-    use super::{CrateGraph, FxHashMap, FileId, SmolStr};
-
-    #[test]
-    #[should_panic]
-    fn it_should_painc_because_of_cycle_dependencies() {
-        let mut graph = CrateGraph::default();
-        let crate1 = graph.add_crate_root(FileId(1u32));
-        let crate2 = graph.add_crate_root(FileId(2u32));
-        let crate3 = graph.add_crate_root(FileId(3u32));
-        graph.add_dep(crate1, SmolStr::new("crate2"), crate2);
-        graph.add_dep(crate2, SmolStr::new("crate3"), crate3);
-        graph.add_dep(crate3, SmolStr::new("crate1"), crate1);
-    }
-
-    #[test]
-    fn it_works() {
-        let mut graph = CrateGraph {
-            arena: FxHashMap::default(),
-        };
-        let crate1 = graph.add_crate_root(FileId(1u32));
-        let crate2 = graph.add_crate_root(FileId(2u32));
-        let crate3 = graph.add_crate_root(FileId(3u32));
-        graph.add_dep(crate1, SmolStr::new("crate2"), crate2);
-        graph.add_dep(crate2, SmolStr::new("crate3"), crate3);
-    }
-}
-
 salsa::query_group! {
     pub trait FilesDatabase: salsa::Database {
         /// Text of the file.
@@ -209,3 +187,39 @@ fn crate_graph() -> Arc<CrateGraph> {
         }
     }
 }
+
+#[cfg(test)]
+mod tests {
+    use super::{CrateGraph, FileId, SmolStr};
+
+    #[test]
+    fn it_should_painc_because_of_cycle_dependencies() {
+        let mut graph = CrateGraph::default();
+        let crate1 = graph.add_crate_root(FileId(1u32));
+        let crate2 = graph.add_crate_root(FileId(2u32));
+        let crate3 = graph.add_crate_root(FileId(3u32));
+        assert!(graph
+            .add_dep(crate1, SmolStr::new("crate2"), crate2)
+            .is_ok());
+        assert!(graph
+            .add_dep(crate2, SmolStr::new("crate3"), crate3)
+            .is_ok());
+        assert!(graph
+            .add_dep(crate3, SmolStr::new("crate1"), crate1)
+            .is_err());
+    }
+
+    #[test]
+    fn it_works() {
+        let mut graph = CrateGraph::default();
+        let crate1 = graph.add_crate_root(FileId(1u32));
+        let crate2 = graph.add_crate_root(FileId(2u32));
+        let crate3 = graph.add_crate_root(FileId(3u32));
+        assert!(graph
+            .add_dep(crate1, SmolStr::new("crate2"), crate2)
+            .is_ok());
+        assert!(graph
+            .add_dep(crate2, SmolStr::new("crate3"), crate3)
+            .is_ok());
+    }
+}
index ba9fcb3d1db38e89dc6318028047d99cf16a8d78..647fd92aad01e430f88d961e25f6c10d575111d2 100644 (file)
@@ -235,7 +235,9 @@ fn item_map_across_crates() {
     let mut crate_graph = CrateGraph::default();
     let main_crate = crate_graph.add_crate_root(main_id);
     let lib_crate = crate_graph.add_crate_root(lib_id);
-    crate_graph.add_dep(main_crate, "test_crate".into(), lib_crate);
+    crate_graph
+        .add_dep(main_crate, "test_crate".into(), lib_crate)
+        .unwrap();
 
     db.set_crate_graph(crate_graph);
 
@@ -288,7 +290,9 @@ pub mod b {
     let mut crate_graph = CrateGraph::default();
     let main_crate = crate_graph.add_crate_root(main_id);
     let lib_crate = crate_graph.add_crate_root(lib_id);
-    crate_graph.add_dep(main_crate, "test_crate".into(), lib_crate);
+    crate_graph
+        .add_dep(main_crate, "test_crate".into(), lib_crate)
+        .unwrap();
 
     db.set_crate_graph(crate_graph);
 
@@ -330,7 +334,9 @@ fn reexport_across_crates() {
     let mut crate_graph = CrateGraph::default();
     let main_crate = crate_graph.add_crate_root(main_id);
     let lib_crate = crate_graph.add_crate_root(lib_id);
-    crate_graph.add_dep(main_crate, "test_crate".into(), lib_crate);
+    crate_graph
+        .add_dep(main_crate, "test_crate".into(), lib_crate)
+        .unwrap();
 
     db.set_crate_graph(crate_graph);
 
index 8d2ff561ac6304e67436560e8c182e1ad17b387f..e2537758dd3b18da725d7fbfae295c1f3135795d 100644 (file)
@@ -13,8 +13,11 @@ pub(crate) fn goto_definition(
     let file = db.source_file(position.file_id);
     let syntax = file.syntax();
     if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, position.offset) {
-        let navs = reference_definition(db, position.file_id, name_ref)?;
-        return Ok(Some(RangeInfo::new(name_ref.syntax().range(), navs)));
+        let navs = reference_definition(db, position.file_id, name_ref)?.to_vec();
+        return Ok(Some(RangeInfo::new(
+            name_ref.syntax().range(),
+            navs.to_vec(),
+        )));
     }
     if let Some(name) = find_node_at_offset::<ast::Name>(syntax, position.offset) {
         let navs = ctry!(name_definition(db, position.file_id, name)?);
@@ -23,11 +26,27 @@ pub(crate) fn goto_definition(
     Ok(None)
 }
 
+pub(crate) enum ReferenceResult {
+    Exact(NavigationTarget),
+    Approximate(Vec<NavigationTarget>),
+}
+
+impl ReferenceResult {
+    fn to_vec(self) -> Vec<NavigationTarget> {
+        use self::ReferenceResult::*;
+        match self {
+            Exact(target) => vec![target],
+            Approximate(vec) => vec,
+        }
+    }
+}
+
 pub(crate) fn reference_definition(
     db: &RootDatabase,
     file_id: FileId,
     name_ref: &ast::NameRef,
-) -> Cancelable<Vec<NavigationTarget>> {
+) -> Cancelable<ReferenceResult> {
+    use self::ReferenceResult::*;
     if let Some(fn_descr) =
         hir::source_binder::function_from_child_node(db, file_id, name_ref.syntax())?
     {
@@ -35,7 +54,7 @@ pub(crate) fn reference_definition(
         // First try to resolve the symbol locally
         if let Some(entry) = scope.resolve_local_name(name_ref) {
             let nav = NavigationTarget::from_scope_entry(file_id, &entry);
-            return Ok(vec![nav]);
+            return Ok(Exact(nav));
         };
     }
     // Then try module name resolution
@@ -51,7 +70,7 @@ pub(crate) fn reference_definition(
             let resolved = module.resolve_path(db, &path)?;
             if let Some(def_id) = resolved.take_types().or(resolved.take_values()) {
                 if let Some(target) = NavigationTarget::from_def(db, def_id.resolve(db)?)? {
-                    return Ok(vec![target]);
+                    return Ok(Exact(target));
                 }
             }
         }
@@ -62,7 +81,7 @@ pub(crate) fn reference_definition(
         .into_iter()
         .map(NavigationTarget::from_symbol)
         .collect();
-    Ok(navs)
+    Ok(Approximate(navs))
 }
 
 fn name_definition(
index b66774cdfa4d28af32b4026a316e3cdb1a1f3c14..2968b807cad49b3ca9118aceccc6003dba30b191 100644 (file)
@@ -16,9 +16,16 @@ pub(crate) fn hover(
 
     let mut range = None;
     if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(file.syntax(), position.offset) {
-        let navs = crate::goto_definition::reference_definition(db, position.file_id, name_ref)?;
-        for nav in navs {
-            res.extend(doc_text_for(db, nav)?)
+        use crate::goto_definition::{ReferenceResult::*, reference_definition};
+        let ref_result = reference_definition(db, position.file_id, name_ref)?;
+        match ref_result {
+            Exact(nav) => res.extend(doc_text_for(db, nav)?),
+            Approximate(navs) => {
+                res.push("Failed to exactly resolve the symbol. This is probably because rust_analyzer does not yet support glob imports or traits.  \nThese methods were found instead:".to_string());
+                for nav in navs {
+                    res.extend(doc_text_for(db, nav)?)
+                }
+            }
         }
         if !res.is_empty() {
             range = Some(name_ref.syntax().range())
@@ -34,7 +41,7 @@ pub(crate) fn hover(
             file_id: position.file_id,
             range: node.range(),
         };
-        res.extend(type_of(db, frange)?);
+        res.extend(type_of(db, frange)?.map(Into::into));
         range = Some(node.range());
     };
 
index 98b1d2d5521170cc57d3ab4767d8da72a37500b3..53e49da5ba550c0a5b0b37ba4afd912936715d2c 100644 (file)
@@ -17,6 +17,7 @@ pub struct Runnable {
 pub enum RunnableKind {
     Test { name: String },
     TestMod { path: String },
+    Bench { name: String },
     Bin,
 }
 
@@ -48,6 +49,10 @@ fn runnable_fn(fn_def: &ast::FnDef) -> Option<Runnable> {
         RunnableKind::Test {
             name: name.to_string(),
         }
+    } else if fn_def.has_atom_attr("bench") {
+        RunnableKind::Bench {
+            name: name.to_string(),
+        }
     } else {
         return None;
     };
index a66f14b821005916a5160e06c6d98ebe22b213ee..db9496bbe0e3f6d54c3d0c6671fbab3f6839540e 100644 (file)
@@ -32,6 +32,15 @@ pub(crate) fn runnable_args(
             res.push(path.to_string());
             res.push("--nocapture".to_string());
         }
+        RunnableKind::Bench { name } => {
+            res.push("bench".to_string());
+            if let Some(spec) = spec {
+                spec.push_to(&mut res);
+            }
+            res.push("--".to_string());
+            res.push(name.to_string());
+            res.push("--nocapture".to_string());
+        }
         RunnableKind::Bin => {
             res.push("run".to_string());
             if let Some(spec) = spec {
index a781df181be2032ea7c202d2842524cbc4cfc561..7326a727dcbafa6b2f9ce0f94c29e6b9121c4573 100644 (file)
@@ -2,22 +2,23 @@
 
 use gen_lsp_server::ErrorCode;
 use languageserver_types::{
-    CodeActionResponse, Command, CodeLens, Diagnostic, DiagnosticSeverity, DocumentFormattingParams,
-    DocumentHighlight, DocumentSymbol, Documentation, FoldingRange, FoldingRangeKind,
-    FoldingRangeParams, Hover, HoverContents, Location, MarkupContent, MarkupKind,
-    ParameterInformation, ParameterLabel, Position, PrepareRenameResponse, Range, RenameParams,
-    SignatureInformation, SymbolInformation, TextDocumentIdentifier, TextEdit, WorkspaceEdit,
+    CodeActionResponse, CodeLens, Command, Diagnostic, DiagnosticSeverity,
+    DocumentFormattingParams, DocumentHighlight, DocumentSymbol, Documentation, FoldingRange,
+    FoldingRangeKind, FoldingRangeParams, Hover, HoverContents, Location, MarkupContent,
+    MarkupKind, ParameterInformation, ParameterLabel, Position, PrepareRenameResponse, Range,
+    RenameParams, SignatureInformation, SymbolInformation, TextDocumentIdentifier, TextEdit,
+    WorkspaceEdit,
 };
 use ra_ide_api::{
-    FileId, FilePosition, FileRange, FoldKind, Query, RunnableKind, Severity, RangeInfo,
+    FileId, FilePosition, FileRange, FoldKind, Query, RangeInfo, RunnableKind, Severity,
 };
-use ra_syntax::{TextUnit, AstNode};
+use ra_syntax::{AstNode, TextUnit};
 use rustc_hash::FxHashMap;
 use serde_json::to_value;
 use std::io::Write;
 
 use crate::{
-    cargo_target_spec::{CargoTargetSpec, runnable_args},
+    cargo_target_spec::{runnable_args, CargoTargetSpec},
     conv::{to_location, to_location_link, Conv, ConvWith, MapConvWith, TryConvWith},
     req::{self, Decoration},
     server_world::ServerWorld,
@@ -258,6 +259,7 @@ pub fn handle_runnables(
             label: match &runnable.kind {
                 RunnableKind::Test { name } => format!("test {}", name),
                 RunnableKind::TestMod { path } => format!("test-mod {}", path),
+                RunnableKind::Bench { name } => format!("bench {}", name),
                 RunnableKind::Bin => "run binary".to_string(),
             },
             bin: "cargo".to_string(),
@@ -586,35 +588,37 @@ pub fn handle_code_lens(
     let mut lenses: Vec<CodeLens> = Default::default();
 
     for runnable in world.analysis().runnables(file_id)? {
-        match &runnable.kind {
-            RunnableKind::Test { name: _ } | RunnableKind::TestMod { path: _ } => {
-                let args = runnable_args(&world, file_id, &runnable.kind)?;
-
-                let range = runnable.range.conv_with(&line_index);
-
-                // This represents the actual command that will be run.
-                let r: req::Runnable = req::Runnable {
-                    range,
-                    label: Default::default(),
-                    bin: "cargo".into(),
-                    args,
-                    env: Default::default(),
-                };
+        let title = match &runnable.kind {
+            RunnableKind::Test { name: _ } | RunnableKind::TestMod { path: _ } => Some("Run Test"),
+            RunnableKind::Bench { name: _ } => Some("Run Bench"),
+            _ => None,
+        };
 
-                let lens = CodeLens {
-                    range,
-                    command: Some(Command {
-                        title: "Run Test".into(),
-                        command: "ra-lsp.run-single".into(),
-                        arguments: Some(vec![to_value(r).unwrap()]),
-                    }),
-                    data: None,
-                };
+        if let Some(title) = title {
+            let args = runnable_args(&world, file_id, &runnable.kind)?;
+            let range = runnable.range.conv_with(&line_index);
+
+            // This represents the actual command that will be run.
+            let r: req::Runnable = req::Runnable {
+                range,
+                label: Default::default(),
+                bin: "cargo".into(),
+                args,
+                env: Default::default(),
+            };
 
-                lenses.push(lens);
-            }
-            _ => continue,
-        };
+            let lens = CodeLens {
+                range,
+                command: Some(Command {
+                    title: title.into(),
+                    command: "ra-lsp.run-single".into(),
+                    arguments: Some(vec![to_value(r).unwrap()]),
+                }),
+                data: None,
+            };
+
+            lenses.push(lens);
+        }
     }
 
     return Ok(Some(lenses));
index 4f3c231d319c48b1db65eacfdab811e05a197f2a..d5dbf999fd157d6e9fcc730790f78170f57e41ac 100644 (file)
@@ -73,7 +73,9 @@ pub fn new(root: PathBuf, workspaces: Vec<ProjectWorkspace>) -> ServerWorldState
                     if let (Some(&from), Some(&to)) =
                         (sysroot_crates.get(&from), sysroot_crates.get(&to))
                     {
-                        crate_graph.add_dep(from, name.clone(), to);
+                        if let Err(_) = crate_graph.add_dep(from, name.clone(), to) {
+                            log::error!("cyclic dependency between sysroot crates")
+                        }
                     }
                 }
             }
@@ -108,11 +110,20 @@ pub fn new(root: PathBuf, workspaces: Vec<ProjectWorkspace>) -> ServerWorldState
                 for &from in pkg_crates.get(&pkg).into_iter().flatten() {
                     if let Some(to) = lib_tgt {
                         if to != from {
-                            crate_graph.add_dep(from, pkg.name(&ws.cargo).into(), to);
+                            if let Err(_) =
+                                crate_graph.add_dep(from, pkg.name(&ws.cargo).into(), to)
+                            {
+                                log::error!(
+                                    "cyclic dependency between targets of {}",
+                                    pkg.name(&ws.cargo)
+                                )
+                            }
                         }
                     }
                     if let Some(std) = libstd {
-                        crate_graph.add_dep(from, "std".into(), std);
+                        if let Err(_) = crate_graph.add_dep(from, "std".into(), std) {
+                            log::error!("cyclic dependency on std for {}", pkg.name(&ws.cargo))
+                        }
                     }
                 }
             }
@@ -123,7 +134,13 @@ pub fn new(root: PathBuf, workspaces: Vec<ProjectWorkspace>) -> ServerWorldState
                 for dep in pkg.dependencies(&ws.cargo) {
                     if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) {
                         for &from in pkg_crates.get(&pkg).into_iter().flatten() {
-                            crate_graph.add_dep(from, dep.name.clone(), to);
+                            if let Err(_) = crate_graph.add_dep(from, dep.name.clone(), to) {
+                                log::error!(
+                                    "cyclic dependency {} -> {}",
+                                    pkg.name(&ws.cargo),
+                                    dep.pkg.name(&ws.cargo)
+                                )
+                            }
                         }
                     }
                 }
index d96ace97959d02f72c2f8e3009b3053a5ca07393..675a534c8f319fc142cccd83e990e1429800b1ce 100644 (file)
@@ -10,7 +10,9 @@ export interface SourceChange {
 }
 
 export async function handle(change: SourceChange) {
-    const wsEdit = Server.client.protocol2CodeConverter.asWorkspaceEdit(change.workspaceEdit);
+    const wsEdit = Server.client.protocol2CodeConverter.asWorkspaceEdit(
+        change.workspaceEdit
+    );
     let created;
     let moved;
     if (change.workspaceEdit.documentChanges) {
index 64401b68401da21cd2882b157a87e02ce6b9f8f8..bb376e3cb41a02c7e51875cf25a4d8da5df34573 100644 (file)
@@ -6,7 +6,6 @@ import {
     SourceChange
 } from './apply_source_change';
 
-
 export async function handle(event: { text: string }): Promise<boolean> {
     const editor = vscode.window.activeTextEditor;
     if (
index f9a4e2fc93b0a4cc1253c49ba3a221ad8cf73873..aa5817c21fabcbdd0b51d93f72364aced9fac080 100644 (file)
@@ -48,7 +48,11 @@ function createTask(spec: Runnable): vscode.Task {
         cwd: '.',
         env: definition.env
     };
-    const exec = new vscode.ShellExecution(definition.command, definition.args, execOption);
+    const exec = new vscode.ShellExecution(
+        definition.command,
+        definition.args,
+        execOption
+    );
 
     const f = vscode.workspace.workspaceFolders![0];
     const t = new vscode.Task(
@@ -59,7 +63,7 @@ function createTask(spec: Runnable): vscode.Task {
         exec,
         ['$rustc']
     );
-    t.presentationOptions.clear = true
+    t.presentationOptions.clear = true;
     return t;
 }
 
@@ -114,8 +118,8 @@ export async function handleSingle(runnable: Runnable) {
     task.group = vscode.TaskGroup.Build;
     task.presentationOptions = {
         reveal: vscode.TaskRevealKind.Always,
-        panel: vscode.TaskPanelKind.Dedicated,
+        panel: vscode.TaskPanelKind.Dedicated
     };
-    
+
     return vscode.tasks.executeTask(task);
-}
\ No newline at end of file
+}
index 9edfb13b5f7d586b7a30d03b66c1b6c25c23b1ac..0098c94547ab05dc17eb6202a9524ac1fdac4184 100644 (file)
@@ -37,8 +37,10 @@ export function activate(context: vscode.ExtensionContext) {
                     return await original(...args);
                 }
             });
-        } catch(_) {
-            vscode.window.showWarningMessage('Enhanced typing feature is disabled because of incompatibility with VIM extension');
+        } catch (_) {
+            vscode.window.showWarningMessage(
+                'Enhanced typing feature is disabled because of incompatibility with VIM extension'
+            );
         }
     }