diff options
author | Zac Pullar-Strecker <[email protected]> | 2020-08-25 05:44:36 +0100 |
---|---|---|
committer | Zac Pullar-Strecker <[email protected]> | 2020-08-25 05:44:36 +0100 |
commit | b835f06cecd2189cb32a431fdb85245fbf53032a (patch) | |
tree | 8bb4ba65f4922e9cca571a7d4a7fa17d047ae779 | |
parent | 452afaebe188251cd4403e56999bf8b58de4fba9 (diff) | |
parent | ef9cea945d5767e7c60d5931a7649a73caea23ad (diff) |
Merge remote-tracking branch 'upstream/master' into 503-hover-doc-links
46 files changed, 959 insertions, 835 deletions
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 000000000..be2c7a8ca --- /dev/null +++ b/.github/workflows/publish.yml | |||
@@ -0,0 +1,44 @@ | |||
1 | name: publish | ||
2 | on: | ||
3 | workflow_dispatch: # We can add version input when 1.0 is released and scheduled releases are removed | ||
4 | |||
5 | schedule: | ||
6 | - cron: "0 0 * * *" # midnight UTC | ||
7 | |||
8 | push: | ||
9 | branches: | ||
10 | - release | ||
11 | |||
12 | jobs: | ||
13 | publish: | ||
14 | name: publish | ||
15 | runs-on: ubuntu-16.04 | ||
16 | steps: | ||
17 | - name: Checkout repository | ||
18 | uses: actions/checkout@v2 | ||
19 | with: | ||
20 | fetch-depth: 0 | ||
21 | |||
22 | - name: Install Rust toolchain | ||
23 | uses: actions-rs/toolchain@v1 | ||
24 | with: | ||
25 | toolchain: stable | ||
26 | profile: minimal | ||
27 | override: true | ||
28 | |||
29 | - name: Install cargo-workspaces | ||
30 | uses: actions-rs/[email protected] | ||
31 | with: | ||
32 | crate: cargo-workspaces | ||
33 | |||
34 | - name: Release | ||
35 | env: | ||
36 | CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} | ||
37 | PATCH: ${{ github.run_number }} | ||
38 | shell: bash | ||
39 | run: | | ||
40 | git config --global user.email "[email protected]" | ||
41 | git config --global user.name "Github Action" | ||
42 | rm Cargo.lock | ||
43 | cargo workspaces rename ra_ap_%n | ||
44 | cargo workspaces publish --yes --force '*' --exact --no-git-commit --allow-dirty --skip-published custom 0.0.$PATCH | ||
diff --git a/Cargo.lock b/Cargo.lock index 1f8e7a29d..015f84ba8 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -1718,9 +1718,9 @@ dependencies = [ | |||
1718 | 1718 | ||
1719 | [[package]] | 1719 | [[package]] |
1720 | name = "ungrammar" | 1720 | name = "ungrammar" |
1721 | version = "1.1.2" | 1721 | version = "1.1.3" |
1722 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1722 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1723 | checksum = "bab6142ac77be714b1ea78faca6efaed5478c50724786b0fe80d8528d10692b3" | 1723 | checksum = "ca4d39065b45f658d33013f7cc93ee050708cd543f6e07dd15b4293fcf217e12" |
1724 | 1724 | ||
1725 | [[package]] | 1725 | [[package]] |
1726 | name = "unicase" | 1726 | name = "unicase" |
diff --git a/crates/arena/Cargo.toml b/crates/arena/Cargo.toml index f2bb5cc45..863eedf76 100644 --- a/crates/arena/Cargo.toml +++ b/crates/arena/Cargo.toml | |||
@@ -1,6 +1,7 @@ | |||
1 | [package] | 1 | [package] |
2 | name = "arena" | 2 | name = "arena" |
3 | version = "0.0.0" | 3 | version = "0.0.0" |
4 | description = "TBD" | ||
4 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
5 | authors = ["rust-analyzer developers"] | 6 | authors = ["rust-analyzer developers"] |
6 | edition = "2018" | 7 | edition = "2018" |
diff --git a/crates/assists/Cargo.toml b/crates/assists/Cargo.toml index a560a35c7..264125651 100644 --- a/crates/assists/Cargo.toml +++ b/crates/assists/Cargo.toml | |||
@@ -1,6 +1,7 @@ | |||
1 | [package] | 1 | [package] |
2 | name = "assists" | 2 | name = "assists" |
3 | version = "0.0.0" | 3 | version = "0.0.0" |
4 | description = "TBD" | ||
4 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
5 | authors = ["rust-analyzer developers"] | 6 | authors = ["rust-analyzer developers"] |
6 | edition = "2018" | 7 | edition = "2018" |
@@ -13,11 +14,11 @@ rustc-hash = "1.1.0" | |||
13 | itertools = "0.9.0" | 14 | itertools = "0.9.0" |
14 | either = "1.5.3" | 15 | either = "1.5.3" |
15 | 16 | ||
16 | stdx = { path = "../stdx" } | 17 | stdx = { path = "../stdx", version = "0.0.0" } |
17 | syntax = { path = "../syntax" } | 18 | syntax = { path = "../syntax", version = "0.0.0" } |
18 | text_edit = { path = "../text_edit" } | 19 | text_edit = { path = "../text_edit", version = "0.0.0" } |
19 | profile = { path = "../profile" } | 20 | profile = { path = "../profile", version = "0.0.0" } |
20 | base_db = { path = "../base_db" } | 21 | base_db = { path = "../base_db", version = "0.0.0" } |
21 | ide_db = { path = "../ide_db" } | 22 | ide_db = { path = "../ide_db", version = "0.0.0" } |
22 | hir = { path = "../hir" } | 23 | hir = { path = "../hir", version = "0.0.0" } |
23 | test_utils = { path = "../test_utils" } | 24 | test_utils = { path = "../test_utils", version = "0.0.0" } |
diff --git a/crates/assists/src/assist_context.rs b/crates/assists/src/assist_context.rs index 11c171fc2..bf520069e 100644 --- a/crates/assists/src/assist_context.rs +++ b/crates/assists/src/assist_context.rs | |||
@@ -73,10 +73,6 @@ impl<'a> AssistContext<'a> { | |||
73 | self.sema.db | 73 | self.sema.db |
74 | } | 74 | } |
75 | 75 | ||
76 | pub(crate) fn source_file(&self) -> &SourceFile { | ||
77 | &self.source_file | ||
78 | } | ||
79 | |||
80 | // NB, this ignores active selection. | 76 | // NB, this ignores active selection. |
81 | pub(crate) fn offset(&self) -> TextSize { | 77 | pub(crate) fn offset(&self) -> TextSize { |
82 | self.frange.range.start() | 78 | self.frange.range.start() |
diff --git a/crates/assists/src/handlers/expand_glob_import.rs b/crates/assists/src/handlers/expand_glob_import.rs index 81d0af2f3..b39d040f6 100644 --- a/crates/assists/src/handlers/expand_glob_import.rs +++ b/crates/assists/src/handlers/expand_glob_import.rs | |||
@@ -1,10 +1,10 @@ | |||
1 | use either::Either; | 1 | use either::Either; |
2 | use hir::{AssocItem, MacroDef, ModuleDef, Name, PathResolution, ScopeDef, SemanticsScope}; | 2 | use hir::{AssocItem, MacroDef, Module, ModuleDef, Name, PathResolution, ScopeDef}; |
3 | use ide_db::{ | 3 | use ide_db::{ |
4 | defs::{classify_name_ref, Definition, NameRefClass}, | 4 | defs::{classify_name_ref, Definition, NameRefClass}, |
5 | RootDatabase, | 5 | search::SearchScope, |
6 | }; | 6 | }; |
7 | use syntax::{algo, ast, match_ast, AstNode, SyntaxNode, SyntaxToken, T}; | 7 | use syntax::{algo, ast, AstNode, Direction, SyntaxNode, SyntaxToken, T}; |
8 | 8 | ||
9 | use crate::{ | 9 | use crate::{ |
10 | assist_context::{AssistBuilder, AssistContext, Assists}, | 10 | assist_context::{AssistBuilder, AssistContext, Assists}, |
@@ -38,140 +38,259 @@ use crate::{ | |||
38 | // ``` | 38 | // ``` |
39 | pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 39 | pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { |
40 | let star = ctx.find_token_at_offset(T![*])?; | 40 | let star = ctx.find_token_at_offset(T![*])?; |
41 | let mod_path = find_mod_path(&star)?; | 41 | let (parent, mod_path) = find_parent_and_path(&star)?; |
42 | let module = match ctx.sema.resolve_path(&mod_path)? { | 42 | let target_module = match ctx.sema.resolve_path(&mod_path)? { |
43 | PathResolution::Def(ModuleDef::Module(it)) => it, | 43 | PathResolution::Def(ModuleDef::Module(it)) => it, |
44 | _ => return None, | 44 | _ => return None, |
45 | }; | 45 | }; |
46 | 46 | ||
47 | let source_file = ctx.source_file(); | 47 | let current_scope = ctx.sema.scope(&star.parent()); |
48 | let scope = ctx.sema.scope_at_offset(source_file.syntax(), ctx.offset()); | 48 | let current_module = current_scope.module()?; |
49 | 49 | ||
50 | let defs_in_mod = find_defs_in_mod(ctx, scope, module)?; | 50 | let refs_in_target = find_refs_in_mod(ctx, target_module, Some(current_module))?; |
51 | let name_refs_in_source_file = | 51 | let imported_defs = find_imported_defs(ctx, star)?; |
52 | source_file.syntax().descendants().filter_map(ast::NameRef::cast).collect(); | 52 | let names_to_import = find_names_to_import(ctx, refs_in_target, imported_defs); |
53 | let used_names = find_used_names(ctx, defs_in_mod, name_refs_in_source_file); | ||
54 | 53 | ||
55 | let parent = star.parent().parent()?; | 54 | let target = parent.clone().either(|n| n.syntax().clone(), |n| n.syntax().clone()); |
56 | acc.add( | 55 | acc.add( |
57 | AssistId("expand_glob_import", AssistKind::RefactorRewrite), | 56 | AssistId("expand_glob_import", AssistKind::RefactorRewrite), |
58 | "Expand glob import", | 57 | "Expand glob import", |
59 | parent.text_range(), | 58 | target.text_range(), |
60 | |builder| { | 59 | |builder| { |
61 | replace_ast(builder, &parent, mod_path, used_names); | 60 | replace_ast(builder, parent, mod_path, names_to_import); |
62 | }, | 61 | }, |
63 | ) | 62 | ) |
64 | } | 63 | } |
65 | 64 | ||
66 | fn find_mod_path(star: &SyntaxToken) -> Option<ast::Path> { | 65 | fn find_parent_and_path( |
67 | star.ancestors().find_map(|n| ast::UseTree::cast(n).and_then(|u| u.path())) | 66 | star: &SyntaxToken, |
67 | ) -> Option<(Either<ast::UseTree, ast::UseTreeList>, ast::Path)> { | ||
68 | return star.ancestors().find_map(|n| { | ||
69 | find_use_tree_list(n.clone()) | ||
70 | .and_then(|(u, p)| Some((Either::Right(u), p))) | ||
71 | .or_else(|| find_use_tree(n).and_then(|(u, p)| Some((Either::Left(u), p)))) | ||
72 | }); | ||
73 | |||
74 | fn find_use_tree_list(n: SyntaxNode) -> Option<(ast::UseTreeList, ast::Path)> { | ||
75 | let use_tree_list = ast::UseTreeList::cast(n)?; | ||
76 | let path = use_tree_list.parent_use_tree().path()?; | ||
77 | Some((use_tree_list, path)) | ||
78 | } | ||
79 | |||
80 | fn find_use_tree(n: SyntaxNode) -> Option<(ast::UseTree, ast::Path)> { | ||
81 | let use_tree = ast::UseTree::cast(n)?; | ||
82 | let path = use_tree.path()?; | ||
83 | Some((use_tree, path)) | ||
84 | } | ||
68 | } | 85 | } |
69 | 86 | ||
70 | #[derive(PartialEq)] | 87 | #[derive(Debug, PartialEq, Clone)] |
71 | enum Def { | 88 | enum Def { |
72 | ModuleDef(ModuleDef), | 89 | ModuleDef(ModuleDef), |
73 | MacroDef(MacroDef), | 90 | MacroDef(MacroDef), |
74 | } | 91 | } |
75 | 92 | ||
76 | impl Def { | 93 | impl Def { |
77 | fn name(&self, db: &RootDatabase) -> Option<Name> { | 94 | fn is_referenced_in(&self, ctx: &AssistContext) -> bool { |
78 | match self { | 95 | let def = match self { |
79 | Def::ModuleDef(def) => def.name(db), | 96 | Def::ModuleDef(def) => Definition::ModuleDef(*def), |
80 | Def::MacroDef(def) => def.name(db), | 97 | Def::MacroDef(def) => Definition::Macro(*def), |
98 | }; | ||
99 | |||
100 | let search_scope = SearchScope::single_file(ctx.frange.file_id); | ||
101 | def.usages(&ctx.sema).in_scope(search_scope).at_least_one() | ||
102 | } | ||
103 | } | ||
104 | |||
105 | #[derive(Debug, Clone)] | ||
106 | struct Ref { | ||
107 | // could be alias | ||
108 | visible_name: Name, | ||
109 | def: Def, | ||
110 | } | ||
111 | |||
112 | impl Ref { | ||
113 | fn from_scope_def(name: Name, scope_def: ScopeDef) -> Option<Self> { | ||
114 | match scope_def { | ||
115 | ScopeDef::ModuleDef(def) => Some(Ref { visible_name: name, def: Def::ModuleDef(def) }), | ||
116 | ScopeDef::MacroDef(def) => Some(Ref { visible_name: name, def: Def::MacroDef(def) }), | ||
117 | _ => None, | ||
81 | } | 118 | } |
82 | } | 119 | } |
83 | } | 120 | } |
84 | 121 | ||
85 | fn find_defs_in_mod( | 122 | #[derive(Debug, Clone)] |
123 | struct Refs(Vec<Ref>); | ||
124 | |||
125 | impl Refs { | ||
126 | fn used_refs(&self, ctx: &AssistContext) -> Refs { | ||
127 | Refs( | ||
128 | self.0 | ||
129 | .clone() | ||
130 | .into_iter() | ||
131 | .filter(|r| { | ||
132 | if let Def::ModuleDef(ModuleDef::Trait(tr)) = r.def { | ||
133 | if tr | ||
134 | .items(ctx.db()) | ||
135 | .into_iter() | ||
136 | .find(|ai| { | ||
137 | if let AssocItem::Function(f) = *ai { | ||
138 | Def::ModuleDef(ModuleDef::Function(f)).is_referenced_in(ctx) | ||
139 | } else { | ||
140 | false | ||
141 | } | ||
142 | }) | ||
143 | .is_some() | ||
144 | { | ||
145 | return true; | ||
146 | } | ||
147 | } | ||
148 | |||
149 | r.def.is_referenced_in(ctx) | ||
150 | }) | ||
151 | .collect(), | ||
152 | ) | ||
153 | } | ||
154 | |||
155 | fn filter_out_by_defs(&self, defs: Vec<Def>) -> Refs { | ||
156 | Refs(self.0.clone().into_iter().filter(|r| !defs.contains(&r.def)).collect()) | ||
157 | } | ||
158 | } | ||
159 | |||
160 | fn find_refs_in_mod( | ||
86 | ctx: &AssistContext, | 161 | ctx: &AssistContext, |
87 | from: SemanticsScope<'_>, | 162 | module: Module, |
88 | module: hir::Module, | 163 | visible_from: Option<Module>, |
89 | ) -> Option<Vec<Def>> { | 164 | ) -> Option<Refs> { |
90 | let module_scope = module.scope(ctx.db(), from.module()); | 165 | if let Some(from) = visible_from { |
91 | 166 | if !is_mod_visible_from(ctx, module, from) { | |
92 | let mut defs = vec![]; | 167 | return None; |
93 | for (_, def) in module_scope { | ||
94 | match def { | ||
95 | ScopeDef::ModuleDef(def) => defs.push(Def::ModuleDef(def)), | ||
96 | ScopeDef::MacroDef(def) => defs.push(Def::MacroDef(def)), | ||
97 | _ => continue, | ||
98 | } | 168 | } |
99 | } | 169 | } |
100 | 170 | ||
101 | Some(defs) | 171 | let module_scope = module.scope(ctx.db(), visible_from); |
172 | let refs = module_scope.into_iter().filter_map(|(n, d)| Ref::from_scope_def(n, d)).collect(); | ||
173 | Some(Refs(refs)) | ||
102 | } | 174 | } |
103 | 175 | ||
104 | fn find_used_names( | 176 | fn is_mod_visible_from(ctx: &AssistContext, module: Module, from: Module) -> bool { |
105 | ctx: &AssistContext, | 177 | match module.parent(ctx.db()) { |
106 | defs_in_mod: Vec<Def>, | 178 | Some(parent) => { |
107 | name_refs_in_source_file: Vec<ast::NameRef>, | 179 | parent.visibility_of(ctx.db(), &ModuleDef::Module(module)).map_or(true, |vis| { |
108 | ) -> Vec<Name> { | 180 | vis.is_visible_from(ctx.db(), from.into()) && is_mod_visible_from(ctx, parent, from) |
109 | let defs_in_source_file = name_refs_in_source_file | 181 | }) |
110 | .iter() | 182 | } |
111 | .filter_map(|r| classify_name_ref(&ctx.sema, r)) | 183 | None => true, |
112 | .filter_map(|rc| match rc { | 184 | } |
113 | NameRefClass::Definition(Definition::ModuleDef(def)) => Some(Def::ModuleDef(def)), | 185 | } |
114 | NameRefClass::Definition(Definition::Macro(def)) => Some(Def::MacroDef(def)), | ||
115 | _ => None, | ||
116 | }) | ||
117 | .collect::<Vec<Def>>(); | ||
118 | 186 | ||
119 | defs_in_mod | 187 | // looks for name refs in parent use block's siblings |
120 | .iter() | 188 | // |
121 | .filter(|def| { | 189 | // mod bar { |
122 | if let Def::ModuleDef(ModuleDef::Trait(tr)) = def { | 190 | // mod qux { |
123 | for item in tr.items(ctx.db()) { | 191 | // struct Qux; |
124 | if let AssocItem::Function(f) = item { | 192 | // } |
125 | if defs_in_source_file.contains(&Def::ModuleDef(ModuleDef::Function(f))) { | 193 | // |
126 | return true; | 194 | // pub use qux::Qux; |
127 | } | 195 | // } |
128 | } | 196 | // |
129 | } | 197 | // ↓ --------------- |
130 | } | 198 | // use foo::*<|>; |
199 | // use baz::Baz; | ||
200 | // ↑ --------------- | ||
201 | fn find_imported_defs(ctx: &AssistContext, star: SyntaxToken) -> Option<Vec<Def>> { | ||
202 | let parent_use_item_syntax = | ||
203 | star.ancestors().find_map(|n| if ast::Use::can_cast(n.kind()) { Some(n) } else { None })?; | ||
204 | |||
205 | Some( | ||
206 | [Direction::Prev, Direction::Next] | ||
207 | .iter() | ||
208 | .map(|dir| { | ||
209 | parent_use_item_syntax | ||
210 | .siblings(dir.to_owned()) | ||
211 | .filter(|n| ast::Use::can_cast(n.kind())) | ||
212 | }) | ||
213 | .flatten() | ||
214 | .filter_map(|n| Some(n.descendants().filter_map(ast::NameRef::cast))) | ||
215 | .flatten() | ||
216 | .filter_map(|r| match classify_name_ref(&ctx.sema, &r)? { | ||
217 | NameRefClass::Definition(Definition::ModuleDef(def)) => Some(Def::ModuleDef(def)), | ||
218 | NameRefClass::Definition(Definition::Macro(def)) => Some(Def::MacroDef(def)), | ||
219 | _ => None, | ||
220 | }) | ||
221 | .collect(), | ||
222 | ) | ||
223 | } | ||
131 | 224 | ||
132 | defs_in_source_file.contains(def) | 225 | fn find_names_to_import( |
133 | }) | 226 | ctx: &AssistContext, |
134 | .filter_map(|d| d.name(ctx.db())) | 227 | refs_in_target: Refs, |
135 | .collect() | 228 | imported_defs: Vec<Def>, |
229 | ) -> Vec<Name> { | ||
230 | let used_refs = refs_in_target.used_refs(ctx).filter_out_by_defs(imported_defs); | ||
231 | used_refs.0.iter().map(|r| r.visible_name.clone()).collect() | ||
136 | } | 232 | } |
137 | 233 | ||
138 | fn replace_ast( | 234 | fn replace_ast( |
139 | builder: &mut AssistBuilder, | 235 | builder: &mut AssistBuilder, |
140 | node: &SyntaxNode, | 236 | parent: Either<ast::UseTree, ast::UseTreeList>, |
141 | path: ast::Path, | 237 | path: ast::Path, |
142 | used_names: Vec<Name>, | 238 | names_to_import: Vec<Name>, |
143 | ) { | 239 | ) { |
144 | let replacement: Either<ast::UseTree, ast::UseTreeList> = match used_names.as_slice() { | 240 | let existing_use_trees = match parent.clone() { |
145 | [name] => Either::Left(ast::make::use_tree( | 241 | Either::Left(_) => vec![], |
146 | ast::make::path_from_text(&format!("{}::{}", path, name)), | 242 | Either::Right(u) => u |
147 | None, | 243 | .use_trees() |
148 | None, | 244 | .filter(|n| |
149 | false, | 245 | // filter out star |
150 | )), | 246 | n.star_token().is_none()) |
151 | names => Either::Right(ast::make::use_tree_list(names.iter().map(|n| { | 247 | .collect(), |
152 | ast::make::use_tree(ast::make::path_from_text(&n.to_string()), None, None, false) | ||
153 | }))), | ||
154 | }; | 248 | }; |
155 | 249 | ||
156 | let mut replace_node = |replacement: Either<ast::UseTree, ast::UseTreeList>| { | 250 | let new_use_trees: Vec<ast::UseTree> = names_to_import |
157 | algo::diff(node, &replacement.either(|u| u.syntax().clone(), |ut| ut.syntax().clone())) | 251 | .iter() |
252 | .map(|n| ast::make::use_tree(ast::make::path_from_text(&n.to_string()), None, None, false)) | ||
253 | .collect(); | ||
254 | |||
255 | let use_trees = [&existing_use_trees[..], &new_use_trees[..]].concat(); | ||
256 | |||
257 | match use_trees.as_slice() { | ||
258 | [name] => { | ||
259 | if let Some(end_path) = name.path() { | ||
260 | let replacement = ast::make::use_tree( | ||
261 | ast::make::path_from_text(&format!("{}::{}", path, end_path)), | ||
262 | None, | ||
263 | None, | ||
264 | false, | ||
265 | ); | ||
266 | |||
267 | algo::diff( | ||
268 | &parent.either(|n| n.syntax().clone(), |n| n.syntax().clone()), | ||
269 | replacement.syntax(), | ||
270 | ) | ||
271 | .into_text_edit(builder.text_edit_builder()); | ||
272 | } | ||
273 | } | ||
274 | names => { | ||
275 | let replacement = match parent { | ||
276 | Either::Left(_) => ast::make::use_tree( | ||
277 | path, | ||
278 | Some(ast::make::use_tree_list(names.to_owned())), | ||
279 | None, | ||
280 | false, | ||
281 | ) | ||
282 | .syntax() | ||
283 | .clone(), | ||
284 | Either::Right(_) => ast::make::use_tree_list(names.to_owned()).syntax().clone(), | ||
285 | }; | ||
286 | |||
287 | algo::diff( | ||
288 | &parent.either(|n| n.syntax().clone(), |n| n.syntax().clone()), | ||
289 | &replacement, | ||
290 | ) | ||
158 | .into_text_edit(builder.text_edit_builder()); | 291 | .into_text_edit(builder.text_edit_builder()); |
159 | }; | ||
160 | |||
161 | match_ast! { | ||
162 | match node { | ||
163 | ast::UseTree(use_tree) => { | ||
164 | replace_node(replacement); | ||
165 | }, | ||
166 | ast::UseTreeList(use_tree_list) => { | ||
167 | replace_node(replacement); | ||
168 | }, | ||
169 | ast::Use(use_item) => { | ||
170 | builder.replace_ast(use_item, ast::make::use_(replacement.left_or_else(|ut| ast::make::use_tree(path, Some(ut), None, false)))); | ||
171 | }, | ||
172 | _ => {}, | ||
173 | } | 292 | } |
174 | } | 293 | }; |
175 | } | 294 | } |
176 | 295 | ||
177 | #[cfg(test)] | 296 | #[cfg(test)] |
@@ -245,7 +364,46 @@ mod foo { | |||
245 | pub fn f() {} | 364 | pub fn f() {} |
246 | } | 365 | } |
247 | 366 | ||
248 | use foo::{Baz, Bar, f}; | 367 | use foo::{f, Baz, Bar}; |
368 | |||
369 | fn qux(bar: Bar, baz: Baz) { | ||
370 | f(); | ||
371 | } | ||
372 | ", | ||
373 | ) | ||
374 | } | ||
375 | |||
376 | #[test] | ||
377 | fn expanding_glob_import_with_existing_uses_in_same_module() { | ||
378 | check_assist( | ||
379 | expand_glob_import, | ||
380 | r" | ||
381 | mod foo { | ||
382 | pub struct Bar; | ||
383 | pub struct Baz; | ||
384 | pub struct Qux; | ||
385 | |||
386 | pub fn f() {} | ||
387 | } | ||
388 | |||
389 | use foo::Bar; | ||
390 | use foo::{*<|>, f}; | ||
391 | |||
392 | fn qux(bar: Bar, baz: Baz) { | ||
393 | f(); | ||
394 | } | ||
395 | ", | ||
396 | r" | ||
397 | mod foo { | ||
398 | pub struct Bar; | ||
399 | pub struct Baz; | ||
400 | pub struct Qux; | ||
401 | |||
402 | pub fn f() {} | ||
403 | } | ||
404 | |||
405 | use foo::Bar; | ||
406 | use foo::{f, Baz}; | ||
249 | 407 | ||
250 | fn qux(bar: Bar, baz: Baz) { | 408 | fn qux(bar: Bar, baz: Baz) { |
251 | f(); | 409 | f(); |
@@ -260,7 +418,7 @@ fn qux(bar: Bar, baz: Baz) { | |||
260 | expand_glob_import, | 418 | expand_glob_import, |
261 | r" | 419 | r" |
262 | mod foo { | 420 | mod foo { |
263 | mod bar { | 421 | pub mod bar { |
264 | pub struct Bar; | 422 | pub struct Bar; |
265 | pub struct Baz; | 423 | pub struct Baz; |
266 | pub struct Qux; | 424 | pub struct Qux; |
@@ -268,7 +426,7 @@ mod foo { | |||
268 | pub fn f() {} | 426 | pub fn f() {} |
269 | } | 427 | } |
270 | 428 | ||
271 | mod baz { | 429 | pub mod baz { |
272 | pub fn g() {} | 430 | pub fn g() {} |
273 | } | 431 | } |
274 | } | 432 | } |
@@ -282,7 +440,7 @@ fn qux(bar: Bar, baz: Baz) { | |||
282 | ", | 440 | ", |
283 | r" | 441 | r" |
284 | mod foo { | 442 | mod foo { |
285 | mod bar { | 443 | pub mod bar { |
286 | pub struct Bar; | 444 | pub struct Bar; |
287 | pub struct Baz; | 445 | pub struct Baz; |
288 | pub struct Qux; | 446 | pub struct Qux; |
@@ -290,55 +448,359 @@ mod foo { | |||
290 | pub fn f() {} | 448 | pub fn f() {} |
291 | } | 449 | } |
292 | 450 | ||
293 | mod baz { | 451 | pub mod baz { |
294 | pub fn g() {} | 452 | pub fn g() {} |
295 | } | 453 | } |
296 | } | 454 | } |
297 | 455 | ||
298 | use foo::{bar::{Baz, Bar, f}, baz::*}; | 456 | use foo::{bar::{f, Baz, Bar}, baz::*}; |
299 | 457 | ||
300 | fn qux(bar: Bar, baz: Baz) { | 458 | fn qux(bar: Bar, baz: Baz) { |
301 | f(); | 459 | f(); |
302 | g(); | 460 | g(); |
303 | } | 461 | } |
304 | ", | 462 | ", |
305 | ) | 463 | ); |
464 | |||
465 | check_assist( | ||
466 | expand_glob_import, | ||
467 | r" | ||
468 | mod foo { | ||
469 | pub mod bar { | ||
470 | pub struct Bar; | ||
471 | pub struct Baz; | ||
472 | pub struct Qux; | ||
473 | |||
474 | pub fn f() {} | ||
475 | } | ||
476 | |||
477 | pub mod baz { | ||
478 | pub fn g() {} | ||
479 | } | ||
480 | } | ||
481 | |||
482 | use foo::{bar::{Bar, Baz, f}, baz::*<|>}; | ||
483 | |||
484 | fn qux(bar: Bar, baz: Baz) { | ||
485 | f(); | ||
486 | g(); | ||
487 | } | ||
488 | ", | ||
489 | r" | ||
490 | mod foo { | ||
491 | pub mod bar { | ||
492 | pub struct Bar; | ||
493 | pub struct Baz; | ||
494 | pub struct Qux; | ||
495 | |||
496 | pub fn f() {} | ||
497 | } | ||
498 | |||
499 | pub mod baz { | ||
500 | pub fn g() {} | ||
501 | } | ||
502 | } | ||
503 | |||
504 | use foo::{bar::{Bar, Baz, f}, baz::g}; | ||
505 | |||
506 | fn qux(bar: Bar, baz: Baz) { | ||
507 | f(); | ||
508 | g(); | ||
509 | } | ||
510 | ", | ||
511 | ); | ||
512 | |||
513 | check_assist( | ||
514 | expand_glob_import, | ||
515 | r" | ||
516 | mod foo { | ||
517 | pub mod bar { | ||
518 | pub struct Bar; | ||
519 | pub struct Baz; | ||
520 | pub struct Qux; | ||
521 | |||
522 | pub fn f() {} | ||
523 | } | ||
524 | |||
525 | pub mod baz { | ||
526 | pub fn g() {} | ||
527 | |||
528 | pub mod qux { | ||
529 | pub fn h() {} | ||
530 | pub fn m() {} | ||
531 | |||
532 | pub mod q { | ||
533 | pub fn j() {} | ||
534 | } | ||
535 | } | ||
536 | } | ||
537 | } | ||
538 | |||
539 | use foo::{ | ||
540 | bar::{*, f}, | ||
541 | baz::{g, qux::*<|>} | ||
542 | }; | ||
543 | |||
544 | fn qux(bar: Bar, baz: Baz) { | ||
545 | f(); | ||
546 | g(); | ||
547 | h(); | ||
548 | q::j(); | ||
549 | } | ||
550 | ", | ||
551 | r" | ||
552 | mod foo { | ||
553 | pub mod bar { | ||
554 | pub struct Bar; | ||
555 | pub struct Baz; | ||
556 | pub struct Qux; | ||
557 | |||
558 | pub fn f() {} | ||
559 | } | ||
560 | |||
561 | pub mod baz { | ||
562 | pub fn g() {} | ||
563 | |||
564 | pub mod qux { | ||
565 | pub fn h() {} | ||
566 | pub fn m() {} | ||
567 | |||
568 | pub mod q { | ||
569 | pub fn j() {} | ||
570 | } | ||
571 | } | ||
572 | } | ||
573 | } | ||
574 | |||
575 | use foo::{ | ||
576 | bar::{*, f}, | ||
577 | baz::{g, qux::{q, h}} | ||
578 | }; | ||
579 | |||
580 | fn qux(bar: Bar, baz: Baz) { | ||
581 | f(); | ||
582 | g(); | ||
583 | h(); | ||
584 | q::j(); | ||
585 | } | ||
586 | ", | ||
587 | ); | ||
588 | |||
589 | check_assist( | ||
590 | expand_glob_import, | ||
591 | r" | ||
592 | mod foo { | ||
593 | pub mod bar { | ||
594 | pub struct Bar; | ||
595 | pub struct Baz; | ||
596 | pub struct Qux; | ||
597 | |||
598 | pub fn f() {} | ||
599 | } | ||
600 | |||
601 | pub mod baz { | ||
602 | pub fn g() {} | ||
603 | |||
604 | pub mod qux { | ||
605 | pub fn h() {} | ||
606 | pub fn m() {} | ||
607 | |||
608 | pub mod q { | ||
609 | pub fn j() {} | ||
610 | } | ||
611 | } | ||
612 | } | ||
613 | } | ||
614 | |||
615 | use foo::{ | ||
616 | bar::{*, f}, | ||
617 | baz::{g, qux::{h, q::*<|>}} | ||
618 | }; | ||
619 | |||
620 | fn qux(bar: Bar, baz: Baz) { | ||
621 | f(); | ||
622 | g(); | ||
623 | h(); | ||
624 | j(); | ||
625 | } | ||
626 | ", | ||
627 | r" | ||
628 | mod foo { | ||
629 | pub mod bar { | ||
630 | pub struct Bar; | ||
631 | pub struct Baz; | ||
632 | pub struct Qux; | ||
633 | |||
634 | pub fn f() {} | ||
635 | } | ||
636 | |||
637 | pub mod baz { | ||
638 | pub fn g() {} | ||
639 | |||
640 | pub mod qux { | ||
641 | pub fn h() {} | ||
642 | pub fn m() {} | ||
643 | |||
644 | pub mod q { | ||
645 | pub fn j() {} | ||
646 | } | ||
647 | } | ||
648 | } | ||
649 | } | ||
650 | |||
651 | use foo::{ | ||
652 | bar::{*, f}, | ||
653 | baz::{g, qux::{h, q::j}} | ||
654 | }; | ||
655 | |||
656 | fn qux(bar: Bar, baz: Baz) { | ||
657 | f(); | ||
658 | g(); | ||
659 | h(); | ||
660 | j(); | ||
661 | } | ||
662 | ", | ||
663 | ); | ||
664 | |||
665 | check_assist( | ||
666 | expand_glob_import, | ||
667 | r" | ||
668 | mod foo { | ||
669 | pub mod bar { | ||
670 | pub struct Bar; | ||
671 | pub struct Baz; | ||
672 | pub struct Qux; | ||
673 | |||
674 | pub fn f() {} | ||
675 | } | ||
676 | |||
677 | pub mod baz { | ||
678 | pub fn g() {} | ||
679 | |||
680 | pub mod qux { | ||
681 | pub fn h() {} | ||
682 | pub fn m() {} | ||
683 | |||
684 | pub mod q { | ||
685 | pub fn j() {} | ||
686 | } | ||
687 | } | ||
688 | } | ||
689 | } | ||
690 | |||
691 | use foo::{ | ||
692 | bar::{*, f}, | ||
693 | baz::{g, qux::{q::j, *<|>}} | ||
694 | }; | ||
695 | |||
696 | fn qux(bar: Bar, baz: Baz) { | ||
697 | f(); | ||
698 | g(); | ||
699 | h(); | ||
700 | j(); | ||
701 | } | ||
702 | ", | ||
703 | r" | ||
704 | mod foo { | ||
705 | pub mod bar { | ||
706 | pub struct Bar; | ||
707 | pub struct Baz; | ||
708 | pub struct Qux; | ||
709 | |||
710 | pub fn f() {} | ||
711 | } | ||
712 | |||
713 | pub mod baz { | ||
714 | pub fn g() {} | ||
715 | |||
716 | pub mod qux { | ||
717 | pub fn h() {} | ||
718 | pub fn m() {} | ||
719 | |||
720 | pub mod q { | ||
721 | pub fn j() {} | ||
722 | } | ||
723 | } | ||
724 | } | ||
725 | } | ||
726 | |||
727 | use foo::{ | ||
728 | bar::{*, f}, | ||
729 | baz::{g, qux::{q::j, h}} | ||
730 | }; | ||
731 | |||
732 | fn qux(bar: Bar, baz: Baz) { | ||
733 | f(); | ||
734 | g(); | ||
735 | h(); | ||
736 | j(); | ||
737 | } | ||
738 | ", | ||
739 | ); | ||
306 | } | 740 | } |
307 | 741 | ||
308 | #[test] | 742 | #[test] |
309 | fn expanding_glob_import_with_macro_defs() { | 743 | fn expanding_glob_import_with_macro_defs() { |
744 | // FIXME: this is currently fails because `Definition::find_usages` ignores macros | ||
745 | // https://github.com/rust-analyzer/rust-analyzer/issues/3484 | ||
746 | // | ||
747 | // check_assist( | ||
748 | // expand_glob_import, | ||
749 | // r" | ||
750 | // //- /lib.rs crate:foo | ||
751 | // #[macro_export] | ||
752 | // macro_rules! bar { | ||
753 | // () => () | ||
754 | // } | ||
755 | |||
756 | // pub fn baz() {} | ||
757 | |||
758 | // //- /main.rs crate:main deps:foo | ||
759 | // use foo::*<|>; | ||
760 | |||
761 | // fn main() { | ||
762 | // bar!(); | ||
763 | // baz(); | ||
764 | // } | ||
765 | // ", | ||
766 | // r" | ||
767 | // use foo::{bar, baz}; | ||
768 | |||
769 | // fn main() { | ||
770 | // bar!(); | ||
771 | // baz(); | ||
772 | // } | ||
773 | // ", | ||
774 | // ) | ||
775 | } | ||
776 | |||
777 | #[test] | ||
778 | fn expanding_glob_import_with_trait_method_uses() { | ||
310 | check_assist( | 779 | check_assist( |
311 | expand_glob_import, | 780 | expand_glob_import, |
312 | r" | 781 | r" |
313 | //- /lib.rs crate:foo | 782 | //- /lib.rs crate:foo |
314 | #[macro_export] | 783 | pub trait Tr { |
315 | macro_rules! bar { | 784 | fn method(&self) {} |
316 | () => () | ||
317 | } | 785 | } |
318 | 786 | impl Tr for () {} | |
319 | pub fn baz() {} | ||
320 | 787 | ||
321 | //- /main.rs crate:main deps:foo | 788 | //- /main.rs crate:main deps:foo |
322 | use foo::*<|>; | 789 | use foo::*<|>; |
323 | 790 | ||
324 | fn main() { | 791 | fn main() { |
325 | bar!(); | 792 | ().method(); |
326 | baz(); | ||
327 | } | 793 | } |
328 | ", | 794 | ", |
329 | r" | 795 | r" |
330 | use foo::{bar, baz}; | 796 | use foo::Tr; |
331 | 797 | ||
332 | fn main() { | 798 | fn main() { |
333 | bar!(); | 799 | ().method(); |
334 | baz(); | ||
335 | } | 800 | } |
336 | ", | 801 | ", |
337 | ) | 802 | ); |
338 | } | ||
339 | 803 | ||
340 | #[test] | ||
341 | fn expanding_glob_import_with_trait_method_uses() { | ||
342 | check_assist( | 804 | check_assist( |
343 | expand_glob_import, | 805 | expand_glob_import, |
344 | r" | 806 | r" |
@@ -348,6 +810,11 @@ pub trait Tr { | |||
348 | } | 810 | } |
349 | impl Tr for () {} | 811 | impl Tr for () {} |
350 | 812 | ||
813 | pub trait Tr2 { | ||
814 | fn method2(&self) {} | ||
815 | } | ||
816 | impl Tr2 for () {} | ||
817 | |||
351 | //- /main.rs crate:main deps:foo | 818 | //- /main.rs crate:main deps:foo |
352 | use foo::*<|>; | 819 | use foo::*<|>; |
353 | 820 | ||
@@ -362,7 +829,42 @@ fn main() { | |||
362 | ().method(); | 829 | ().method(); |
363 | } | 830 | } |
364 | ", | 831 | ", |
365 | ) | 832 | ); |
833 | } | ||
834 | |||
835 | #[test] | ||
836 | fn expanding_is_not_applicable_if_target_module_is_not_accessible_from_current_scope() { | ||
837 | check_assist_not_applicable( | ||
838 | expand_glob_import, | ||
839 | r" | ||
840 | mod foo { | ||
841 | mod bar { | ||
842 | pub struct Bar; | ||
843 | } | ||
844 | } | ||
845 | |||
846 | use foo::bar::*<|>; | ||
847 | |||
848 | fn baz(bar: Bar) {} | ||
849 | ", | ||
850 | ); | ||
851 | |||
852 | check_assist_not_applicable( | ||
853 | expand_glob_import, | ||
854 | r" | ||
855 | mod foo { | ||
856 | mod bar { | ||
857 | pub mod baz { | ||
858 | pub struct Baz; | ||
859 | } | ||
860 | } | ||
861 | } | ||
862 | |||
863 | use foo::bar::baz::*<|>; | ||
864 | |||
865 | fn qux(baz: Baz) {} | ||
866 | ", | ||
867 | ); | ||
366 | } | 868 | } |
367 | 869 | ||
368 | #[test] | 870 | #[test] |
diff --git a/crates/assists/src/handlers/invert_if.rs b/crates/assists/src/handlers/invert_if.rs index f0e047538..294256297 100644 --- a/crates/assists/src/handlers/invert_if.rs +++ b/crates/assists/src/handlers/invert_if.rs | |||
@@ -106,4 +106,22 @@ mod tests { | |||
106 | "fn f() { i<|>f let Some(_) = Some(1) { 1 } else { 0 } }", | 106 | "fn f() { i<|>f let Some(_) = Some(1) { 1 } else { 0 } }", |
107 | ) | 107 | ) |
108 | } | 108 | } |
109 | |||
110 | #[test] | ||
111 | fn invert_if_option_case() { | ||
112 | check_assist( | ||
113 | invert_if, | ||
114 | "fn f() { if<|> doc_style.is_some() { Class::DocComment } else { Class::Comment } }", | ||
115 | "fn f() { if doc_style.is_none() { Class::Comment } else { Class::DocComment } }", | ||
116 | ) | ||
117 | } | ||
118 | |||
119 | #[test] | ||
120 | fn invert_if_result_case() { | ||
121 | check_assist( | ||
122 | invert_if, | ||
123 | "fn f() { i<|>f doc_style.is_err() { Class::Err } else { Class::Ok } }", | ||
124 | "fn f() { if doc_style.is_ok() { Class::Ok } else { Class::Err } }", | ||
125 | ) | ||
126 | } | ||
109 | } | 127 | } |
diff --git a/crates/assists/src/utils.rs b/crates/assists/src/utils.rs index d071d6502..e15c982e7 100644 --- a/crates/assists/src/utils.rs +++ b/crates/assists/src/utils.rs | |||
@@ -11,7 +11,7 @@ use syntax::{ | |||
11 | ast::{self, make, NameOwner}, | 11 | ast::{self, make, NameOwner}, |
12 | AstNode, Direction, | 12 | AstNode, Direction, |
13 | SyntaxKind::*, | 13 | SyntaxKind::*, |
14 | SyntaxNode, TextSize, T, | 14 | SyntaxNode, SyntaxText, TextSize, T, |
15 | }; | 15 | }; |
16 | 16 | ||
17 | use crate::assist_config::SnippetCap; | 17 | use crate::assist_config::SnippetCap; |
@@ -179,6 +179,25 @@ fn invert_special_case(expr: &ast::Expr) -> Option<ast::Expr> { | |||
179 | ast::BinOp::EqualityTest => bin.replace_op(T![!=]).map(|it| it.into()), | 179 | ast::BinOp::EqualityTest => bin.replace_op(T![!=]).map(|it| it.into()), |
180 | _ => None, | 180 | _ => None, |
181 | }, | 181 | }, |
182 | ast::Expr::MethodCallExpr(mce) => { | ||
183 | const IS_SOME_TEXT: &str = "is_some"; | ||
184 | const IS_NONE_TEXT: &str = "is_none"; | ||
185 | const IS_OK_TEXT: &str = "is_ok"; | ||
186 | const IS_ERR_TEXT: &str = "is_err"; | ||
187 | |||
188 | let name = mce.name_ref()?; | ||
189 | let name_text = name.text(); | ||
190 | |||
191 | let caller = || -> Option<SyntaxText> { Some(mce.receiver()?.syntax().text()) }; | ||
192 | |||
193 | match name_text { | ||
194 | x if x == IS_SOME_TEXT => make::expr_method_call(IS_NONE_TEXT, caller), | ||
195 | x if x == IS_NONE_TEXT => make::expr_method_call(IS_SOME_TEXT, caller), | ||
196 | x if x == IS_OK_TEXT => make::expr_method_call(IS_ERR_TEXT, caller), | ||
197 | x if x == IS_ERR_TEXT => make::expr_method_call(IS_OK_TEXT, caller), | ||
198 | _ => None, | ||
199 | } | ||
200 | } | ||
182 | ast::Expr::PrefixExpr(pe) if pe.op_kind()? == ast::PrefixOp::Not => pe.expr(), | 201 | ast::Expr::PrefixExpr(pe) if pe.op_kind()? == ast::PrefixOp::Not => pe.expr(), |
183 | // FIXME: | 202 | // FIXME: |
184 | // ast::Expr::Literal(true | false ) | 203 | // ast::Expr::Literal(true | false ) |
diff --git a/crates/base_db/Cargo.toml b/crates/base_db/Cargo.toml index 7347d7528..f7bfcb0d7 100644 --- a/crates/base_db/Cargo.toml +++ b/crates/base_db/Cargo.toml | |||
@@ -1,6 +1,7 @@ | |||
1 | [package] | 1 | [package] |
2 | name = "base_db" | 2 | name = "base_db" |
3 | version = "0.0.0" | 3 | version = "0.0.0" |
4 | description = "TBD" | ||
4 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
5 | authors = ["rust-analyzer developers"] | 6 | authors = ["rust-analyzer developers"] |
6 | edition = "2018" | 7 | edition = "2018" |
@@ -12,10 +13,10 @@ doctest = false | |||
12 | salsa = "0.15.2" | 13 | salsa = "0.15.2" |
13 | rustc-hash = "1.1.0" | 14 | rustc-hash = "1.1.0" |
14 | 15 | ||
15 | syntax = { path = "../syntax" } | 16 | syntax = { path = "../syntax", version = "0.0.0" } |
16 | cfg = { path = "../cfg" } | 17 | cfg = { path = "../cfg", version = "0.0.0" } |
17 | profile = { path = "../profile" } | 18 | profile = { path = "../profile", version = "0.0.0" } |
18 | tt = { path = "../tt" } | 19 | tt = { path = "../tt", version = "0.0.0" } |
19 | test_utils = { path = "../test_utils" } | 20 | test_utils = { path = "../test_utils", version = "0.0.0" } |
20 | vfs = { path = "../vfs" } | 21 | vfs = { path = "../vfs", version = "0.0.0" } |
21 | stdx = { path = "../stdx" } | 22 | stdx = { path = "../stdx", version = "0.0.0" } |
diff --git a/crates/cfg/Cargo.toml b/crates/cfg/Cargo.toml index d2ea551d1..a6785ee8e 100644 --- a/crates/cfg/Cargo.toml +++ b/crates/cfg/Cargo.toml | |||
@@ -1,6 +1,7 @@ | |||
1 | [package] | 1 | [package] |
2 | name = "cfg" | 2 | name = "cfg" |
3 | version = "0.0.0" | 3 | version = "0.0.0" |
4 | description = "TBD" | ||
4 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
5 | authors = ["rust-analyzer developers"] | 6 | authors = ["rust-analyzer developers"] |
6 | edition = "2018" | 7 | edition = "2018" |
@@ -11,7 +12,7 @@ doctest = false | |||
11 | [dependencies] | 12 | [dependencies] |
12 | rustc-hash = "1.1.0" | 13 | rustc-hash = "1.1.0" |
13 | 14 | ||
14 | tt = { path = "../tt" } | 15 | tt = { path = "../tt", version = "0.0.0" } |
15 | 16 | ||
16 | [dev-dependencies] | 17 | [dev-dependencies] |
17 | mbe = { path = "../mbe" } | 18 | mbe = { path = "../mbe" } |
diff --git a/crates/flycheck/Cargo.toml b/crates/flycheck/Cargo.toml index 262a66e4e..c230fc1e2 100644 --- a/crates/flycheck/Cargo.toml +++ b/crates/flycheck/Cargo.toml | |||
@@ -1,6 +1,7 @@ | |||
1 | [package] | 1 | [package] |
2 | name = "flycheck" | 2 | name = "flycheck" |
3 | version = "0.0.0" | 3 | version = "0.0.0" |
4 | description = "TBD" | ||
4 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
5 | authors = ["rust-analyzer developers"] | 6 | authors = ["rust-analyzer developers"] |
6 | edition = "2018" | 7 | edition = "2018" |
@@ -15,4 +16,4 @@ cargo_metadata = "0.11.1" | |||
15 | serde_json = "1.0.48" | 16 | serde_json = "1.0.48" |
16 | jod-thread = "0.1.1" | 17 | jod-thread = "0.1.1" |
17 | 18 | ||
18 | toolchain = { path = "../toolchain" } | 19 | toolchain = { path = "../toolchain", version = "0.0.0" } |
diff --git a/crates/hir/Cargo.toml b/crates/hir/Cargo.toml index d0ddca27f..72f941c46 100644 --- a/crates/hir/Cargo.toml +++ b/crates/hir/Cargo.toml | |||
@@ -1,6 +1,7 @@ | |||
1 | [package] | 1 | [package] |
2 | name = "hir" | 2 | name = "hir" |
3 | version = "0.0.0" | 3 | version = "0.0.0" |
4 | description = "TBD" | ||
4 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
5 | authors = ["rust-analyzer developers"] | 6 | authors = ["rust-analyzer developers"] |
6 | edition = "2018" | 7 | edition = "2018" |
@@ -16,11 +17,11 @@ arrayvec = "0.5.1" | |||
16 | itertools = "0.9.0" | 17 | itertools = "0.9.0" |
17 | url = "2.1.1" | 18 | url = "2.1.1" |
18 | 19 | ||
19 | stdx = { path = "../stdx" } | 20 | stdx = { path = "../stdx", version = "0.0.0" } |
20 | syntax = { path = "../syntax" } | 21 | syntax = { path = "../syntax", version = "0.0.0" } |
21 | base_db = { path = "../base_db" } | 22 | base_db = { path = "../base_db", version = "0.0.0" } |
22 | profile = { path = "../profile" } | 23 | profile = { path = "../profile", version = "0.0.0" } |
23 | hir_expand = { path = "../hir_expand" } | 24 | hir_expand = { path = "../hir_expand", version = "0.0.0" } |
24 | hir_def = { path = "../hir_def" } | 25 | hir_def = { path = "../hir_def", version = "0.0.0" } |
25 | hir_ty = { path = "../hir_ty" } | 26 | hir_ty = { path = "../hir_ty", version = "0.0.0" } |
26 | tt = { path = "../tt" } | 27 | tt = { path = "../tt", version = "0.0.0" } |
diff --git a/crates/hir_def/Cargo.toml b/crates/hir_def/Cargo.toml index 57745322f..011e4612c 100644 --- a/crates/hir_def/Cargo.toml +++ b/crates/hir_def/Cargo.toml | |||
@@ -1,6 +1,7 @@ | |||
1 | [package] | 1 | [package] |
2 | name = "hir_def" | 2 | name = "hir_def" |
3 | version = "0.0.0" | 3 | version = "0.0.0" |
4 | description = "TBD" | ||
4 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
5 | authors = ["rust-analyzer developers"] | 6 | authors = ["rust-analyzer developers"] |
6 | edition = "2018" | 7 | edition = "2018" |
@@ -20,16 +21,16 @@ itertools = "0.9.0" | |||
20 | indexmap = "1.4.0" | 21 | indexmap = "1.4.0" |
21 | smallvec = "1.4.0" | 22 | smallvec = "1.4.0" |
22 | 23 | ||
23 | stdx = { path = "../stdx" } | 24 | stdx = { path = "../stdx", version = "0.0.0" } |
24 | arena = { path = "../arena" } | 25 | arena = { path = "../arena", version = "0.0.0" } |
25 | base_db = { path = "../base_db" } | 26 | base_db = { path = "../base_db", version = "0.0.0" } |
26 | syntax = { path = "../syntax" } | 27 | syntax = { path = "../syntax", version = "0.0.0" } |
27 | profile = { path = "../profile" } | 28 | profile = { path = "../profile", version = "0.0.0" } |
28 | hir_expand = { path = "../hir_expand" } | 29 | hir_expand = { path = "../hir_expand", version = "0.0.0" } |
29 | test_utils = { path = "../test_utils" } | 30 | test_utils = { path = "../test_utils", version = "0.0.0" } |
30 | mbe = { path = "../mbe" } | 31 | mbe = { path = "../mbe", version = "0.0.0" } |
31 | cfg = { path = "../cfg" } | 32 | cfg = { path = "../cfg", version = "0.0.0" } |
32 | tt = { path = "../tt" } | 33 | tt = { path = "../tt", version = "0.0.0" } |
33 | 34 | ||
34 | [dev-dependencies] | 35 | [dev-dependencies] |
35 | expect-test = "0.1" | 36 | expect-test = "0.1" |
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index 391ab5d39..6a503d785 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs | |||
@@ -557,6 +557,10 @@ impl Ctx { | |||
557 | let statik = self.lower_static(&ast)?; | 557 | let statik = self.lower_static(&ast)?; |
558 | statik.into() | 558 | statik.into() |
559 | } | 559 | } |
560 | ast::ExternItem::TypeAlias(ty) => { | ||
561 | let id = self.lower_type_alias(&ty)?; | ||
562 | id.into() | ||
563 | } | ||
560 | ast::ExternItem::MacroCall(_) => return None, | 564 | ast::ExternItem::MacroCall(_) => return None, |
561 | }; | 565 | }; |
562 | self.add_attrs(id.into(), attrs); | 566 | self.add_attrs(id.into(), attrs); |
diff --git a/crates/hir_def/src/nameres/tests.rs b/crates/hir_def/src/nameres/tests.rs index 8aaf7a158..5ca30dac9 100644 --- a/crates/hir_def/src/nameres/tests.rs +++ b/crates/hir_def/src/nameres/tests.rs | |||
@@ -46,6 +46,7 @@ union U { to_be: bool, not_to_be: u8 } | |||
46 | enum E { V } | 46 | enum E { V } |
47 | 47 | ||
48 | extern { | 48 | extern { |
49 | type Ext; | ||
49 | static EXT: u8; | 50 | static EXT: u8; |
50 | fn ext(); | 51 | fn ext(); |
51 | } | 52 | } |
@@ -65,6 +66,7 @@ extern { | |||
65 | Baz: t v | 66 | Baz: t v |
66 | E: t | 67 | E: t |
67 | EXT: v | 68 | EXT: v |
69 | Ext: t | ||
68 | U: t | 70 | U: t |
69 | ext: v | 71 | ext: v |
70 | "#]], | 72 | "#]], |
diff --git a/crates/hir_expand/Cargo.toml b/crates/hir_expand/Cargo.toml index 1c4699291..9fad2ab94 100644 --- a/crates/hir_expand/Cargo.toml +++ b/crates/hir_expand/Cargo.toml | |||
@@ -1,6 +1,7 @@ | |||
1 | [package] | 1 | [package] |
2 | name = "hir_expand" | 2 | name = "hir_expand" |
3 | version = "0.0.0" | 3 | version = "0.0.0" |
4 | description = "TBD" | ||
4 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
5 | authors = ["rust-analyzer developers"] | 6 | authors = ["rust-analyzer developers"] |
6 | edition = "2018" | 7 | edition = "2018" |
@@ -13,11 +14,11 @@ log = "0.4.8" | |||
13 | either = "1.5.3" | 14 | either = "1.5.3" |
14 | rustc-hash = "1.0.0" | 15 | rustc-hash = "1.0.0" |
15 | 16 | ||
16 | arena = { path = "../arena" } | 17 | arena = { path = "../arena", version = "0.0.0" } |
17 | base_db = { path = "../base_db" } | 18 | base_db = { path = "../base_db", version = "0.0.0" } |
18 | syntax = { path = "../syntax" } | 19 | syntax = { path = "../syntax", version = "0.0.0" } |
19 | parser = { path = "../parser" } | 20 | parser = { path = "../parser", version = "0.0.0" } |
20 | profile = { path = "../profile" } | 21 | profile = { path = "../profile", version = "0.0.0" } |
21 | tt = { path = "../tt" } | 22 | tt = { path = "../tt", version = "0.0.0" } |
22 | mbe = { path = "../mbe" } | 23 | mbe = { path = "../mbe", version = "0.0.0" } |
23 | test_utils = { path = "../test_utils"} | 24 | test_utils = { path = "../test_utils", version = "0.0.0" } |
diff --git a/crates/hir_ty/Cargo.toml b/crates/hir_ty/Cargo.toml index 06da0d0ec..33e155a70 100644 --- a/crates/hir_ty/Cargo.toml +++ b/crates/hir_ty/Cargo.toml | |||
@@ -1,6 +1,7 @@ | |||
1 | [package] | 1 | [package] |
2 | name = "hir_ty" | 2 | name = "hir_ty" |
3 | version = "0.0.0" | 3 | version = "0.0.0" |
4 | description = "TBD" | ||
4 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
5 | authors = ["rust-analyzer developers"] | 6 | authors = ["rust-analyzer developers"] |
6 | edition = "2018" | 7 | edition = "2018" |
@@ -20,14 +21,14 @@ chalk-solve = { version = "0.23.0" } | |||
20 | chalk-ir = { version = "0.23.0" } | 21 | chalk-ir = { version = "0.23.0" } |
21 | chalk-recursive = { version = "0.23.0" } | 22 | chalk-recursive = { version = "0.23.0" } |
22 | 23 | ||
23 | stdx = { path = "../stdx" } | 24 | stdx = { path = "../stdx", version = "0.0.0" } |
24 | hir_def = { path = "../hir_def" } | 25 | hir_def = { path = "../hir_def", version = "0.0.0" } |
25 | hir_expand = { path = "../hir_expand" } | 26 | hir_expand = { path = "../hir_expand", version = "0.0.0" } |
26 | arena = { path = "../arena" } | 27 | arena = { path = "../arena", version = "0.0.0" } |
27 | base_db = { path = "../base_db" } | 28 | base_db = { path = "../base_db", version = "0.0.0" } |
28 | profile = { path = "../profile" } | 29 | profile = { path = "../profile", version = "0.0.0" } |
29 | syntax = { path = "../syntax" } | 30 | syntax = { path = "../syntax", version = "0.0.0" } |
30 | test_utils = { path = "../test_utils" } | 31 | test_utils = { path = "../test_utils", version = "0.0.0" } |
31 | 32 | ||
32 | [dev-dependencies] | 33 | [dev-dependencies] |
33 | expect-test = "0.1" | 34 | expect-test = "0.1" |
diff --git a/crates/ide/Cargo.toml b/crates/ide/Cargo.toml index 9ecf43e5a..e61c276df 100644 --- a/crates/ide/Cargo.toml +++ b/crates/ide/Cargo.toml | |||
@@ -1,6 +1,7 @@ | |||
1 | [package] | 1 | [package] |
2 | name = "ide" | 2 | name = "ide" |
3 | version = "0.0.0" | 3 | version = "0.0.0" |
4 | description = "TBD" | ||
4 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
5 | authors = ["rust-analyzer developers"] | 6 | authors = ["rust-analyzer developers"] |
6 | edition = "2018" | 7 | edition = "2018" |
@@ -18,20 +19,20 @@ oorandom = "11.1.2" | |||
18 | pulldown-cmark-to-cmark = "5.0.0" | 19 | pulldown-cmark-to-cmark = "5.0.0" |
19 | pulldown-cmark = {version = "0.7.2", default-features = false} | 20 | pulldown-cmark = {version = "0.7.2", default-features = false} |
20 | 21 | ||
21 | stdx = { path = "../stdx" } | 22 | stdx = { path = "../stdx", version = "0.0.0" } |
22 | syntax = { path = "../syntax" } | 23 | syntax = { path = "../syntax", version = "0.0.0" } |
23 | text_edit = { path = "../text_edit" } | 24 | text_edit = { path = "../text_edit", version = "0.0.0" } |
24 | base_db = { path = "../base_db" } | 25 | base_db = { path = "../base_db", version = "0.0.0" } |
25 | ide_db = { path = "../ide_db" } | 26 | ide_db = { path = "../ide_db", version = "0.0.0" } |
26 | cfg = { path = "../cfg" } | 27 | cfg = { path = "../cfg", version = "0.0.0" } |
27 | profile = { path = "../profile" } | 28 | profile = { path = "../profile", version = "0.0.0" } |
28 | test_utils = { path = "../test_utils" } | 29 | test_utils = { path = "../test_utils", version = "0.0.0" } |
29 | assists = { path = "../assists" } | 30 | assists = { path = "../assists", version = "0.0.0" } |
30 | ssr = { path = "../ssr" } | 31 | ssr = { path = "../ssr", version = "0.0.0" } |
31 | 32 | ||
32 | # ide should depend only on the top-level `hir` package. if you need | 33 | # ide should depend only on the top-level `hir` package. if you need |
33 | # something from some `hir_xxx` subpackage, reexport the API via `hir`. | 34 | # something from some `hir_xxx` subpackage, reexport the API via `hir`. |
34 | hir = { path = "../hir" } | 35 | hir = { path = "../hir", version = "0.0.0" } |
35 | 36 | ||
36 | [dev-dependencies] | 37 | [dev-dependencies] |
37 | expect-test = "0.1" | 38 | expect-test = "0.1" |
diff --git a/crates/ide/src/completion.rs b/crates/ide/src/completion.rs index 25e580d80..33bed6991 100644 --- a/crates/ide/src/completion.rs +++ b/crates/ide/src/completion.rs | |||
@@ -92,7 +92,7 @@ pub use crate::completion::{ | |||
92 | /// already present, it should give all possible variants for the identifier at | 92 | /// already present, it should give all possible variants for the identifier at |
93 | /// the caret. In other words, for | 93 | /// the caret. In other words, for |
94 | /// | 94 | /// |
95 | /// ```no-run | 95 | /// ```no_run |
96 | /// fn f() { | 96 | /// fn f() { |
97 | /// let foo = 92; | 97 | /// let foo = 92; |
98 | /// let _ = bar<|> | 98 | /// let _ = bar<|> |
diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs index 4139f329e..dd59d9e70 100644 --- a/crates/ide/src/runnables.rs +++ b/crates/ide/src/runnables.rs | |||
@@ -160,7 +160,7 @@ fn runnable_fn( | |||
160 | RunnableKind::Test { test_id, attr } | 160 | RunnableKind::Test { test_id, attr } |
161 | } else if fn_def.has_atom_attr("bench") { | 161 | } else if fn_def.has_atom_attr("bench") { |
162 | RunnableKind::Bench { test_id } | 162 | RunnableKind::Bench { test_id } |
163 | } else if has_doc_test(&fn_def) { | 163 | } else if has_runnable_doc_test(&fn_def) { |
164 | RunnableKind::DocTest { test_id } | 164 | RunnableKind::DocTest { test_id } |
165 | } else { | 165 | } else { |
166 | return None; | 166 | return None; |
@@ -211,8 +211,13 @@ fn has_test_related_attribute(fn_def: &ast::Fn) -> bool { | |||
211 | .any(|attribute_text| attribute_text.contains("test")) | 211 | .any(|attribute_text| attribute_text.contains("test")) |
212 | } | 212 | } |
213 | 213 | ||
214 | fn has_doc_test(fn_def: &ast::Fn) -> bool { | 214 | fn has_runnable_doc_test(fn_def: &ast::Fn) -> bool { |
215 | fn_def.doc_comment_text().map_or(false, |comment| comment.contains("```")) | 215 | fn_def.doc_comment_text().map_or(false, |comments_text| { |
216 | comments_text.contains("```") | ||
217 | && !comments_text.contains("```ignore") | ||
218 | && !comments_text.contains("```no_run") | ||
219 | && !comments_text.contains("```compile_fail") | ||
220 | }) | ||
216 | } | 221 | } |
217 | 222 | ||
218 | fn runnable_mod( | 223 | fn runnable_mod( |
@@ -417,6 +422,21 @@ fn main() {} | |||
417 | /// let x = 5; | 422 | /// let x = 5; |
418 | /// ``` | 423 | /// ``` |
419 | fn foo() {} | 424 | fn foo() {} |
425 | |||
426 | /// ```no_run | ||
427 | /// let z = 55; | ||
428 | /// ``` | ||
429 | fn should_have_no_runnable() {} | ||
430 | |||
431 | /// ```ignore | ||
432 | /// let z = 55; | ||
433 | /// ``` | ||
434 | fn should_have_no_runnable_2() {} | ||
435 | |||
436 | /// ```compile_fail | ||
437 | /// let z = 55; | ||
438 | /// ``` | ||
439 | fn should_have_no_runnable_3() {} | ||
420 | "#, | 440 | "#, |
421 | &[&BIN, &DOCTEST], | 441 | &[&BIN, &DOCTEST], |
422 | expect![[r#" | 442 | expect![[r#" |
diff --git a/crates/ide_db/Cargo.toml b/crates/ide_db/Cargo.toml index 692fb6415..320fb15e5 100644 --- a/crates/ide_db/Cargo.toml +++ b/crates/ide_db/Cargo.toml | |||
@@ -1,6 +1,7 @@ | |||
1 | [package] | 1 | [package] |
2 | name = "ide_db" | 2 | name = "ide_db" |
3 | version = "0.0.0" | 3 | version = "0.0.0" |
4 | description = "TBD" | ||
4 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
5 | authors = ["rust-analyzer developers"] | 6 | authors = ["rust-analyzer developers"] |
6 | edition = "2018" | 7 | edition = "2018" |
@@ -19,12 +20,12 @@ rustc-hash = "1.1.0" | |||
19 | once_cell = "1.3.1" | 20 | once_cell = "1.3.1" |
20 | either = "1.5.3" | 21 | either = "1.5.3" |
21 | 22 | ||
22 | stdx = { path = "../stdx" } | 23 | stdx = { path = "../stdx", version = "0.0.0" } |
23 | syntax = { path = "../syntax" } | 24 | syntax = { path = "../syntax", version = "0.0.0" } |
24 | text_edit = { path = "../text_edit" } | 25 | text_edit = { path = "../text_edit", version = "0.0.0" } |
25 | base_db = { path = "../base_db" } | 26 | base_db = { path = "../base_db", version = "0.0.0" } |
26 | profile = { path = "../profile" } | 27 | profile = { path = "../profile", version = "0.0.0" } |
27 | test_utils = { path = "../test_utils" } | 28 | test_utils = { path = "../test_utils", version = "0.0.0" } |
28 | # ide should depend only on the top-level `hir` package. if you need | 29 | # ide should depend only on the top-level `hir` package. if you need |
29 | # something from some `hir_xxx` subpackage, reexport the API via `hir`. | 30 | # something from some `hir_xxx` subpackage, reexport the API via `hir`. |
30 | hir = { path = "../hir" } | 31 | hir = { path = "../hir", version = "0.0.0" } |
diff --git a/crates/mbe/Cargo.toml b/crates/mbe/Cargo.toml index 1aba8b7c4..af80e2be3 100644 --- a/crates/mbe/Cargo.toml +++ b/crates/mbe/Cargo.toml | |||
@@ -1,6 +1,7 @@ | |||
1 | [package] | 1 | [package] |
2 | name = "mbe" | 2 | name = "mbe" |
3 | version = "0.0.0" | 3 | version = "0.0.0" |
4 | description = "TBD" | ||
4 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
5 | authors = ["rust-analyzer developers"] | 6 | authors = ["rust-analyzer developers"] |
6 | edition = "2018" | 7 | edition = "2018" |
@@ -13,9 +14,9 @@ rustc-hash = "1.1.0" | |||
13 | smallvec = "1.2.0" | 14 | smallvec = "1.2.0" |
14 | log = "0.4.8" | 15 | log = "0.4.8" |
15 | 16 | ||
16 | syntax = { path = "../syntax" } | 17 | syntax = { path = "../syntax", version = "0.0.0" } |
17 | parser = { path = "../parser" } | 18 | parser = { path = "../parser", version = "0.0.0" } |
18 | tt = { path = "../tt" } | 19 | tt = { path = "../tt", version = "0.0.0" } |
19 | 20 | ||
20 | [dev-dependencies] | 21 | [dev-dependencies] |
21 | test_utils = { path = "../test_utils" } | 22 | test_utils = { path = "../test_utils" } |
diff --git a/crates/parser/Cargo.toml b/crates/parser/Cargo.toml index 358be92d1..1610e0d23 100644 --- a/crates/parser/Cargo.toml +++ b/crates/parser/Cargo.toml | |||
@@ -1,6 +1,7 @@ | |||
1 | [package] | 1 | [package] |
2 | name = "parser" | 2 | name = "parser" |
3 | version = "0.0.0" | 3 | version = "0.0.0" |
4 | description = "TBD" | ||
4 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
5 | authors = ["rust-analyzer developers"] | 6 | authors = ["rust-analyzer developers"] |
6 | edition = "2018" | 7 | edition = "2018" |
diff --git a/crates/paths/Cargo.toml b/crates/paths/Cargo.toml index 5ac18d63b..da26938c1 100644 --- a/crates/paths/Cargo.toml +++ b/crates/paths/Cargo.toml | |||
@@ -1,6 +1,7 @@ | |||
1 | [package] | 1 | [package] |
2 | name = "paths" | 2 | name = "paths" |
3 | version = "0.0.0" | 3 | version = "0.0.0" |
4 | description = "TBD" | ||
4 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
5 | authors = ["rust-analyzer developers"] | 6 | authors = ["rust-analyzer developers"] |
6 | edition = "2018" | 7 | edition = "2018" |
diff --git a/crates/proc_macro_api/Cargo.toml b/crates/proc_macro_api/Cargo.toml index a3a4c1103..75f67a22e 100644 --- a/crates/proc_macro_api/Cargo.toml +++ b/crates/proc_macro_api/Cargo.toml | |||
@@ -1,6 +1,7 @@ | |||
1 | [package] | 1 | [package] |
2 | name = "proc_macro_api" | 2 | name = "proc_macro_api" |
3 | version = "0.0.0" | 3 | version = "0.0.0" |
4 | description = "TBD" | ||
4 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
5 | authors = ["rust-analyzer developers"] | 6 | authors = ["rust-analyzer developers"] |
6 | edition = "2018" | 7 | edition = "2018" |
@@ -15,4 +16,4 @@ log = "0.4.8" | |||
15 | crossbeam-channel = "0.4.0" | 16 | crossbeam-channel = "0.4.0" |
16 | jod-thread = "0.1.1" | 17 | jod-thread = "0.1.1" |
17 | 18 | ||
18 | tt = { path = "../tt" } | 19 | tt = { path = "../tt", version = "0.0.0" } |
diff --git a/crates/proc_macro_srv/Cargo.toml b/crates/proc_macro_srv/Cargo.toml index a468b5560..fb84e04ae 100644 --- a/crates/proc_macro_srv/Cargo.toml +++ b/crates/proc_macro_srv/Cargo.toml | |||
@@ -1,6 +1,7 @@ | |||
1 | [package] | 1 | [package] |
2 | name = "proc_macro_srv" | 2 | name = "proc_macro_srv" |
3 | version = "0.0.0" | 3 | version = "0.0.0" |
4 | description = "TBD" | ||
4 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
5 | authors = ["rust-analyzer developers"] | 6 | authors = ["rust-analyzer developers"] |
6 | edition = "2018" | 7 | edition = "2018" |
@@ -13,10 +14,10 @@ goblin = "0.2.1" | |||
13 | libloading = "0.6.0" | 14 | libloading = "0.6.0" |
14 | memmap = "0.7" | 15 | memmap = "0.7" |
15 | 16 | ||
16 | tt = { path = "../tt" } | 17 | tt = { path = "../tt", version = "0.0.0" } |
17 | mbe = { path = "../mbe" } | 18 | mbe = { path = "../mbe", version = "0.0.0" } |
18 | proc_macro_api = { path = "../proc_macro_api" } | 19 | proc_macro_api = { path = "../proc_macro_api", version = "0.0.0" } |
19 | test_utils = { path = "../test_utils" } | 20 | test_utils = { path = "../test_utils", version = "0.0.0" } |
20 | 21 | ||
21 | [dev-dependencies] | 22 | [dev-dependencies] |
22 | cargo_metadata = "0.11.1" | 23 | cargo_metadata = "0.11.1" |
diff --git a/crates/proc_macro_test/Cargo.toml b/crates/proc_macro_test/Cargo.toml index 7b0f64f31..753443be2 100644 --- a/crates/proc_macro_test/Cargo.toml +++ b/crates/proc_macro_test/Cargo.toml | |||
@@ -4,6 +4,7 @@ version = "0.0.0" | |||
4 | license = "MIT OR Apache-2.0" | 4 | license = "MIT OR Apache-2.0" |
5 | authors = ["rust-analyzer developers"] | 5 | authors = ["rust-analyzer developers"] |
6 | edition = "2018" | 6 | edition = "2018" |
7 | publish = false | ||
7 | 8 | ||
8 | [lib] | 9 | [lib] |
9 | doctest = false | 10 | doctest = false |
diff --git a/crates/profile/Cargo.toml b/crates/profile/Cargo.toml index e271e3a56..261172d61 100644 --- a/crates/profile/Cargo.toml +++ b/crates/profile/Cargo.toml | |||
@@ -1,6 +1,7 @@ | |||
1 | [package] | 1 | [package] |
2 | name = "profile" | 2 | name = "profile" |
3 | version = "0.0.0" | 3 | version = "0.0.0" |
4 | description = "TBD" | ||
4 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
5 | authors = ["rust-analyzer developers"] | 6 | authors = ["rust-analyzer developers"] |
6 | edition = "2018" | 7 | edition = "2018" |
@@ -14,7 +15,7 @@ cfg-if = "0.1.10" | |||
14 | libc = "0.2.73" | 15 | libc = "0.2.73" |
15 | backtrace = { version = "0.3.44", optional = true } | 16 | backtrace = { version = "0.3.44", optional = true } |
16 | 17 | ||
17 | arena = { path = "../arena" } | 18 | arena = { path = "../arena", version = "0.0.0" } |
18 | 19 | ||
19 | [target.'cfg(target_os = "linux")'.dependencies] | 20 | [target.'cfg(target_os = "linux")'.dependencies] |
20 | perf-event = "0.4" | 21 | perf-event = "0.4" |
diff --git a/crates/project_model/Cargo.toml b/crates/project_model/Cargo.toml index 386f72f41..8bee398d9 100644 --- a/crates/project_model/Cargo.toml +++ b/crates/project_model/Cargo.toml | |||
@@ -1,6 +1,7 @@ | |||
1 | [package] | 1 | [package] |
2 | name = "project_model" | 2 | name = "project_model" |
3 | version = "0.0.0" | 3 | version = "0.0.0" |
4 | description = "TBD" | ||
4 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
5 | authors = ["rust-analyzer developers"] | 6 | authors = ["rust-analyzer developers"] |
6 | edition = "2018" | 7 | edition = "2018" |
@@ -16,10 +17,10 @@ serde = { version = "1.0.106", features = ["derive"] } | |||
16 | serde_json = "1.0.48" | 17 | serde_json = "1.0.48" |
17 | anyhow = "1.0.26" | 18 | anyhow = "1.0.26" |
18 | 19 | ||
19 | arena = { path = "../arena" } | 20 | arena = { path = "../arena", version = "0.0.0" } |
20 | cfg = { path = "../cfg" } | 21 | cfg = { path = "../cfg", version = "0.0.0" } |
21 | base_db = { path = "../base_db" } | 22 | base_db = { path = "../base_db", version = "0.0.0" } |
22 | toolchain = { path = "../toolchain" } | 23 | toolchain = { path = "../toolchain", version = "0.0.0" } |
23 | proc_macro_api = { path = "../proc_macro_api" } | 24 | proc_macro_api = { path = "../proc_macro_api", version = "0.0.0" } |
24 | paths = { path = "../paths" } | 25 | paths = { path = "../paths", version = "0.0.0" } |
25 | stdx = { path = "../stdx" } | 26 | stdx = { path = "../stdx", version = "0.0.0" } |
diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml index 068a961dc..044686a99 100644 --- a/crates/rust-analyzer/Cargo.toml +++ b/crates/rust-analyzer/Cargo.toml | |||
@@ -1,6 +1,7 @@ | |||
1 | [package] | 1 | [package] |
2 | name = "rust-analyzer" | 2 | name = "rust-analyzer" |
3 | version = "0.0.0" | 3 | version = "0.0.0" |
4 | description = "TBD" | ||
4 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
5 | authors = ["rust-analyzer developers"] | 6 | authors = ["rust-analyzer developers"] |
6 | autobins = false | 7 | autobins = false |
@@ -32,26 +33,26 @@ rayon = "1.3.1" | |||
32 | mimalloc = { version = "0.1.19", default-features = false, optional = true } | 33 | mimalloc = { version = "0.1.19", default-features = false, optional = true } |
33 | lsp-server = "0.3.3" | 34 | lsp-server = "0.3.3" |
34 | 35 | ||
35 | stdx = { path = "../stdx" } | 36 | stdx = { path = "../stdx", version = "0.0.0" } |
36 | flycheck = { path = "../flycheck" } | 37 | flycheck = { path = "../flycheck", version = "0.0.0" } |
37 | ide = { path = "../ide" } | 38 | ide = { path = "../ide", version = "0.0.0" } |
38 | profile = { path = "../profile" } | 39 | profile = { path = "../profile", version = "0.0.0" } |
39 | project_model = { path = "../project_model" } | 40 | project_model = { path = "../project_model", version = "0.0.0" } |
40 | syntax = { path = "../syntax" } | 41 | syntax = { path = "../syntax", version = "0.0.0" } |
41 | text_edit = { path = "../text_edit" } | 42 | text_edit = { path = "../text_edit", version = "0.0.0" } |
42 | vfs = { path = "../vfs" } | 43 | vfs = { path = "../vfs", version = "0.0.0" } |
43 | vfs-notify = { path = "../vfs-notify" } | 44 | vfs-notify = { path = "../vfs-notify", version = "0.0.0" } |
44 | cfg = { path = "../cfg" } | 45 | cfg = { path = "../cfg", version = "0.0.0" } |
45 | toolchain = { path = "../toolchain" } | 46 | toolchain = { path = "../toolchain", version = "0.0.0" } |
46 | 47 | ||
47 | # This should only be used in CLI | 48 | # This should only be used in CLI |
48 | base_db = { path = "../base_db" } | 49 | base_db = { path = "../base_db", version = "0.0.0" } |
49 | ide_db = { path = "../ide_db" } | 50 | ide_db = { path = "../ide_db", version = "0.0.0" } |
50 | ssr = { path = "../ssr" } | 51 | ssr = { path = "../ssr", version = "0.0.0" } |
51 | hir = { path = "../hir" } | 52 | hir = { path = "../hir", version = "0.0.0" } |
52 | hir_def = { path = "../hir_def" } | 53 | hir_def = { path = "../hir_def", version = "0.0.0" } |
53 | hir_ty = { path = "../hir_ty" } | 54 | hir_ty = { path = "../hir_ty", version = "0.0.0" } |
54 | proc_macro_srv = { path = "../proc_macro_srv" } | 55 | proc_macro_srv = { path = "../proc_macro_srv", version = "0.0.0" } |
55 | 56 | ||
56 | [target.'cfg(windows)'.dependencies] | 57 | [target.'cfg(windows)'.dependencies] |
57 | winapi = "0.3.8" | 58 | winapi = "0.3.8" |
diff --git a/crates/ssr/Cargo.toml b/crates/ssr/Cargo.toml index 22b6af0fa..6f0f53d70 100644 --- a/crates/ssr/Cargo.toml +++ b/crates/ssr/Cargo.toml | |||
@@ -14,12 +14,12 @@ doctest = false | |||
14 | rustc-hash = "1.1.0" | 14 | rustc-hash = "1.1.0" |
15 | itertools = "0.9.0" | 15 | itertools = "0.9.0" |
16 | 16 | ||
17 | text_edit = { path = "../text_edit" } | 17 | text_edit = { path = "../text_edit", version = "0.0.0" } |
18 | syntax = { path = "../syntax" } | 18 | syntax = { path = "../syntax", version = "0.0.0" } |
19 | base_db = { path = "../base_db" } | 19 | base_db = { path = "../base_db", version = "0.0.0" } |
20 | ide_db = { path = "../ide_db" } | 20 | ide_db = { path = "../ide_db", version = "0.0.0" } |
21 | hir = { path = "../hir" } | 21 | hir = { path = "../hir", version = "0.0.0" } |
22 | test_utils = { path = "../test_utils" } | 22 | test_utils = { path = "../test_utils", version = "0.0.0" } |
23 | 23 | ||
24 | [dev-dependencies] | 24 | [dev-dependencies] |
25 | expect-test = "0.1" | 25 | expect-test = "0.1" |
diff --git a/crates/stdx/Cargo.toml b/crates/stdx/Cargo.toml index b186b46f2..8d7a51156 100644 --- a/crates/stdx/Cargo.toml +++ b/crates/stdx/Cargo.toml | |||
@@ -1,6 +1,7 @@ | |||
1 | [package] | 1 | [package] |
2 | name = "stdx" | 2 | name = "stdx" |
3 | version = "0.0.0" | 3 | version = "0.0.0" |
4 | description = "TBD" | ||
4 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
5 | authors = ["rust-analyzer developers"] | 6 | authors = ["rust-analyzer developers"] |
6 | edition = "2018" | 7 | edition = "2018" |
diff --git a/crates/syntax/Cargo.toml b/crates/syntax/Cargo.toml index 6818f3ad8..2c1bdb295 100644 --- a/crates/syntax/Cargo.toml +++ b/crates/syntax/Cargo.toml | |||
@@ -23,9 +23,9 @@ once_cell = "1.3.1" | |||
23 | smol_str = { version = "0.1.15", features = ["serde"] } | 23 | smol_str = { version = "0.1.15", features = ["serde"] } |
24 | serde = { version = "1.0.106", features = ["derive"] } | 24 | serde = { version = "1.0.106", features = ["derive"] } |
25 | 25 | ||
26 | stdx = { path = "../stdx" } | 26 | stdx = { path = "../stdx", version = "0.0.0" } |
27 | text_edit = { path = "../text_edit" } | 27 | text_edit = { path = "../text_edit", version = "0.0.0" } |
28 | parser = { path = "../parser" } | 28 | parser = { path = "../parser", version = "0.0.0" } |
29 | 29 | ||
30 | [dev-dependencies] | 30 | [dev-dependencies] |
31 | walkdir = "2.3.1" | 31 | walkdir = "2.3.1" |
diff --git a/crates/syntax/src/algo.rs b/crates/syntax/src/algo.rs index 6254b38ba..ea199f9b8 100644 --- a/crates/syntax/src/algo.rs +++ b/crates/syntax/src/algo.rs | |||
@@ -32,7 +32,7 @@ pub fn ancestors_at_offset( | |||
32 | /// imprecise: if the cursor is strictly between two nodes of the desired type, | 32 | /// imprecise: if the cursor is strictly between two nodes of the desired type, |
33 | /// as in | 33 | /// as in |
34 | /// | 34 | /// |
35 | /// ```no-run | 35 | /// ```no_run |
36 | /// struct Foo {}|struct Bar; | 36 | /// struct Foo {}|struct Bar; |
37 | /// ``` | 37 | /// ``` |
38 | /// | 38 | /// |
diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs index 6317407c6..d6af5755c 100644 --- a/crates/syntax/src/ast/generated/nodes.rs +++ b/crates/syntax/src/ast/generated/nodes.rs | |||
@@ -1380,6 +1380,7 @@ pub enum ExternItem { | |||
1380 | Fn(Fn), | 1380 | Fn(Fn), |
1381 | MacroCall(MacroCall), | 1381 | MacroCall(MacroCall), |
1382 | Static(Static), | 1382 | Static(Static), |
1383 | TypeAlias(TypeAlias), | ||
1383 | } | 1384 | } |
1384 | impl ast::AttrsOwner for ExternItem {} | 1385 | impl ast::AttrsOwner for ExternItem {} |
1385 | impl ast::NameOwner for ExternItem {} | 1386 | impl ast::NameOwner for ExternItem {} |
@@ -3339,10 +3340,13 @@ impl From<MacroCall> for ExternItem { | |||
3339 | impl From<Static> for ExternItem { | 3340 | impl From<Static> for ExternItem { |
3340 | fn from(node: Static) -> ExternItem { ExternItem::Static(node) } | 3341 | fn from(node: Static) -> ExternItem { ExternItem::Static(node) } |
3341 | } | 3342 | } |
3343 | impl From<TypeAlias> for ExternItem { | ||
3344 | fn from(node: TypeAlias) -> ExternItem { ExternItem::TypeAlias(node) } | ||
3345 | } | ||
3342 | impl AstNode for ExternItem { | 3346 | impl AstNode for ExternItem { |
3343 | fn can_cast(kind: SyntaxKind) -> bool { | 3347 | fn can_cast(kind: SyntaxKind) -> bool { |
3344 | match kind { | 3348 | match kind { |
3345 | FN | MACRO_CALL | STATIC => true, | 3349 | FN | MACRO_CALL | STATIC | TYPE_ALIAS => true, |
3346 | _ => false, | 3350 | _ => false, |
3347 | } | 3351 | } |
3348 | } | 3352 | } |
@@ -3351,6 +3355,7 @@ impl AstNode for ExternItem { | |||
3351 | FN => ExternItem::Fn(Fn { syntax }), | 3355 | FN => ExternItem::Fn(Fn { syntax }), |
3352 | MACRO_CALL => ExternItem::MacroCall(MacroCall { syntax }), | 3356 | MACRO_CALL => ExternItem::MacroCall(MacroCall { syntax }), |
3353 | STATIC => ExternItem::Static(Static { syntax }), | 3357 | STATIC => ExternItem::Static(Static { syntax }), |
3358 | TYPE_ALIAS => ExternItem::TypeAlias(TypeAlias { syntax }), | ||
3354 | _ => return None, | 3359 | _ => return None, |
3355 | }; | 3360 | }; |
3356 | Some(res) | 3361 | Some(res) |
@@ -3360,6 +3365,7 @@ impl AstNode for ExternItem { | |||
3360 | ExternItem::Fn(it) => &it.syntax, | 3365 | ExternItem::Fn(it) => &it.syntax, |
3361 | ExternItem::MacroCall(it) => &it.syntax, | 3366 | ExternItem::MacroCall(it) => &it.syntax, |
3362 | ExternItem::Static(it) => &it.syntax, | 3367 | ExternItem::Static(it) => &it.syntax, |
3368 | ExternItem::TypeAlias(it) => &it.syntax, | ||
3363 | } | 3369 | } |
3364 | } | 3370 | } |
3365 | } | 3371 | } |
diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs index d20c085aa..7958721e2 100644 --- a/crates/syntax/src/ast/make.rs +++ b/crates/syntax/src/ast/make.rs | |||
@@ -7,7 +7,7 @@ | |||
7 | use itertools::Itertools; | 7 | use itertools::Itertools; |
8 | use stdx::format_to; | 8 | use stdx::format_to; |
9 | 9 | ||
10 | use crate::{ast, AstNode, SourceFile, SyntaxKind, SyntaxNode, SyntaxToken}; | 10 | use crate::{ast, AstNode, SourceFile, SyntaxKind, SyntaxNode, SyntaxText, SyntaxToken}; |
11 | 11 | ||
12 | pub fn name(text: &str) -> ast::Name { | 12 | pub fn name(text: &str) -> ast::Name { |
13 | ast_from_text(&format!("mod {};", text)) | 13 | ast_from_text(&format!("mod {};", text)) |
@@ -137,6 +137,12 @@ pub fn expr_prefix(op: SyntaxKind, expr: ast::Expr) -> ast::Expr { | |||
137 | pub fn expr_call(f: ast::Expr, arg_list: ast::ArgList) -> ast::Expr { | 137 | pub fn expr_call(f: ast::Expr, arg_list: ast::ArgList) -> ast::Expr { |
138 | expr_from_text(&format!("{}{}", f, arg_list)) | 138 | expr_from_text(&format!("{}{}", f, arg_list)) |
139 | } | 139 | } |
140 | pub fn expr_method_call<F>(text: &str, caller: F) -> Option<ast::Expr> | ||
141 | where | ||
142 | F: FnOnce() -> Option<SyntaxText>, | ||
143 | { | ||
144 | try_expr_from_text(&format!("{}.{}()", caller()?, text)) | ||
145 | } | ||
140 | fn expr_from_text(text: &str) -> ast::Expr { | 146 | fn expr_from_text(text: &str) -> ast::Expr { |
141 | ast_from_text(&format!("const C: () = {};", text)) | 147 | ast_from_text(&format!("const C: () = {};", text)) |
142 | } | 148 | } |
diff --git a/crates/test_utils/Cargo.toml b/crates/test_utils/Cargo.toml index 45e5fb97f..93eecc678 100644 --- a/crates/test_utils/Cargo.toml +++ b/crates/test_utils/Cargo.toml | |||
@@ -1,6 +1,7 @@ | |||
1 | [package] | 1 | [package] |
2 | name = "test_utils" | 2 | name = "test_utils" |
3 | version = "0.0.0" | 3 | version = "0.0.0" |
4 | description = "TBD" | ||
4 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
5 | authors = ["rust-analyzer developers"] | 6 | authors = ["rust-analyzer developers"] |
6 | edition = "2018" | 7 | edition = "2018" |
@@ -15,4 +16,4 @@ text-size = "1.0.0" | |||
15 | serde_json = "1.0.48" | 16 | serde_json = "1.0.48" |
16 | rustc-hash = "1.1.0" | 17 | rustc-hash = "1.1.0" |
17 | 18 | ||
18 | stdx = { path = "../stdx" } | 19 | stdx = { path = "../stdx", version = "0.0.0" } |
diff --git a/crates/text_edit/Cargo.toml b/crates/text_edit/Cargo.toml index a69b1ef2b..8aadc1875 100644 --- a/crates/text_edit/Cargo.toml +++ b/crates/text_edit/Cargo.toml | |||
@@ -1,6 +1,7 @@ | |||
1 | [package] | 1 | [package] |
2 | name = "text_edit" | 2 | name = "text_edit" |
3 | version = "0.0.0" | 3 | version = "0.0.0" |
4 | description = "TBD" | ||
4 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
5 | authors = ["rust-analyzer developers"] | 6 | authors = ["rust-analyzer developers"] |
6 | edition = "2018" | 7 | edition = "2018" |
diff --git a/crates/toolchain/Cargo.toml b/crates/toolchain/Cargo.toml index 4856668f8..dcf0bfca0 100644 --- a/crates/toolchain/Cargo.toml +++ b/crates/toolchain/Cargo.toml | |||
@@ -1,6 +1,7 @@ | |||
1 | [package] | 1 | [package] |
2 | name = "toolchain" | 2 | name = "toolchain" |
3 | version = "0.0.0" | 3 | version = "0.0.0" |
4 | description = "TBD" | ||
4 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
5 | authors = ["rust-analyzer developers"] | 6 | authors = ["rust-analyzer developers"] |
6 | edition = "2018" | 7 | edition = "2018" |
diff --git a/crates/tt/Cargo.toml b/crates/tt/Cargo.toml index dfcdcf03e..5b8972ea3 100644 --- a/crates/tt/Cargo.toml +++ b/crates/tt/Cargo.toml | |||
@@ -1,6 +1,7 @@ | |||
1 | [package] | 1 | [package] |
2 | name = "tt" | 2 | name = "tt" |
3 | version = "0.0.0" | 3 | version = "0.0.0" |
4 | description = "TBD" | ||
4 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
5 | authors = ["rust-analyzer developers"] | 6 | authors = ["rust-analyzer developers"] |
6 | edition = "2018" | 7 | edition = "2018" |
@@ -13,4 +14,4 @@ doctest = false | |||
13 | # to reduce number of compilations | 14 | # to reduce number of compilations |
14 | smol_str = { version = "0.1.15", features = ["serde"] } | 15 | smol_str = { version = "0.1.15", features = ["serde"] } |
15 | 16 | ||
16 | stdx = { path = "../stdx" } | 17 | stdx = { path = "../stdx", version = "0.0.0" } |
diff --git a/crates/vfs-notify/Cargo.toml b/crates/vfs-notify/Cargo.toml index c1e53f4b1..54b51faab 100644 --- a/crates/vfs-notify/Cargo.toml +++ b/crates/vfs-notify/Cargo.toml | |||
@@ -1,6 +1,7 @@ | |||
1 | [package] | 1 | [package] |
2 | name = "vfs-notify" | 2 | name = "vfs-notify" |
3 | version = "0.0.0" | 3 | version = "0.0.0" |
4 | description = "TBD" | ||
4 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
5 | authors = ["rust-analyzer developers"] | 6 | authors = ["rust-analyzer developers"] |
6 | edition = "2018" | 7 | edition = "2018" |
@@ -16,5 +17,5 @@ walkdir = "2.3.1" | |||
16 | crossbeam-channel = "0.4.0" | 17 | crossbeam-channel = "0.4.0" |
17 | notify = "5.0.0-pre.3" | 18 | notify = "5.0.0-pre.3" |
18 | 19 | ||
19 | vfs = { path = "../vfs" } | 20 | vfs = { path = "../vfs", version = "0.0.0" } |
20 | paths = { path = "../paths" } | 21 | paths = { path = "../paths", version = "0.0.0" } |
diff --git a/crates/vfs/Cargo.toml b/crates/vfs/Cargo.toml index 9ae8f19b6..c318a68f7 100644 --- a/crates/vfs/Cargo.toml +++ b/crates/vfs/Cargo.toml | |||
@@ -1,6 +1,7 @@ | |||
1 | [package] | 1 | [package] |
2 | name = "vfs" | 2 | name = "vfs" |
3 | version = "0.0.0" | 3 | version = "0.0.0" |
4 | description = "TBD" | ||
4 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
5 | authors = ["rust-analyzer developers"] | 6 | authors = ["rust-analyzer developers"] |
6 | edition = "2018" | 7 | edition = "2018" |
@@ -12,4 +13,4 @@ doctest = false | |||
12 | rustc-hash = "1.0" | 13 | rustc-hash = "1.0" |
13 | fst = "0.4" | 14 | fst = "0.4" |
14 | 15 | ||
15 | paths = { path = "../paths" } | 16 | paths = { path = "../paths", version = "0.0.0" } |
diff --git a/docs/dev/style.md b/docs/dev/style.md index 44f0956c2..bb99c4855 100644 --- a/docs/dev/style.md +++ b/docs/dev/style.md | |||
@@ -181,6 +181,30 @@ fn frobnicate(walrus: Option<Walrus>) { | |||
181 | } | 181 | } |
182 | ``` | 182 | ``` |
183 | 183 | ||
184 | # Early Returns | ||
185 | |||
186 | Do use early returns | ||
187 | |||
188 | ```rust | ||
189 | // Good | ||
190 | fn foo() -> Option<Bar> { | ||
191 | if !condition() { | ||
192 | return None; | ||
193 | } | ||
194 | |||
195 | Some(...) | ||
196 | } | ||
197 | |||
198 | // Not as good | ||
199 | fn foo() -> Option<Bar> { | ||
200 | if condition() { | ||
201 | Some(...) | ||
202 | } else { | ||
203 | None | ||
204 | } | ||
205 | } | ||
206 | ``` | ||
207 | |||
184 | # Getters & Setters | 208 | # Getters & Setters |
185 | 209 | ||
186 | If a field can have any value without breaking invariants, make the field public. | 210 | If a field can have any value without breaking invariants, make the field public. |
@@ -189,7 +213,7 @@ Never provide setters. | |||
189 | 213 | ||
190 | Getters should return borrowed data: | 214 | Getters should return borrowed data: |
191 | 215 | ||
192 | ``` | 216 | ```rust |
193 | struct Person { | 217 | struct Person { |
194 | // Invariant: never empty | 218 | // Invariant: never empty |
195 | first_name: String, | 219 | first_name: String, |
@@ -231,6 +255,41 @@ if words.len() != 2 { | |||
231 | } | 255 | } |
232 | ``` | 256 | ``` |
233 | 257 | ||
258 | # Avoid Monomorphization | ||
259 | |||
260 | Rust uses monomorphization to compile generic code, meaning that for each instantiation of a generic functions with concrete types, the function is compiled afresh, *per crate*. | ||
261 | This allows for exceptionally good performance, but leads to increased compile times. | ||
262 | Runtime performance obeys 80%/20% rule -- only a small fraction of code is hot. | ||
263 | Compile time **does not** obey this rule -- all code has to be compiled. | ||
264 | For this reason, avoid making a lot of code type parametric, *especially* on the boundaries between crates. | ||
265 | |||
266 | ```rust | ||
267 | // Good | ||
268 | fn frbonicate(f: impl FnMut()) { | ||
269 | frobnicate_impl(&mut f) | ||
270 | } | ||
271 | fn frobnicate_impl(f: &mut dyn FnMut()) { | ||
272 | // lots of code | ||
273 | } | ||
274 | |||
275 | // Not as good | ||
276 | fn frbonicate(f: impl FnMut()) { | ||
277 | // lots of code | ||
278 | } | ||
279 | ``` | ||
280 | |||
281 | Avoid `AsRef` polymorphism, it pays back only for widely used libraries: | ||
282 | |||
283 | ```rust | ||
284 | // Good | ||
285 | fn frbonicate(f: &Path) { | ||
286 | } | ||
287 | |||
288 | // Not as good | ||
289 | fn frbonicate(f: impl AsRef<Path>) { | ||
290 | } | ||
291 | ``` | ||
292 | |||
234 | # Documentation | 293 | # Documentation |
235 | 294 | ||
236 | For `.md` and `.adoc` files, prefer a sentence-per-line format, don't wrap lines. | 295 | For `.md` and `.adoc` files, prefer a sentence-per-line format, don't wrap lines. |
diff --git a/editors/code/src/net.ts b/editors/code/src/net.ts index 681eaa9c9..5eba2728d 100644 --- a/editors/code/src/net.ts +++ b/editors/code/src/net.ts | |||
@@ -134,6 +134,14 @@ async function downloadFile( | |||
134 | 134 | ||
135 | await pipeline(srcStream, destFileStream); | 135 | await pipeline(srcStream, destFileStream); |
136 | 136 | ||
137 | // Don't apply the workaround in fixed versions of nodejs, since the process | ||
138 | // freezes on them, the process waits for no-longer emitted `close` event. | ||
139 | // The fix was applied in commit 7eed9d6bcc in v13.11.0 | ||
140 | // See the nodejs changelog: | ||
141 | // https://github.com/nodejs/node/blob/master/doc/changelogs/CHANGELOG_V13.md | ||
142 | const [, major, minor] = /v(\d+)\.(\d+)\.(\d+)/.exec(process.version)!; | ||
143 | if (+major > 13 || (+major === 13 && +minor >= 11)) return; | ||
144 | |||
137 | await new Promise<void>(resolve => { | 145 | await new Promise<void>(resolve => { |
138 | destFileStream.on("close", resolve); | 146 | destFileStream.on("close", resolve); |
139 | destFileStream.destroy(); | 147 | destFileStream.destroy(); |
diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index e9edbdd10..0750b5657 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml | |||
@@ -15,7 +15,7 @@ flate2 = "1.0" | |||
15 | pico-args = "0.3.1" | 15 | pico-args = "0.3.1" |
16 | proc-macro2 = "1.0.8" | 16 | proc-macro2 = "1.0.8" |
17 | quote = "1.0.2" | 17 | quote = "1.0.2" |
18 | ungrammar = "1.1.1" | 18 | ungrammar = "1.1.3" |
19 | walkdir = "2.3.1" | 19 | walkdir = "2.3.1" |
20 | write-json = "0.1.0" | 20 | write-json = "0.1.0" |
21 | # Avoid adding more dependencies to this crate | 21 | # Avoid adding more dependencies to this crate |
diff --git a/xtask/src/codegen/rust.ungram b/xtask/src/codegen/rust.ungram deleted file mode 100644 index aca23890c..000000000 --- a/xtask/src/codegen/rust.ungram +++ /dev/null | |||
@@ -1,587 +0,0 @@ | |||
1 | //*************************// | ||
2 | // Names, Paths and Macros // | ||
3 | //*************************// | ||
4 | |||
5 | Name = | ||
6 | 'ident' | ||
7 | |||
8 | NameRef = | ||
9 | 'ident' | 'int_number' | ||
10 | |||
11 | Path = | ||
12 | (qualifier:Path '::')? segment:PathSegment | ||
13 | |||
14 | PathSegment = | ||
15 | 'crate' | 'self' | 'super' | ||
16 | | '::' NameRef | ||
17 | | NameRef GenericArgList? | ||
18 | | NameRef ParamList RetType? | ||
19 | | '<' PathType ('as' PathType)? '>' | ||
20 | |||
21 | GenericArgList = | ||
22 | '::'? '<' (GenericArg (',' GenericArg)* ','?)? '>' | ||
23 | |||
24 | GenericArg = | ||
25 | TypeArg | ||
26 | | AssocTypeArg | ||
27 | | LifetimeArg | ||
28 | | ConstArg | ||
29 | |||
30 | TypeArg = | ||
31 | Type | ||
32 | |||
33 | AssocTypeArg = | ||
34 | NameRef (':' TypeBoundList | '=' Type) | ||
35 | |||
36 | LifetimeArg = | ||
37 | 'lifetime' | ||
38 | |||
39 | ConstArg = | ||
40 | Expr | ||
41 | |||
42 | MacroCall = | ||
43 | Attr* Path '!' Name? TokenTree ';'? | ||
44 | |||
45 | TokenTree = | ||
46 | '(' ')' | ||
47 | | '{' '}' | ||
48 | | '[' ']' | ||
49 | |||
50 | MacroItems = | ||
51 | Item* | ||
52 | |||
53 | MacroStmts = | ||
54 | statements:Stmt* | ||
55 | Expr? | ||
56 | |||
57 | //*************************// | ||
58 | // Items // | ||
59 | //*************************// | ||
60 | |||
61 | SourceFile = | ||
62 | 'shebang'? | ||
63 | Attr* | ||
64 | Item* | ||
65 | |||
66 | Item = | ||
67 | Const | ||
68 | | Enum | ||
69 | | ExternBlock | ||
70 | | ExternCrate | ||
71 | | Fn | ||
72 | | Impl | ||
73 | | MacroCall | ||
74 | | Module | ||
75 | | Static | ||
76 | | Struct | ||
77 | | Trait | ||
78 | | TypeAlias | ||
79 | | Union | ||
80 | | Use | ||
81 | |||
82 | Module = | ||
83 | Attr* Visibility? 'mod' Name | ||
84 | (ItemList | ';') | ||
85 | |||
86 | ItemList = | ||
87 | '{' Attr* Item* '}' | ||
88 | |||
89 | ExternCrate = | ||
90 | Attr* Visibility? 'extern' 'crate' (NameRef | 'self') Rename? ';' | ||
91 | |||
92 | Rename = | ||
93 | 'as' (Name | '_') | ||
94 | |||
95 | Use = | ||
96 | Attr* Visibility? 'use' UseTree ';' | ||
97 | |||
98 | UseTree = | ||
99 | (Path? '::')? ('*' | UseTreeList ) | ||
100 | | Path Rename? | ||
101 | |||
102 | UseTreeList = | ||
103 | '{' (UseTree (',' UseTree)* ','?)? '}' | ||
104 | |||
105 | Fn = | ||
106 | Attr* Visibility? | ||
107 | 'default'? ('async' | 'const')? 'unsafe'? Abi? | ||
108 | 'fn' Name GenericParamList? ParamList RetType? | ||
109 | WhereClause? | ||
110 | (body:BlockExpr | ';') | ||
111 | |||
112 | Abi = | ||
113 | 'extern' 'string'? | ||
114 | |||
115 | ParamList = | ||
116 | '('( | ||
117 | SelfParam | ||
118 | | (SelfParam ',')? (Param (',' Param)* ','?)? | ||
119 | )')' | ||
120 | |||
121 | SelfParam = | ||
122 | Attr* ( | ||
123 | ('&' 'lifetime'?)? 'mut'? 'self' | ||
124 | | 'mut'? 'self' ':' Type | ||
125 | ) | ||
126 | |||
127 | Param = | ||
128 | Attr* ( | ||
129 | Pat (':' Type) | ||
130 | | Type | ||
131 | | '...' | ||
132 | ) | ||
133 | |||
134 | RetType = | ||
135 | '->' Type | ||
136 | |||
137 | TypeAlias = | ||
138 | Attr* Visibility? 'default'? 'type' Name GenericParamList? (':' TypeBoundList?)? WhereClause? | ||
139 | '=' Type ';' | ||
140 | |||
141 | Struct = | ||
142 | Attr* Visibility? 'struct' Name GenericParamList? ( | ||
143 | WhereClause? (RecordFieldList | ';') | ||
144 | | TupleFieldList WhereClause? ';' | ||
145 | ) | ||
146 | |||
147 | RecordFieldList = | ||
148 | '{' fields:(RecordField (',' RecordField)* ','?)? '}' | ||
149 | |||
150 | RecordField = | ||
151 | Attr* Visibility? Name ':' Type | ||
152 | |||
153 | TupleFieldList = | ||
154 | '(' fields:(TupleField (',' TupleField)* ','?)? ')' | ||
155 | |||
156 | TupleField = | ||
157 | Attr* Visibility? Type | ||
158 | |||
159 | FieldList = | ||
160 | RecordFieldList | ||
161 | | TupleFieldList | ||
162 | |||
163 | Enum = | ||
164 | Attr* Visibility? 'enum' Name GenericParamList? WhereClause? | ||
165 | VariantList | ||
166 | |||
167 | VariantList = | ||
168 | '{' (Variant (',' Variant)* ','?)? '}' | ||
169 | |||
170 | Variant = | ||
171 | Attr* Visibility? Name FieldList ('=' Expr)? | ||
172 | |||
173 | Union = | ||
174 | Attr* Visibility? 'union' Name GenericParamList? WhereClause? | ||
175 | RecordFieldList | ||
176 | |||
177 | AdtDef = | ||
178 | Enum | ||
179 | | Struct | ||
180 | | Union | ||
181 | |||
182 | Const = | ||
183 | Attr* Visibility? 'default'? 'const' (Name | '_') ':' Type | ||
184 | '=' body:Expr ';' | ||
185 | |||
186 | Static = | ||
187 | Attr* Visibility? 'static'? 'mut'? Name ':' Type | ||
188 | '=' body:Expr ';' | ||
189 | |||
190 | Trait = | ||
191 | Attr* Visibility? 'unsafe'? 'auto'? 'trait' Name GenericParamList | ||
192 | (':' TypeBoundList?)? WhereClause | ||
193 | AssocItemList | ||
194 | |||
195 | AssocItemList = | ||
196 | '{' Attr* AssocItem* '}' | ||
197 | |||
198 | AssocItem = | ||
199 | Const | ||
200 | | Fn | ||
201 | | MacroCall | ||
202 | | TypeAlias | ||
203 | |||
204 | Impl = | ||
205 | Attr* Visibility? | ||
206 | 'default'? 'unsafe'? 'impl' 'const'? GenericParamList? | ||
207 | ('!'? target_trait:Type 'for')? target_type:Type | ||
208 | WhereClause? | ||
209 | AssocItemList | ||
210 | |||
211 | ExternBlock = | ||
212 | Attr* Abi ExternItemList | ||
213 | |||
214 | ExternItemList = | ||
215 | '{' Attr* ExternItem* '}' | ||
216 | |||
217 | ExternItem = | ||
218 | Fn | Static | MacroCall | ||
219 | |||
220 | GenericParamList = | ||
221 | '<' (GenericParam (',' GenericParam)* ','?)? '>' | ||
222 | |||
223 | GenericParam = | ||
224 | ConstParam | ||
225 | | LifetimeParam | ||
226 | | TypeParam | ||
227 | |||
228 | TypeParam = | ||
229 | Attr* Name (':' TypeBoundList?)? | ||
230 | ('=' default_type:Type)? | ||
231 | |||
232 | ConstParam = | ||
233 | Attr* 'const' Name ':' Type | ||
234 | ('=' default_val:Expr)? | ||
235 | |||
236 | LifetimeParam = | ||
237 | Attr* 'lifetime' (':' TypeBoundList?)? | ||
238 | |||
239 | WhereClause = | ||
240 | 'where' predicates:(WherePred (',' WherePred)* ','?) | ||
241 | |||
242 | WherePred = | ||
243 | ('for' GenericParamList)? ('lifetime' | Type) ':' TypeBoundList | ||
244 | |||
245 | Visibility = | ||
246 | 'pub' ('(' | ||
247 | 'super' | ||
248 | | 'self' | ||
249 | | 'crate' | ||
250 | | 'in' Path | ||
251 | ')')? | ||
252 | |||
253 | Attr = | ||
254 | '#' '!'? '[' Path ('=' Literal | TokenTree)? ']' | ||
255 | |||
256 | //****************************// | ||
257 | // Statements and Expressions // | ||
258 | //****************************// | ||
259 | |||
260 | Stmt = | ||
261 | ExprStmt | ||
262 | | Item | ||
263 | | LetStmt | ||
264 | |||
265 | LetStmt = | ||
266 | Attr* 'let' Pat (':' Type)? | ||
267 | '=' initializer:Expr ';' | ||
268 | |||
269 | ExprStmt = | ||
270 | Attr* Expr ';'? | ||
271 | |||
272 | Expr = | ||
273 | ArrayExpr | ||
274 | | AwaitExpr | ||
275 | | BinExpr | ||
276 | | BlockExpr | ||
277 | | BoxExpr | ||
278 | | BreakExpr | ||
279 | | CallExpr | ||
280 | | CastExpr | ||
281 | | ClosureExpr | ||
282 | | ContinueExpr | ||
283 | | EffectExpr | ||
284 | | FieldExpr | ||
285 | | ForExpr | ||
286 | | IfExpr | ||
287 | | IndexExpr | ||
288 | | Literal | ||
289 | | LoopExpr | ||
290 | | MacroCall | ||
291 | | MatchExpr | ||
292 | | MethodCallExpr | ||
293 | | ParenExpr | ||
294 | | PathExpr | ||
295 | | PrefixExpr | ||
296 | | RangeExpr | ||
297 | | RecordExpr | ||
298 | | RefExpr | ||
299 | | ReturnExpr | ||
300 | | TryExpr | ||
301 | | TupleExpr | ||
302 | | WhileExpr | ||
303 | |||
304 | Literal = | ||
305 | Attr* value:( | ||
306 | 'int_number' | 'float_number' | ||
307 | | 'string' | 'raw_string' | ||
308 | | 'byte_string' | 'raw_byte_string' | ||
309 | | 'true' | 'false' | ||
310 | | 'char' | 'byte' | ||
311 | ) | ||
312 | |||
313 | PathExpr = | ||
314 | Attr* Path | ||
315 | |||
316 | BlockExpr = | ||
317 | '{' | ||
318 | Attr* | ||
319 | statements:Stmt* | ||
320 | Expr? | ||
321 | '}' | ||
322 | |||
323 | RefExpr = | ||
324 | Attr* '&' ('raw' |'mut' | 'const') Expr | ||
325 | |||
326 | TryExpr = | ||
327 | Attr* Expr '?' | ||
328 | |||
329 | EffectExpr = | ||
330 | Attr* Label? ('try' | 'unsafe' | 'async') BlockExpr | ||
331 | |||
332 | PrefixExpr = | ||
333 | Attr* op:('-' | '!' | '*') Expr | ||
334 | |||
335 | BinExpr = | ||
336 | Attr* | ||
337 | lhs:Expr | ||
338 | op:( | ||
339 | '||' | '&&' | ||
340 | | '==' | '!=' | '<=' | '>=' | '<' | '>' | ||
341 | | '+' | '*' | '-' | '/' | '%' | '<<' | '>>' | '^' | '|' | '&' | ||
342 | | '=' | '+=' | '/=' | '*=' | '%=' | '>>=' | '<<=' | '-=' | '|=' | '&=' | '^=' | ||
343 | ) | ||
344 | rhs:Expr | ||
345 | |||
346 | CastExpr = | ||
347 | Attr* Expr 'as' Type | ||
348 | |||
349 | ParenExpr = | ||
350 | Attr* '(' Attr* Expr ')' | ||
351 | |||
352 | ArrayExpr = | ||
353 | Attr* '[' Attr* ( | ||
354 | (Expr (',' Expr)* ','?)? | ||
355 | | Expr ';' Expr | ||
356 | ) ']' | ||
357 | |||
358 | IndexExpr = | ||
359 | Attr* base:Expr '[' index:Expr ']' | ||
360 | |||
361 | TupleExpr = | ||
362 | Attr* '(' Attr* fields:(Expr (',' Expr)* ','?)? ')' | ||
363 | |||
364 | RecordExpr = | ||
365 | Path RecordExprFieldList | ||
366 | |||
367 | RecordExprFieldList = | ||
368 | '{' | ||
369 | Attr* | ||
370 | fields:(RecordExprField (',' RecordExprField)* ','?) | ||
371 | ('..' spread:Expr)? | ||
372 | '}' | ||
373 | |||
374 | RecordExprField = | ||
375 | Attr* NameRef (':' Expr)? | ||
376 | |||
377 | CallExpr = | ||
378 | Attr* Expr ArgList | ||
379 | |||
380 | ArgList = | ||
381 | '(' args:(Expr (',' Expr)* ','?)? ')' | ||
382 | |||
383 | MethodCallExpr = | ||
384 | Attr* Expr '.' NameRef GenericArgList? ArgList | ||
385 | |||
386 | FieldExpr = | ||
387 | Attr* Expr '.' NameRef | ||
388 | |||
389 | ClosureExpr = | ||
390 | Attr* 'static'? 'async'? 'move'? ParamList RetType? | ||
391 | body:Expr | ||
392 | |||
393 | IfExpr = | ||
394 | Attr* 'if' Condition then_branch:BlockExpr | ||
395 | ('else' else_branch:(IfExpr | BlockExpr))? | ||
396 | |||
397 | Condition = | ||
398 | 'let' Pat '=' Expr | ||
399 | | Expr | ||
400 | |||
401 | LoopExpr = | ||
402 | Attr* Label? 'loop' | ||
403 | loop_body:BlockExpr | ||
404 | |||
405 | ForExpr = | ||
406 | Attr* Label? 'for' Pat 'in' iterable:Expr | ||
407 | loop_body:BlockExpr | ||
408 | |||
409 | WhileExpr = | ||
410 | Attr* Label? 'while' Condition | ||
411 | loop_body:BlockExpr | ||
412 | |||
413 | Label = | ||
414 | 'lifetime' | ||
415 | |||
416 | BreakExpr = | ||
417 | Attr* 'break' 'lifetime'? Expr? | ||
418 | |||
419 | ContinueExpr = | ||
420 | Attr* 'continue' 'lifetime'? | ||
421 | |||
422 | RangeExpr = | ||
423 | Attr* start:Expr? op:('..' | '..=') end:Expr? | ||
424 | |||
425 | MatchExpr = | ||
426 | Attr* 'match' Expr MatchArmList | ||
427 | |||
428 | MatchArmList = | ||
429 | '{' | ||
430 | Attr* | ||
431 | arms:MatchArm* | ||
432 | '}' | ||
433 | |||
434 | MatchArm = | ||
435 | Attr* Pat guard:MatchGuard? '=>' Expr ','? | ||
436 | |||
437 | MatchGuard = | ||
438 | 'if' Expr | ||
439 | |||
440 | ReturnExpr = | ||
441 | Attr* 'return' Expr? | ||
442 | |||
443 | AwaitExpr = | ||
444 | Attr* Expr '.' 'await' | ||
445 | |||
446 | BoxExpr = | ||
447 | Attr* 'box' Expr | ||
448 | |||
449 | //*************************// | ||
450 | // Types // | ||
451 | //*************************// | ||
452 | |||
453 | Type = | ||
454 | ArrayType | ||
455 | | DynTraitType | ||
456 | | FnPointerType | ||
457 | | ForType | ||
458 | | ImplTraitType | ||
459 | | InferType | ||
460 | | NeverType | ||
461 | | ParenType | ||
462 | | PathType | ||
463 | | PointerType | ||
464 | | ReferenceType | ||
465 | | SliceType | ||
466 | | TupleType | ||
467 | |||
468 | ParenType = | ||
469 | '(' Type ')' | ||
470 | |||
471 | NeverType = | ||
472 | '!' | ||
473 | |||
474 | PathType = | ||
475 | Path | ||
476 | |||
477 | TupleType = | ||
478 | '(' fields:(Type (',' Type)* ','?)? ')' | ||
479 | |||
480 | PointerType = | ||
481 | '*' ('const' | 'mut') Type | ||
482 | |||
483 | ReferenceType = | ||
484 | '&' 'lifetime'? 'mut'? Type | ||
485 | |||
486 | ArrayType = | ||
487 | '[' Type ';' Expr ']' | ||
488 | |||
489 | SliceType = | ||
490 | '[' Type ']' | ||
491 | |||
492 | InferType = | ||
493 | '_' | ||
494 | |||
495 | FnPointerType = | ||
496 | 'const'? 'async'? 'unsafe'? Abi? 'fn' ParamList RetType? | ||
497 | |||
498 | ForType = | ||
499 | 'for' GenericParamList Type | ||
500 | |||
501 | ImplTraitType = | ||
502 | 'impl' TypeBoundList | ||
503 | |||
504 | DynTraitType = | ||
505 | 'dyn' TypeBoundList | ||
506 | |||
507 | TypeBoundList = | ||
508 | bounds:(TypeBound ('+' TypeBound)* '+'?) | ||
509 | |||
510 | TypeBound = | ||
511 | 'lifetime' | ||
512 | | '?'? Type | ||
513 | |||
514 | //************************// | ||
515 | // Patterns // | ||
516 | //************************// | ||
517 | |||
518 | Pat = | ||
519 | IdentPat | ||
520 | | BoxPat | ||
521 | | RestPat | ||
522 | | LiteralPat | ||
523 | | MacroPat | ||
524 | | OrPat | ||
525 | | ParenPat | ||
526 | | PathPat | ||
527 | | WildcardPat | ||
528 | | RangePat | ||
529 | | RecordPat | ||
530 | | RefPat | ||
531 | | SlicePat | ||
532 | | TuplePat | ||
533 | | TupleStructPat | ||
534 | |||
535 | LiteralPat = | ||
536 | Literal | ||
537 | |||
538 | IdentPat = | ||
539 | Attr* 'ref'? 'mut'? Name ('@' Pat)? | ||
540 | |||
541 | WildcardPat = | ||
542 | '_' | ||
543 | |||
544 | RangePat = | ||
545 | start:Pat op:('..' | '..=') end:Pat | ||
546 | |||
547 | RefPat = | ||
548 | '&' 'mut'? Pat | ||
549 | |||
550 | RecordPat = | ||
551 | Path RecordPatFieldList | ||
552 | |||
553 | RecordPatFieldList = | ||
554 | '{' | ||
555 | fields:(RecordPatField (',' RecordPatField)* ','?) | ||
556 | '..'? | ||
557 | '}' | ||
558 | |||
559 | RecordPatField = | ||
560 | Attr* (NameRef ':')? Pat | ||
561 | |||
562 | TupleStructPat = | ||
563 | Path '(' fields:(Pat (',' Pat)* ','?)? ')' | ||
564 | |||
565 | TuplePat = | ||
566 | '(' fields:(Pat (',' Pat)* ','?)? ')' | ||
567 | |||
568 | ParenPat = | ||
569 | '(' Pat ')' | ||
570 | |||
571 | SlicePat = | ||
572 | '[' (Pat (',' Pat)* ','?)? ']' | ||
573 | |||
574 | PathPat = | ||
575 | Path | ||
576 | |||
577 | OrPat = | ||
578 | (Pat ('|' Pat)* '|'?) | ||
579 | |||
580 | BoxPat = | ||
581 | 'box' Pat | ||
582 | |||
583 | RestPat = | ||
584 | '..' | ||
585 | |||
586 | MacroPat = | ||
587 | MacroCall | ||