Repository: rust-analyzer/rust-analyzer
Pull request #1736 (2019-08-25 16:02:42)

Switch to `@types/vscode` and `vscode-test`
The old `vscode` package is outdated and it is recommened to switch to
these two new packages. This also solves a problem of a missing `.d.ts`
for `vscode` in Nixos.


Patch:
diff --git a/.travis.yml b/.travis.yml
index 52af053753..87b546442f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -60,6 +60,7 @@ deploy:
     github-token: $DOCS_TOKEN  # Set in the settings page of your repository, as a secure variable
     keep-history: true
     local-dir: target/doc
+    branch: gh-pages
     on:
         branch: master
         condition: $DEPLOY_DOCS = 1
diff --git a/Cargo.lock b/Cargo.lock
index e2938b5f8c..84f9f8ccd1 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1080,13 +1080,12 @@ dependencies = [
 name = "ra_batch"
 version = "0.1.0"
 dependencies = [
- "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "ra_db 0.1.0",
  "ra_hir 0.1.0",
  "ra_ide_api 0.1.0",
  "ra_project_model 0.1.0",
- "ra_vfs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ra_vfs 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "ra_vfs_glob 0.1.0",
  "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1192,7 +1191,7 @@ dependencies = [
  "ra_project_model 0.1.0",
  "ra_syntax 0.1.0",
  "ra_text_edit 0.1.0",
- "ra_vfs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ra_vfs 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "ra_vfs_glob 0.1.0",
  "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1301,7 +1300,7 @@ dependencies = [
 
 [[package]]
 name = "ra_vfs"
-version = "0.3.0"
+version = "0.2.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1319,7 +1318,7 @@ name = "ra_vfs_glob"
 version = "0.1.0"
 dependencies = [
  "globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "ra_vfs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ra_vfs 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2121,7 +2120,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
 "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
 "checksum ra_rustc_lexer 0.1.0-pre.3 (registry+https://github.com/rust-lang/crates.io-index)" = "04371af481820ff8d35c7d12b503eb09cf9e1bd246269bf4a33e3d8c54fa3a4a"
-"checksum ra_vfs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ccc8b709e0b7ceec822513451b610df1b9370b01953a8bc545a041a6b3bfef01"
+"checksum ra_vfs 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "9e891866e1bb03f50a28cc01e3f244a62107c301ae674ba06b2e7a9b310ae75a"
 "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
 "checksum rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d47eab0e83d9693d40f825f86948aa16eff6750ead4bdffc4ab95b8b3a7f052c"
 "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
diff --git a/crates/ra_assists/src/add_missing_impl_members.rs b/crates/ra_assists/src/add_missing_impl_members.rs
index cbeb7054f4..31c7d4e804 100644
--- a/crates/ra_assists/src/add_missing_impl_members.rs
+++ b/crates/ra_assists/src/add_missing_impl_members.rs
@@ -1,14 +1,13 @@
-use hir::{db::HirDatabase, HasSource};
-use ra_syntax::{
-    ast::{self, AstNode, NameOwner},
-    SmolStr,
-};
-
 use crate::{
     ast_editor::{AstBuilder, AstEditor},
     Assist, AssistCtx, AssistId,
 };
 
+use hir::{db::HirDatabase, HasSource};
+use ra_db::FilePosition;
+use ra_syntax::ast::{self, AstNode, NameOwner};
+use ra_syntax::SmolStr;
+
 #[derive(PartialEq)]
 enum AddMissingImplMembersMode {
     DefaultMethodsOnly,
@@ -44,7 +43,8 @@ fn add_missing_impl_members_inner(
 
     let trait_def = {
         let file_id = ctx.frange.file_id;
-        let analyzer = hir::SourceAnalyzer::new(ctx.db, file_id, impl_node.syntax(), None);
+        let position = FilePosition { file_id, offset: impl_node.syntax().text_range().start() };
+        let analyzer = hir::SourceAnalyzer::new(ctx.db, position.file_id, impl_node.syntax(), None);
 
         resolve_target_trait_def(ctx.db, &analyzer, &impl_node)?
     };
diff --git a/crates/ra_assists/src/ast_editor.rs b/crates/ra_assists/src/ast_editor.rs
index 6815638dc8..95b871b30c 100644
--- a/crates/ra_assists/src/ast_editor.rs
+++ b/crates/ra_assists/src/ast_editor.rs
@@ -1,8 +1,6 @@
 use std::{iter, ops::RangeInclusive};
 
 use arrayvec::ArrayVec;
-use itertools::Itertools;
-
 use hir::Name;
 use ra_fmt::leading_indent;
 use ra_syntax::{
@@ -19,10 +17,7 @@ pub struct AstEditor<N: AstNode> {
 }
 
 impl<N: AstNode> AstEditor<N> {
-    pub fn new(node: N) -> AstEditor<N>
-    where
-        N: Clone,
-    {
+    pub fn new(node: N) -> AstEditor<N> {
         AstEditor { original_ast: node.clone(), ast: node }
     }
 
@@ -93,15 +88,15 @@ impl<N: AstNode> AstEditor<N> {
     }
 }
 
-impl AstEditor<ast::RecordFieldList> {
-    pub fn append_field(&mut self, field: &ast::RecordField) {
+impl AstEditor<ast::NamedFieldList> {
+    pub fn append_field(&mut self, field: &ast::NamedField) {
         self.insert_field(InsertPosition::Last, field)
     }
 
     pub fn insert_field(
         &mut self,
-        position: InsertPosition<&'_ ast::RecordField>,
-        field: &ast::RecordField,
+        position: InsertPosition<&'_ ast::NamedField>,
+        field: &ast::NamedField,
     ) {
         let is_multiline = self.ast().syntax().text().contains_char('\n');
         let ws;
@@ -173,7 +168,8 @@ impl AstEditor<ast::RecordFieldList> {
 
 impl AstEditor<ast::ItemList> {
     pub fn append_items(&mut self, items: impl Iterator<Item = ast::ImplItem>) {
-        if !self.ast().syntax().text().contains_char('\n') {
+        let n_existing_items = self.ast().impl_items().count();
+        if n_existing_items == 0 {
             self.do_make_multiline();
         }
         items.for_each(|it| self.append_item(it));
@@ -245,16 +241,16 @@ pub struct AstBuilder<N: AstNode> {
     _phantom: std::marker::PhantomData<N>,
 }
 
-impl AstBuilder<ast::RecordField> {
-    pub fn from_name(name: &Name) -> ast::RecordField {
+impl AstBuilder<ast::NamedField> {
+    pub fn from_name(name: &Name) -> ast::NamedField {
         ast_node_from_file_text(&format!("fn f() {{ S {{ {}: (), }} }}", name))
     }
 
-    fn from_text(text: &str) -> ast::RecordField {
+    fn from_text(text: &str) -> ast::NamedField {
         ast_node_from_file_text(&format!("fn f() {{ S {{ {}, }} }}", text))
     }
 
-    pub fn from_pieces(name: &ast::NameRef, expr: Option<&ast::Expr>) -> ast::RecordField {
+    pub fn from_pieces(name: &ast::NameRef, expr: Option<&ast::Expr>) -> ast::NamedField {
         match expr {
             Some(expr) => Self::from_text(&format!("{}: {}", name.syntax(), expr.syntax())),
             None => Self::from_text(&name.syntax().to_string()),
@@ -292,97 +288,9 @@ impl AstBuilder<ast::NameRef> {
     }
 }
 
-impl AstBuilder<ast::Path> {
-    fn from_text(text: &str) -> ast::Path {
-        ast_node_from_file_text(text)
-    }
-
-    pub fn from_pieces(enum_name: ast::Name, var_name: ast::Name) -> ast::Path {
-        Self::from_text(&format!("{}::{}", enum_name.syntax(), var_name.syntax()))
-    }
-}
-
-impl AstBuilder<ast::BindPat> {
-    fn from_text(text: &str) -> ast::BindPat {
-        ast_node_from_file_text(&format!("fn f({}: ())", text))
-    }
-
-    pub fn from_name(name: &ast::Name) -> ast::BindPat {
-        Self::from_text(name.text())
-    }
-}
-
-impl AstBuilder<ast::PlaceholderPat> {
-    fn from_text(text: &str) -> ast::PlaceholderPat {
-        ast_node_from_file_text(&format!("fn f({}: ())", text))
-    }
-
-    pub fn placeholder() -> ast::PlaceholderPat {
-        Self::from_text("_")
-    }
-}
-
-impl AstBuilder<ast::TupleStructPat> {
-    fn from_text(text: &str) -> ast::TupleStructPat {
-        ast_node_from_file_text(&format!("fn f({}: ())", text))
-    }
-
-    pub fn from_pieces(
-        path: &ast::Path,
-        pats: impl Iterator<Item = ast::Pat>,
-    ) -> ast::TupleStructPat {
-        let pats_str = pats.map(|p| p.syntax().to_string()).collect::<Vec<_>>().join(", ");
-        Self::from_text(&format!("{}({})", path.syntax(), pats_str))
-    }
-}
-
-impl AstBuilder<ast::RecordPat> {
-    fn from_text(text: &str) -> ast::RecordPat {
-        ast_node_from_file_text(&format!("fn f({}: ())", text))
-    }
-
-    pub fn from_pieces(path: &ast::Path, pats: impl Iterator<Item = ast::Pat>) -> ast::RecordPat {
-        let pats_str = pats.map(|p| p.syntax().to_string()).collect::<Vec<_>>().join(", ");
-        Self::from_text(&format!("{}{{ {} }}", path.syntax(), pats_str))
-    }
-}
-
-impl AstBuilder<ast::PathPat> {
-    fn from_text(text: &str) -> ast::PathPat {
-        ast_node_from_file_text(&format!("fn f({}: ())", text))
-    }
-
-    pub fn from_path(path: &ast::Path) -> ast::PathPat {
-        let path_str = path.syntax().text().to_string();
-        Self::from_text(path_str.as_str())
-    }
-}
-
-impl AstBuilder<ast::MatchArm> {
-    fn from_text(text: &str) -> ast::MatchArm {
-        ast_node_from_file_text(&format!("fn f() {{ match () {{{}}} }}", text))
-    }
-
-    pub fn from_pieces(pats: impl Iterator<Item = ast::Pat>, expr: &ast::Expr) -> ast::MatchArm {
-        let pats_str = pats.map(|p| p.syntax().to_string()).join(" | ");
-        Self::from_text(&format!("{} => {}", pats_str, expr.syntax()))
-    }
-}
-
-impl AstBuilder<ast::MatchArmList> {
-    fn from_text(text: &str) -> ast::MatchArmList {
-        ast_node_from_file_text(&format!("fn f() {{ match () {{{}}} }}", text))
-    }
-
-    pub fn from_arms(arms: impl Iterator<Item = ast::MatchArm>) -> ast::MatchArmList {
-        let arms_str = arms.map(|arm| format!("\n    {}", arm.syntax())).join(",");
-        Self::from_text(&format!("{},\n", arms_str))
-    }
-}
-
 fn ast_node_from_file_text<N: AstNode>(text: &str) -> N {
     let parse = SourceFile::parse(text);
-    let res = parse.tree().syntax().descendants().find_map(N::cast).unwrap();
+    let res = parse.tree().syntax().descendants().find_map(N::cast).unwrap().to_owned();
     res
 }
 
diff --git a/crates/ra_assists/src/change_visibility.rs b/crates/ra_assists/src/change_visibility.rs
index 60c74debca..d28cdd07bf 100644
--- a/crates/ra_assists/src/change_visibility.rs
+++ b/crates/ra_assists/src/change_visibility.rs
@@ -38,7 +38,7 @@ fn add_vis(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
         (vis_offset(&parent), keyword.text_range())
     } else {
         let ident = ctx.token_at_offset().find(|leaf| leaf.kind() == IDENT)?;
-        let field = ident.parent().ancestors().find_map(ast::RecordFieldDef::cast)?;
+        let field = ident.parent().ancestors().find_map(ast::NamedFieldDef::cast)?;
         if field.name()?.syntax().text_range() != ident.text_range() && field.visibility().is_some()
         {
             return None;
diff --git a/crates/ra_assists/src/fill_match_arms.rs b/crates/ra_assists/src/fill_match_arms.rs
index cc38795624..85ff5c052a 100644
--- a/crates/ra_assists/src/fill_match_arms.rs
+++ b/crates/ra_assists/src/fill_match_arms.rs
@@ -1,91 +1,97 @@
-use std::iter;
+use itertools::Itertools;
+use std::fmt::Write;
 
-use hir::{db::HirDatabase, AdtDef, HasSource};
-use ra_syntax::ast::{self, AstNode, NameOwner};
+use hir::{db::HirDatabase, AdtDef, FieldSource, HasSource};
+use ra_syntax::ast::{self, AstNode};
 
-use crate::{ast_editor::AstBuilder, Assist, AssistCtx, AssistId};
+use crate::{Assist, AssistCtx, AssistId};
+
+fn is_trivial_arm(arm: &ast::MatchArm) -> bool {
+    fn single_pattern(arm: &ast::MatchArm) -> Option<ast::Pat> {
+        let (pat,) = arm.pats().collect_tuple()?;
+        Some(pat)
+    }
+    match single_pattern(arm) {
+        Some(ast::Pat::PlaceholderPat(..)) => true,
+        _ => false,
+    }
+}
 
 pub(crate) fn fill_match_arms(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
     let match_expr = ctx.node_at_offset::<ast::MatchExpr>()?;
-    let match_arm_list = match_expr.match_arm_list()?;
 
     // We already have some match arms, so we don't provide any assists.
     // Unless if there is only one trivial match arm possibly created
     // by match postfix complete. Trivial match arm is the catch all arm.
-    let mut existing_arms = match_arm_list.arms();
-    if let Some(arm) = existing_arms.next() {
-        if !is_trivial(&arm) || existing_arms.next().is_some() {
-            return None;
+    if let Some(arm_list) = match_expr.match_arm_list() {
+        let mut arm_iter = arm_list.arms();
+        let first = arm_iter.next();
+
+        match &first {
+            // If there arm list is empty or there is only one trivial arm, then proceed.
+            Some(arm) if is_trivial_arm(arm) => {
+                if arm_iter.next() != None {
+                    return None;
+                }
+            }
+            None => {}
+
+            _ => {
+                return None;
+            }
         }
     };
 
     let expr = match_expr.expr()?;
-    let enum_def = {
-        let file_id = ctx.frange.file_id;
-        let analyzer = hir::SourceAnalyzer::new(ctx.db, file_id, expr.syntax(), None);
-        resolve_enum_def(ctx.db, &analyzer, &expr)?
-    };
-    let variant_list = enum_def.variant_list()?;
+    let analyzer = hir::SourceAnalyzer::new(ctx.db, ctx.frange.file_id, expr.syntax(), None);
+    let match_expr_ty = analyzer.type_of(ctx.db, &expr)?;
+    let enum_def = analyzer.autoderef(ctx.db, match_expr_ty).find_map(|ty| match ty.as_adt() {
+        Some((AdtDef::Enum(e), _)) => Some(e),
+        _ => None,
+    })?;
+    let enum_name = enum_def.name(ctx.db)?;
+    let db = ctx.db;
 
     ctx.add_action(AssistId("fill_match_arms"), "fill match arms", |edit| {
-        let variants = variant_list.variants();
-        let arms = variants.into_iter().filter_map(build_pat).map(|pat| {
-            AstBuilder::<ast::MatchArm>::from_pieces(
-                iter::once(pat),
-                &AstBuilder::<ast::Expr>::unit(),
-            )
-        });
-        let new_arm_list = AstBuilder::<ast::MatchArmList>::from_arms(arms);
+        let mut buf = format!("match {} {{\n", expr.syntax().text().to_string());
+        let variants = enum_def.variants(db);
+        for variant in variants {
+            let name = match variant.name(db) {
+                Some(it) => it,
+                None => continue,
+            };
+            write!(&mut buf, "    {}::{}", enum_name, name.to_string()).unwrap();
+
+            let pat = variant
+                .fields(db)
+                .into_iter()
+                .map(|field| {
+                    let name = field.name(db).to_string();
+                    let src = field.source(db);
+                    match src.ast {
+                        FieldSource::Named(_) => name,
+                        FieldSource::Pos(_) => "_".to_string(),
+                    }
+                })
+                .collect::<Vec<_>>();
 
+            match pat.first().map(|s| s.as_str()) {
+                Some("_") => write!(&mut buf, "({})", pat.join(", ")).unwrap(),
+                Some(_) => write!(&mut buf, "{{{}}}", pat.join(", ")).unwrap(),
+                None => (),
+            };
+
+            buf.push_str(" => (),\n");
+        }
+        buf.push_str("}");
         edit.target(match_expr.syntax().text_range());
         edit.set_cursor(expr.syntax().text_range().start());
-        edit.replace_node_and_indent(match_arm_list.syntax(), new_arm_list.syntax().text());
+        edit.replace_node_and_indent(match_expr.syntax(), buf);
     });
 
     ctx.build()
 }
 
-fn is_trivial(arm: &ast::MatchArm) -> bool {
-    arm.pats().any(|pat| match pat {
-        ast::Pat::PlaceholderPat(..) => true,
-        _ => false,
-    })
-}
-
-fn resolve_enum_def(
-    db: &impl HirDatabase,
-    analyzer: &hir::SourceAnalyzer,
-    expr: &ast::Expr,
-) -> Option<ast::EnumDef> {
-    let expr_ty = analyzer.type_of(db, &expr)?;
-
-    analyzer.autoderef(db, expr_ty).find_map(|ty| match ty.as_adt() {
-        Some((AdtDef::Enum(e), _)) => Some(e.source(db).ast),
-        _ => None,
-    })
-}
-
-fn build_pat(var: ast::EnumVariant) -> Option<ast::Pat> {
-    let path = &AstBuilder::<ast::Path>::from_pieces(var.parent_enum().name()?, var.name()?);
-
-    let pat: ast::Pat = match var.kind() {
-        ast::StructKind::Tuple(field_list) => {
-            let pats = iter::repeat(AstBuilder::<ast::PlaceholderPat>::placeholder().into())
-                .take(field_list.fields().count());
-            AstBuilder::<ast::TupleStructPat>::from_pieces(path, pats).into()
-        }
-        ast::StructKind::Named(field_list) => {
-            let pats = field_list
-                .fields()
-                .map(|f| AstBuilder::<ast::BindPat>::from_name(&f.name().unwrap()).into());
-            AstBuilder::<ast::RecordPat>::from_pieces(path, pats).into()
-        }
-        ast::StructKind::Unit => AstBuilder::<ast::PathPat>::from_path(path).into(),
-    };
-
-    Some(pat)
-}
-
 #[cfg(test)]
 mod tests {
     use crate::helpers::{check_assist, check_assist_target};
@@ -102,7 +108,7 @@ mod tests {
                 Bs,
                 Cs(String),
                 Ds(String, String),
-                Es{ x: usize, y: usize }
+                Es{x: usize, y: usize}
             }
 
             fn main() {
@@ -116,7 +122,7 @@ mod tests {
                 Bs,
                 Cs(String),
                 Ds(String, String),
-                Es{ x: usize, y: usize }
+                Es{x: usize, y: usize}
             }
 
             fn main() {
@@ -126,7 +132,7 @@ mod tests {
                     A::Bs => (),
                     A::Cs(_) => (),
                     A::Ds(_, _) => (),
-                    A::Es{ x, y } => (),
+                    A::Es{x, y} => (),
                 }
             }
             "#,
@@ -164,7 +170,7 @@ mod tests {
             fill_match_arms,
             r#"
             enum A {
-                Es{ x: usize, y: usize }
+                Es{x: usize, y: usize}
             }
 
             fn foo(a: &mut A) {
@@ -174,12 +180,57 @@ mod tests {
             "#,
             r#"
             enum A {
-                Es{ x: usize, y: usize }
+                Es{x: usize, y: usize}
             }
 
             fn foo(a: &mut A) {
                 match <|>a {
-                    A::Es{ x, y } => (),
+                    A::Es{x, y} => (),
+                }
+            }
+            "#,
+        );
+
+        check_assist(
+            fill_match_arms,
+            r#"
+            enum E { X, Y}
+
+            fn main() {
+                match &E::X<|>
+            }
+            "#,
+            r#"
+            enum E { X, Y}
+
+            fn main() {
+                match <|>&E::X {
+                    E::X => (),
+                    E::Y => (),
+                }
+            }
+            "#,
+        );
+    }
+
+    #[test]
+    fn fill_match_arms_no_body() {
+        check_assist(
+            fill_match_arms,
+            r#"
+            enum E { X, Y}
+
+            fn main() {
+                match E::X<|>
+            }
+            "#,
+            r#"
+            enum E { X, Y}
+
+            fn main() {
+                match <|>E::X {
+                    E::X => (),
+                    E::Y => (),
                 }
             }
             "#,
@@ -191,7 +242,7 @@ mod tests {
         check_assist_target(
             fill_match_arms,
             r#"
-            enum E { X, Y }
+            enum E { X, Y}
 
             fn main() {
                 match E::X<|> {}
diff --git a/crates/ra_batch/Cargo.toml b/crates/ra_batch/Cargo.toml
index 5fc2703ee9..8e23826a41 100644
--- a/crates/ra_batch/Cargo.toml
+++ b/crates/ra_batch/Cargo.toml
@@ -7,9 +7,8 @@ authors = ["rust-analyzer developers"]
 [dependencies]
 log = "0.4.5"
 rustc-hash = "1.0"
-crossbeam-channel = "0.3.5"
 
-ra_vfs = "0.3.0"
+ra_vfs = "0.2.0"
 ra_vfs_glob = { path = "../ra_vfs_glob" }
 ra_db = { path = "../ra_db" }
 ra_ide_api = { path = "../ra_ide_api" }
diff --git a/crates/ra_batch/src/lib.rs b/crates/ra_batch/src/lib.rs
index 4e5bad0443..f458ea3003 100644
--- a/crates/ra_batch/src/lib.rs
+++ b/crates/ra_batch/src/lib.rs
@@ -2,11 +2,10 @@ use std::{collections::HashSet, error::Error, path::Path};
 
 use rustc_hash::FxHashMap;
 
-use crossbeam_channel::{unbounded, Receiver};
 use ra_db::{CrateGraph, FileId, SourceRootId};
 use ra_ide_api::{AnalysisChange, AnalysisHost, FeatureFlags};
 use ra_project_model::{PackageRoot, ProjectWorkspace};
-use ra_vfs::{RootEntry, Vfs, VfsChange, VfsTask};
+use ra_vfs::{RootEntry, Vfs, VfsChange};
 use ra_vfs_glob::RustPackageFilterBuilder;
 
 type Result<T> = std::result::Result<T, Box<dyn Error + Send + Sync>>;
@@ -22,8 +21,6 @@ pub fn load_cargo(root: &Path) -> Result<(AnalysisHost, FxHashMap<SourceRootId,
     let root = std::env::current_dir()?.join(root);
     let ws = ProjectWorkspace::discover(root.as_ref())?;
     let project_roots = ws.to_roots();
-    let (sender, receiver) = unbounded();
-    let sender = Box::new(move |t| sender.send(t).unwrap());
     let (mut vfs, roots) = Vfs::new(
         project_roots
             .iter()
@@ -36,7 +33,6 @@ pub fn load_cargo(root: &Path) -> Result<(AnalysisHost, FxHashMap<SourceRootId,
                 )
             })
             .collect(),
-        sender,
     );
     let crate_graph = ws.to_crate_graph(&mut |path: &Path| {
         let vfs_file = vfs.load(path);
@@ -57,7 +53,7 @@ pub fn load_cargo(root: &Path) -> Result<(AnalysisHost, FxHashMap<SourceRootId,
             (source_root_id, project_root)
         })
         .collect::<FxHashMap<_, _>>();
-    let host = load(&source_roots, crate_graph, &mut vfs, receiver);
+    let host = load(&source_roots, crate_graph, &mut vfs);
     Ok((host, source_roots))
 }
 
@@ -65,7 +61,6 @@ pub fn load(
     source_roots: &FxHashMap<SourceRootId, PackageRoot>,
     crate_graph: CrateGraph,
     vfs: &mut Vfs,
-    receiver: Receiver<VfsTask>,
 ) -> AnalysisHost {
     let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::<usize>().ok());
     let mut host = AnalysisHost::new(lru_cap, FeatureFlags::default());
@@ -73,6 +68,7 @@ pub fn load(
     analysis_change.set_crate_graph(crate_graph);
 
     // wait until Vfs has loaded all roots
+    let receiver = vfs.task_receiver().clone();
     let mut roots_loaded = HashSet::new();
     for task in receiver {
         vfs.handle_task(task);
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 66a58efed3..89fc1d1a1c 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -318,8 +318,8 @@ pub struct StructField {
 
 #[derive(Debug)]
 pub enum FieldSource {
-    Named(ast::RecordFieldDef),
-    Pos(ast::TupleFieldDef),
+    Named(ast::NamedFieldDef),
+    Pos(ast::PosFieldDef),
 }
 
 impl StructField {
diff --git a/crates/ra_hir/src/diagnostics.rs b/crates/ra_hir/src/diagnostics.rs
index 475dd5766e..f6240830f8 100644
--- a/crates/ra_hir/src/diagnostics.rs
+++ b/crates/ra_hir/src/diagnostics.rs
@@ -79,7 +79,7 @@ impl<'a> DiagnosticSink<'a> {
 #[derive(Debug)]
 pub struct NoSuchField {
     pub file: HirFileId,
-    pub field: AstPtr<ast::RecordField>,
+    pub field: AstPtr<ast::NamedField>,
 }
 
 impl Diagnostic for NoSuchField {
@@ -118,7 +118,7 @@ impl Diagnostic for UnresolvedModule {
 #[derive(Debug)]
 pub struct MissingFields {
     pub file: HirFileId,
-    pub field_list: AstPtr<ast::RecordFieldList>,
+    pub field_list: AstPtr<ast::NamedFieldList>,
     pub missed_fields: Vec<Name>,
 }
 
@@ -135,39 +135,11 @@ impl Diagnostic for MissingFields {
 }
 
 impl AstDiagnostic for MissingFields {
-    type AST = ast::RecordFieldList;
+    type AST = ast::NamedFieldList;
 
     fn ast(&self, db: &impl HirDatabase) -> Self::AST {
         let root = db.parse_or_expand(self.source().file_id).unwrap();
         let node = self.source().ast.to_node(&root);
-        ast::RecordFieldList::cast(node).unwrap()
-    }
-}
-
-#[derive(Debug)]
-pub struct MissingOkInTailExpr {
-    pub file: HirFileId,
-    pub expr: AstPtr<ast::Expr>,
-}
-
-impl Diagnostic for MissingOkInTailExpr {
-    fn message(&self) -> String {
-        "wrap return expression in Ok".to_string()
-    }
-    fn source(&self) -> Source<SyntaxNodePtr> {
-        Source { file_id: self.file, ast: self.expr.into() }
-    }
-    fn as_any(&self) -> &(dyn Any + Send + 'static) {
-        self
-    }
-}
-
-impl AstDiagnostic for MissingOkInTailExpr {
-    type AST = ast::Expr;
-
-    fn ast(&self, db: &impl HirDatabase) -> Self::AST {
-        let root = db.parse_or_expand(self.file).unwrap();
-        let node = self.source().ast.to_node(&root);
-        ast::Expr::cast(node).unwrap()
+        ast::NamedFieldList::cast(node).unwrap()
     }
 }
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index 7cdc7555c5..328d635d45 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -60,7 +60,7 @@ pub struct BodySourceMap {
     expr_map_back: ArenaMap<ExprId, SyntaxNodePtr>,
     pat_map: FxHashMap<PatPtr, PatId>,
     pat_map_back: ArenaMap<PatId, PatPtr>,
-    field_map: FxHashMap<(ExprId, usize), AstPtr<ast::RecordField>>,
+    field_map: FxHashMap<(ExprId, usize), AstPtr<ast::NamedField>>,
 }
 
 type PatPtr = Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>;
@@ -148,7 +148,7 @@ impl BodySourceMap {
         self.pat_map.get(&Either::A(AstPtr::new(node))).cloned()
     }
 
-    pub(crate) fn field_syntax(&self, expr: ExprId, field: usize) -> AstPtr<ast::RecordField> {
+    pub(crate) fn field_syntax(&self, expr: ExprId, field: usize) -> AstPtr<ast::NamedField> {
         self.field_map[&(expr, field)]
     }
 }
@@ -210,9 +210,9 @@ pub enum Expr {
     Return {
         expr: Option<ExprId>,
     },
-    RecordLit {
+    StructLit {
         path: Option<Path>,
-        fields: Vec<RecordLitField>,
+        fields: Vec<StructLitField>,
         spread: Option<ExprId>,
     },
     Field {
@@ -316,7 +316,7 @@ pub struct MatchArm {
 }
 
 #[derive(Debug, Clone, Eq, PartialEq)]
-pub struct RecordLitField {
+pub struct StructLitField {
     pub name: Name,
     pub expr: ExprId,
 }
@@ -388,7 +388,7 @@ impl Expr {
                     f(*expr);
                 }
             }
-            Expr::RecordLit { fields, spread, .. } => {
+            Expr::StructLit { fields, spread, .. } => {
                 for field in fields {
                     f(field.expr);
                 }
@@ -474,7 +474,7 @@ impl BindingAnnotation {
 }
 
 #[derive(Debug, Clone, Eq, PartialEq)]
-pub struct RecordFieldPat {
+pub struct FieldPat {
     pub(crate) name: Name,
     pub(crate) pat: PatId,
 }
@@ -487,7 +487,7 @@ pub enum Pat {
     Tuple(Vec<PatId>),
     Struct {
         path: Option<Path>,
-        args: Vec<RecordFieldPat>,
+        args: Vec<FieldPat>,
         // FIXME: 'ellipsis' option
     },
     Range {
@@ -746,14 +746,14 @@ where
                 let expr = e.expr().map(|e| self.collect_expr(e));
                 self.alloc_expr(Expr::Return { expr }, syntax_ptr)
             }
-            ast::Expr::RecordLit(e) => {
+            ast::Expr::StructLit(e) => {
                 let path = e.path().and_then(Path::from_ast);
                 let mut field_ptrs = Vec::new();
-                let record_lit = if let Some(nfl) = e.record_field_list() {
+                let struct_lit = if let Some(nfl) = e.named_field_list() {
                     let fields = nfl
                         .fields()
                         .inspect(|field| field_ptrs.push(AstPtr::new(field)))
-                        .map(|field| RecordLitField {
+                        .map(|field| StructLitField {
                             name: field
                                 .name_ref()
                                 .map(|nr| nr.as_name())
@@ -776,12 +776,12 @@ where
                         })
                         .collect();
                     let spread = nfl.spread().map(|s| self.collect_expr(s));
-                    Expr::RecordLit { path, fields, spread }
+                    Expr::StructLit { path, fields, spread }
                 } else {
-                    Expr::RecordLit { path, fields: Vec::new(), spread: None }
+                    Expr::StructLit { path, fields: Vec::new(), spread: None }
                 };
 
-                let res = self.alloc_expr(record_lit, syntax_ptr);
+                let res = self.alloc_expr(struct_lit, syntax_ptr);
                 for (i, ptr) in field_ptrs.into_iter().enumerate() {
                     self.source_map.field_map.insert((res, i), ptr);
                 }
@@ -994,25 +994,25 @@ where
                 Pat::Tuple(args)
             }
             ast::Pat::PlaceholderPat(_) => Pat::Wild,
-            ast::Pat::RecordPat(p) => {
+            ast::Pat::StructPat(p) => {
                 let path = p.path().and_then(Path::from_ast);
-                let record_field_pat_list =
-                    p.record_field_pat_list().expect("every struct should have a field list");
-                let mut fields: Vec<_> = record_field_pat_list
+                let field_pat_list =
+                    p.field_pat_list().expect("every struct should have a field list");
+                let mut fields: Vec<_> = field_pat_list
                     .bind_pats()
                     .filter_map(|bind_pat| {
                         let ast_pat =
                             ast::Pat::cast(bind_pat.syntax().clone()).expect("bind pat is a pat");
                         let pat = self.collect_pat(ast_pat);
                         let name = bind_pat.name()?.as_name();
-                        Some(RecordFieldPat { name, pat })
+                        Some(FieldPat { name, pat })
                     })
                     .collect();
-                let iter = record_field_pat_list.record_field_pats().filter_map(|f| {
+                let iter = field_pat_list.field_pats().filter_map(|f| {
                     let ast_pat = f.pat()?;
                     let pat = self.collect_pat(ast_pat);
                     let name = f.name()?.as_name();
-                    Some(RecordFieldPat { name, pat })
+                    Some(FieldPat { name, pat })
                 });
                 fields.extend(iter);
 
@@ -1020,7 +1020,6 @@ where
             }
 
             // FIXME: implement
-            ast::Pat::BoxPat(_) => Pat::Missing,
             ast::Pat::LiteralPat(_) => Pat::Missing,
             ast::Pat::SlicePat(_) | ast::Pat::RangePat(_) => Pat::Missing,
         };
diff --git a/crates/ra_hir/src/expr/validation.rs b/crates/ra_hir/src/expr/validation.rs
index 5d9d59ff89..82a06ca25c 100644
--- a/crates/ra_hir/src/expr/validation.rs
+++ b/crates/ra_hir/src/expr/validation.rs
@@ -1,19 +1,16 @@
 use rustc_hash::FxHashSet;
 use std::sync::Arc;
 
-use ra_syntax::ast::{AstNode, RecordLit};
+use ra_syntax::ast::{AstNode, StructLit};
 
-use super::{Expr, ExprId, RecordLitField};
+use super::{Expr, ExprId, StructLitField};
 use crate::{
     adt::AdtDef,
-    diagnostics::{DiagnosticSink, MissingFields, MissingOkInTailExpr},
+    diagnostics::{DiagnosticSink, MissingFields},
     expr::AstPtr,
-    name,
-    path::{PathKind, PathSegment},
-    ty::{ApplicationTy, InferenceResult, Ty, TypeCtor},
-    Function, HasSource, HirDatabase, ModuleDef, Name, Path, PerNs, Resolution,
+    ty::InferenceResult,
+    Function, HasSource, HirDatabase, Name, Path,
 };
-use ra_syntax::ast;
 
 pub(crate) struct ExprValidator<'a, 'b: 'a> {
     func: Function,
@@ -32,24 +29,18 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
 
     pub(crate) fn validate_body(&mut self, db: &impl HirDatabase) {
         let body = self.func.body(db);
-
         for e in body.exprs() {
-            if let (id, Expr::RecordLit { path, fields, spread }) = e {
-                self.validate_record_literal(id, path, fields, *spread, db);
+            if let (id, Expr::StructLit { path, fields, spread }) = e {
+                self.validate_struct_literal(id, path, fields, *spread, db);
             }
         }
-
-        let body_expr = &body[body.body_expr()];
-        if let Expr::Block { statements: _, tail: Some(t) } = body_expr {
-            self.validate_results_in_tail_expr(*t, db);
-        }
     }
 
-    fn validate_record_literal(
+    fn validate_struct_literal(
         &mut self,
         id: ExprId,
         _path: &Option<Path>,
-        fields: &[RecordLitField],
+        fields: &[StructLitField],
         spread: Option<ExprId>,
         db: &impl HirDatabase,
     ) {
@@ -85,8 +76,8 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
         if let Some(field_list_node) = source_map
             .expr_syntax(id)
             .map(|ptr| ptr.to_node(source_file.syntax()))
-            .and_then(RecordLit::cast)
-            .and_then(|lit| lit.record_field_list())
+            .and_then(StructLit::cast)
+            .and_then(|lit| lit.named_field_list())
         {
             let field_list_ptr = AstPtr::new(&field_list_node);
             self.sink.push(MissingFields {
@@ -96,42 +87,4 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
             })
         }
     }
-
-    fn validate_results_in_tail_expr(&mut self, id: ExprId, db: &impl HirDatabase) {
-        let mismatch = match self.infer.type_mismatch_for_expr(id) {
-            Some(m) => m,
-            None => return,
-        };
-
-        let std_result_path = Path {
-            kind: PathKind::Abs,
-            segments: vec![
-                PathSegment { name: name::STD, args_and_bindings: None },
-                PathSegment { name: name::RESULT_MOD, args_and_bindings: None },
-                PathSegment { name: name::RESULT_TYPE, args_and_bindings: None },
-            ],
-        };
-
-        let resolver = self.func.resolver(db);
-        let std_result_enum =
-            match resolver.resolve_path_segments(db, &std_result_path).into_fully_resolved() {
-                PerNs { types: Some(Resolution::Def(ModuleDef::Enum(e))), .. } => e,
-                _ => return,
-            };
-
-        let std_result_ctor = TypeCtor::Adt(AdtDef::Enum(std_result_enum));
-        let params = match &mismatch.expected {
-            Ty::Apply(ApplicationTy { ctor, parameters }) if ctor == &std_result_ctor => parameters,
-            _ => return,
-        };
-
-        if params.len() == 2 && &params[0] == &mismatch.actual {
-            let source_map = self.func.body_source_map(db);
-            let file_id = self.func.source(db).file_id;
-
-            if let Some(expr) = source_map.expr_syntax(id).and_then(|n| n.cast::<ast::Expr>()) {
-                self.sink.push(MissingOkInTailExpr { file: file_id, expr });
-            }
-        }
-    }
 }
diff --git a/crates/ra_hir/src/name.rs b/crates/ra_hir/src/name.rs
index 9c4822d917..6d14eea8ec 100644
--- a/crates/ra_hir/src/name.rs
+++ b/crates/ra_hir/src/name.rs
@@ -120,8 +120,6 @@ pub(crate) const TRY: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"Try")
 pub(crate) const OK: Name = Name::new(SmolStr::new_inline_from_ascii(2, b"Ok"));
 pub(crate) const FUTURE_MOD: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"future"));
 pub(crate) const FUTURE_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Future"));
-pub(crate) const RESULT_MOD: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"result"));
-pub(crate) const RESULT_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Result"));
 pub(crate) const OUTPUT: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Output"));
 
 fn resolve_name(text: &SmolStr) -> SmolStr {
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 56ff7da3ab..e86716d74c 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -278,13 +278,13 @@ impl SourceAnalyzer {
         self.infer.as_ref()?.field_resolution(expr_id)
     }
 
-    pub fn resolve_record_literal(&self, record_lit: &ast::RecordLit) -> Option<crate::VariantDef> {
-        let expr_id = self.body_source_map.as_ref()?.node_expr(&record_lit.clone().into())?;
+    pub fn resolve_struct_literal(&self, struct_lit: &ast::StructLit) -> Option<crate::VariantDef> {
+        let expr_id = self.body_source_map.as_ref()?.node_expr(&struct_lit.clone().into())?;
         self.infer.as_ref()?.variant_resolution_for_expr(expr_id)
     }
 
-    pub fn resolve_record_pattern(&self, record_pat: &ast::RecordPat) -> Option<crate::VariantDef> {
-        let pat_id = self.body_source_map.as_ref()?.node_pat(&record_pat.clone().into())?;
+    pub fn resolve_struct_pattern(&self, struct_pat: &ast::StructPat) -> Option<crate::VariantDef> {
+        let pat_id = self.body_source_map.as_ref()?.node_pat(&struct_pat.clone().into())?;
         self.infer.as_ref()?.variant_resolution_for_pat(pat_id)
     }
 
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index d94e8154b0..cca59538ac 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -37,8 +37,8 @@ use crate::{
     code_model::{ModuleDef::Trait, TypeAlias},
     diagnostics::DiagnosticSink,
     expr::{
-        self, Array, BinaryOp, BindingAnnotation, Body, Expr, ExprId, Literal, Pat, PatId,
-        RecordFieldPat, Statement, UnaryOp,
+        self, Array, BinaryOp, BindingAnnotation, Body, Expr, ExprId, FieldPat, Literal, Pat,
+        PatId, Statement, UnaryOp,
     },
     generics::{GenericParams, HasGenericParams},
     name,
@@ -106,13 +106,6 @@ impl Default for BindingMode {
     }
 }
 
-/// A mismatch between an expected and an inferred type.
-#[derive(Clone, PartialEq, Eq, Debug, Hash)]
-pub struct TypeMismatch {
-    pub expected: Ty,
-    pub actual: Ty,
-}
-
 /// The result of type inference: A mapping from expressions and patterns to types.
 #[derive(Clone, PartialEq, Eq, Debug, Default)]
 pub struct InferenceResult {
@@ -127,7 +120,6 @@ pub struct InferenceResult {
     diagnostics: Vec<InferenceDiagnostic>,
     pub(super) type_of_expr: ArenaMap<ExprId, Ty>,
     pub(super) type_of_pat: ArenaMap<PatId, Ty>,
-    pub(super) type_mismatches: ArenaMap<ExprId, TypeMismatch>,
 }
 
 impl InferenceResult {
@@ -149,9 +141,6 @@ impl InferenceResult {
     pub fn assoc_resolutions_for_pat(&self, id: PatId) -> Option<ImplItem> {
         self.assoc_resolutions.get(&id.into()).copied()
     }
-    pub fn type_mismatch_for_expr(&self, expr: ExprId) -> Option<&TypeMismatch> {
-        self.type_mismatches.get(expr)
-    }
     pub(crate) fn add_diagnostics(
         &self,
         db: &impl HirDatabase,
@@ -716,10 +705,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
         ty
     }
 
-    fn infer_record_pat(
+    fn infer_struct_pat(
         &mut self,
         path: Option<&Path>,
-        subpats: &[RecordFieldPat],
+        subpats: &[FieldPat],
         expected: &Ty,
         default_bm: BindingMode,
         id: PatId,
@@ -811,7 +800,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
                 self.infer_tuple_struct_pat(p.as_ref(), subpats, expected, default_bm)
             }
             Pat::Struct { path: ref p, args: ref fields } => {
-                self.infer_record_pat(p.as_ref(), fields, expected, default_bm, pat)
+                self.infer_struct_pat(p.as_ref(), fields, expected, default_bm, pat)
             }
             Pat::Path(path) => {
                 // FIXME use correct resolver for the surrounding expression
@@ -1114,7 +1103,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
                 }
                 Ty::simple(TypeCtor::Never)
             }
-            Expr::RecordLit { path, fields, spread } => {
+            Expr::StructLit { path, fields, spread } => {
                 let (ty, def_id) = self.resolve_variant(path.as_ref());
                 if let Some(variant) = def_id {
                     self.write_variant_resolution(tgt_expr.into(), variant);
@@ -1356,15 +1345,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
         };
         // use a new type variable if we got Ty::Unknown here
         let ty = self.insert_type_vars_shallow(ty);
-        let could_unify = self.unify(&ty, &expected.ty);
+        self.unify(&ty, &expected.ty);
         let ty = self.resolve_ty_as_possible(&mut vec![], ty);
         self.write_expr_ty(tgt_expr, ty.clone());
-        if !could_unify {
-            self.result.type_mismatches.insert(
-                tgt_expr,
-                TypeMismatch { expected: expected.ty.clone(), actual: ty.clone() },
-            );
-        }
         ty
     }
 
diff --git a/crates/ra_ide_api/src/completion.rs b/crates/ra_ide_api/src/completion.rs
index a4f080adc6..a6b68be75e 100644
--- a/crates/ra_ide_api/src/completion.rs
+++ b/crates/ra_ide_api/src/completion.rs
@@ -3,8 +3,8 @@ mod completion_context;
 mod presentation;
 
 mod complete_dot;
-mod complete_record_literal;
-mod complete_record_pattern;
+mod complete_struct_literal;
+mod complete_struct_pattern;
 mod complete_pattern;
 mod complete_fn_param;
 mod complete_keyword;
@@ -65,8 +65,8 @@ pub(crate) fn completions(db: &db::RootDatabase, position: FilePosition) -> Opti
     complete_path::complete_path(&mut acc, &ctx);
     complete_scope::complete_scope(&mut acc, &ctx);
     complete_dot::complete_dot(&mut acc, &ctx);
-    complete_record_literal::complete_record_literal(&mut acc, &ctx);
-    complete_record_pattern::complete_record_pattern(&mut acc, &ctx);
+    complete_struct_literal::complete_struct_literal(&mut acc, &ctx);
+    complete_struct_pattern::complete_struct_pattern(&mut acc, &ctx);
     complete_pattern::complete_pattern(&mut acc, &ctx);
     complete_postfix::complete_postfix(&mut acc, &ctx);
     Some(acc)
diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs
index 27256f8796..d43ff2eecc 100644
--- a/crates/ra_ide_api/src/completion/complete_dot.rs
+++ b/crates/ra_ide_api/src/completion/complete_dot.rs
@@ -45,7 +45,7 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty)
                 // FIXME unions
                 TypeCtor::Tuple { .. } => {
                     for (i, ty) in a_ty.parameters.iter().enumerate() {
-                        acc.add_tuple_field(ctx, i, ty);
+                        acc.add_pos_field(ctx, i, ty);
                     }
                 }
                 _ => {}
diff --git a/crates/ra_ide_api/src/completion/complete_record_literal.rs b/crates/ra_ide_api/src/completion/complete_struct_literal.rs
similarity index 89%
rename from crates/ra_ide_api/src/completion/complete_record_literal.rs
rename to crates/ra_ide_api/src/completion/complete_struct_literal.rs
index 6b929a8acf..6aa41f4985 100644
--- a/crates/ra_ide_api/src/completion/complete_record_literal.rs
+++ b/crates/ra_ide_api/src/completion/complete_struct_literal.rs
@@ -3,11 +3,11 @@ use hir::Substs;
 use crate::completion::{CompletionContext, Completions};
 
 /// Complete fields in fields literals.
-pub(super) fn complete_record_literal(acc: &mut Completions, ctx: &CompletionContext) {
-    let (ty, variant) = match ctx.record_lit_syntax.as_ref().and_then(|it| {
+pub(super) fn complete_struct_literal(acc: &mut Completions, ctx: &CompletionContext) {
+    let (ty, variant) = match ctx.struct_lit_syntax.as_ref().and_then(|it| {
         Some((
             ctx.analyzer.type_of(ctx.db, &it.clone().into())?,
-            ctx.analyzer.resolve_record_literal(it)?,
+            ctx.analyzer.resolve_struct_literal(it)?,
         ))
     }) {
         Some(it) => it,
@@ -30,7 +30,7 @@ mod tests {
     }
 
     #[test]
-    fn test_record_literal_field() {
+    fn test_struct_literal_field() {
         let completions = complete(
             r"
             struct A { the_field: u32 }
@@ -54,7 +54,7 @@ mod tests {
     }
 
     #[test]
-    fn test_record_literal_enum_variant() {
+    fn test_struct_literal_enum_variant() {
         let completions = complete(
             r"
             enum E {
@@ -80,7 +80,7 @@ mod tests {
     }
 
     #[test]
-    fn test_record_literal_two_structs() {
+    fn test_struct_literal_two_structs() {
         let completions = complete(
             r"
             struct A { a: u32 }
@@ -106,7 +106,7 @@ mod tests {
     }
 
     #[test]
-    fn test_record_literal_generic_struct() {
+    fn test_struct_literal_generic_struct() {
         let completions = complete(
             r"
             struct A<T> { a: T }
diff --git a/crates/ra_ide_api/src/completion/complete_record_pattern.rs b/crates/ra_ide_api/src/completion/complete_struct_pattern.rs
similarity index 89%
rename from crates/ra_ide_api/src/completion/complete_record_pattern.rs
rename to crates/ra_ide_api/src/completion/complete_struct_pattern.rs
index 8c8b47ea46..d0dde59305 100644
--- a/crates/ra_ide_api/src/completion/complete_record_pattern.rs
+++ b/crates/ra_ide_api/src/completion/complete_struct_pattern.rs
@@ -2,11 +2,11 @@ use hir::Substs;
 
 use crate::completion::{CompletionContext, Completions};
 
-pub(super) fn complete_record_pattern(acc: &mut Completions, ctx: &CompletionContext) {
-    let (ty, variant) = match ctx.record_lit_pat.as_ref().and_then(|it| {
+pub(super) fn complete_struct_pattern(acc: &mut Completions, ctx: &CompletionContext) {
+    let (ty, variant) = match ctx.struct_lit_pat.as_ref().and_then(|it| {
         Some((
             ctx.analyzer.type_of_pat(ctx.db, &it.clone().into())?,
-            ctx.analyzer.resolve_record_pattern(it)?,
+            ctx.analyzer.resolve_struct_pattern(it)?,
         ))
     }) {
         Some(it) => it,
@@ -29,7 +29,7 @@ mod tests {
     }
 
     #[test]
-    fn test_record_pattern_field() {
+    fn test_struct_pattern_field() {
         let completions = complete(
             r"
             struct S { foo: u32 }
@@ -56,7 +56,7 @@ mod tests {
     }
 
     #[test]
-    fn test_record_pattern_enum_variant() {
+    fn test_struct_pattern_enum_variant() {
         let completions = complete(
             r"
             enum E {
diff --git a/crates/ra_ide_api/src/completion/completion_context.rs b/crates/ra_ide_api/src/completion/completion_context.rs
index 7139947b34..dfaa9ce696 100644
--- a/crates/ra_ide_api/src/completion/completion_context.rs
+++ b/crates/ra_ide_api/src/completion/completion_context.rs
@@ -20,8 +20,8 @@ pub(crate) struct CompletionContext<'a> {
     pub(super) module: Option<hir::Module>,
     pub(super) function_syntax: Option<ast::FnDef>,
     pub(super) use_item_syntax: Option<ast::UseItem>,
-    pub(super) record_lit_syntax: Option<ast::RecordLit>,
-    pub(super) record_lit_pat: Option<ast::RecordPat>,
+    pub(super) struct_lit_syntax: Option<ast::StructLit>,
+    pub(super) struct_lit_pat: Option<ast::StructPat>,
     pub(super) is_param: bool,
     /// If a name-binding or reference to a const in a pattern.
     /// Irrefutable patterns (like let) are excluded.
@@ -60,8 +60,8 @@ impl<'a> CompletionContext<'a> {
             module,
             function_syntax: None,
             use_item_syntax: None,
-            record_lit_syntax: None,
-            record_lit_pat: None,
+            struct_lit_syntax: None,
+            struct_lit_pat: None,
             is_param: false,
             is_pat_binding: false,
             is_trivial_path: false,
@@ -120,8 +120,8 @@ impl<'a> CompletionContext<'a> {
                 self.is_param = true;
                 return;
             }
-            if name.syntax().ancestors().find_map(ast::RecordFieldPatList::cast).is_some() {
-                self.record_lit_pat =
+            if name.syntax().ancestors().find_map(ast::FieldPatList::cast).is_some() {
+                self.struct_lit_pat =
                     find_node_at_offset(original_parse.tree().syntax(), self.offset);
             }
         }
@@ -129,8 +129,8 @@ impl<'a> CompletionContext<'a> {
 
     fn classify_name_ref(&mut self, original_file: SourceFile, name_ref: ast::NameRef) {
         let name_range = name_ref.syntax().text_range();
-        if name_ref.syntax().parent().and_then(ast::RecordField::cast).is_some() {
-            self.record_lit_syntax = find_node_at_offset(original_file.syntax(), self.offset);
+        if name_ref.syntax().parent().and_then(ast::NamedField::cast).is_some() {
+            self.struct_lit_syntax = find_node_at_offset(original_file.syntax(), self.offset);
         }
 
         let top_node = name_ref
diff --git a/crates/ra_ide_api/src/completion/presentation.rs b/crates/ra_ide_api/src/completion/presentation.rs
index 147ceda0c7..2b3f984829 100644
--- a/crates/ra_ide_api/src/completion/presentation.rs
+++ b/crates/ra_ide_api/src/completion/presentation.rs
@@ -28,7 +28,7 @@ impl Completions {
         .add_to(self);
     }
 
-    pub(crate) fn add_tuple_field(&mut self, ctx: &CompletionContext, field: usize, ty: &hir::Ty) {
+    pub(crate) fn add_pos_field(&mut self, ctx: &CompletionContext, field: usize, ty: &hir::Ty) {
         CompletionItem::new(CompletionKind::Reference, ctx.source_range(), field.to_string())
             .kind(CompletionItemKind::Field)
             .detail(ty.display(ctx.db).to_string())
diff --git a/crates/ra_ide_api/src/diagnostics.rs b/crates/ra_ide_api/src/diagnostics.rs
index 1a4882824f..98b840b267 100644
--- a/crates/ra_ide_api/src/diagnostics.rs
+++ b/crates/ra_ide_api/src/diagnostics.rs
@@ -9,7 +9,7 @@ use ra_assists::ast_editor::{AstBuilder, AstEditor};
 use ra_db::SourceDatabase;
 use ra_prof::profile;
 use ra_syntax::{
-    ast::{self, AstNode, RecordField},
+    ast::{self, AstNode, NamedField},
     Location, SyntaxNode, TextRange, T,
 };
 use ra_text_edit::{TextEdit, TextEditBuilder};
@@ -62,7 +62,7 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic>
         let node = d.ast(db);
         let mut ast_editor = AstEditor::new(node);
         for f in d.missed_fields.iter() {
-            ast_editor.append_field(&AstBuilder::<RecordField>::from_name(f));
+            ast_editor.append_field(&AstBuilder::<NamedField>::from_name(f));
         }
 
         let mut builder = TextEditBuilder::default();
@@ -75,19 +75,6 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic>
             severity: Severity::Error,
             fix: Some(fix),
         })
-    })
-    .on::<hir::diagnostics::MissingOkInTailExpr, _>(|d| {
-        let node = d.ast(db);
-        let mut builder = TextEditBuilder::default();
-        let replacement = format!("Ok({})", node.syntax());
-        builder.replace(node.syntax().text_range(), replacement);
-        let fix = SourceChange::source_file_edit_from("wrap with ok", file_id, builder.finish());
-        res.borrow_mut().push(Diagnostic {
-            range: d.highlight_range(),
-            message: d.message(),
-            severity: Severity::Error,
-            fix: Some(fix),
-        })
     });
     if let Some(m) = source_binder::module_from_file_id(db, file_id) {
         m.diagnostics(db, &mut sink);
@@ -154,20 +141,20 @@ fn check_struct_shorthand_initialization(
     file_id: FileId,
     node: &SyntaxNode,
 ) -> Option<()> {
-    let record_lit = ast::RecordLit::cast(node.clone())?;
-    let record_field_list = record_lit.record_field_list()?;
-    for record_field in record_field_list.fields() {
-        if let (Some(name_ref), Some(expr)) = (record_field.name_ref(), record_field.expr()) {
+    let struct_lit = ast::StructLit::cast(node.clone())?;
+    let named_field_list = struct_lit.named_field_list()?;
+    for named_field in named_field_list.fields() {
+        if let (Some(name_ref), Some(expr)) = (named_field.name_ref(), named_field.expr()) {
             let field_name = name_ref.syntax().text().to_string();
             let field_expr = expr.syntax().text().to_string();
             if field_name == field_expr {
                 let mut edit_builder = TextEditBuilder::default();
-                edit_builder.delete(record_field.syntax().text_range());
-                edit_builder.insert(record_field.syntax().text_range().start(), field_name);
+                edit_builder.delete(named_field.syntax().text_range());
+                edit_builder.insert(named_field.syntax().text_range().start(), field_name);
                 let edit = edit_builder.finish();
 
                 acc.push(Diagnostic {
-                    range: record_field.syntax().text_range(),
+                    range: named_field.syntax().text_range(),
                     message: "Shorthand struct initialization".to_string(),
                     severity: Severity::WeakWarning,
                     fix: Some(SourceChange::source_file_edit(
@@ -184,11 +171,10 @@ fn check_struct_shorthand_initialization(
 #[cfg(test)]
 mod tests {
     use insta::assert_debug_snapshot_matches;
-    use join_to_string::join;
     use ra_syntax::SourceFile;
     use test_utils::assert_eq_text;
 
-    use crate::mock_analysis::{analysis_and_position, single_file};
+    use crate::mock_analysis::single_file;
 
     use super::*;
 
@@ -217,48 +203,6 @@ mod tests {
         assert_eq_text!(after, &actual);
     }
 
-    /// Takes a multi-file input fixture with annotated cursor positions,
-    /// and checks that:
-    ///  * a diagnostic is produced
-    ///  * this diagnostic touches the input cursor position
-    ///  * that the contents of the file containing the cursor match `after` after the diagnostic fix is applied
-    fn check_apply_diagnostic_fix_from_position(fixture: &str, after: &str) {
-        let (analysis, file_position) = analysis_and_position(fixture);
-        let diagnostic = analysis.diagnostics(file_position.file_id).unwrap().pop().unwrap();
-        let mut fix = diagnostic.fix.unwrap();
-        let edit = fix.source_file_edits.pop().unwrap().edit;
-        let target_file_contents = analysis.file_text(file_position.file_id).unwrap();
-        let actual = edit.apply(&target_file_contents);
-
-        // Strip indent and empty lines from `after`, to match the behaviour of
-        // `parse_fixture` called from `analysis_and_position`.
-        let margin = fixture
-            .lines()
-            .filter(|it| it.trim_start().starts_with("//-"))
-            .map(|it| it.len() - it.trim_start().len())
-            .next()
-            .expect("empty fixture");
-        let after = join(after.lines().filter_map(|line| {
-            if line.len() > margin {
-                Some(&line[margin..])
-            } else {
-                None
-            }
-        }))
-        .separator("\n")
-        .suffix("\n")
-        .to_string();
-
-        assert_eq_text!(&after, &actual);
-        assert!(
-            diagnostic.range.start() <= file_position.offset
-                && diagnostic.range.end() >= file_position.offset,
-            "diagnostic range {} does not touch cursor position {}",
-            diagnostic.range,
-            file_position.offset
-        );
-    }
-
     fn check_apply_diagnostic_fix(before: &str, after: &str) {
         let (analysis, file_id) = single_file(before);
         let diagnostic = analysis.diagnostics(file_id).unwrap().pop().unwrap();
@@ -268,169 +212,12 @@ mod tests {
         assert_eq_text!(after, &actual);
     }
 
-    /// Takes a multi-file input fixture with annotated cursor position and checks that no diagnostics
-    /// apply to the file containing the cursor.
-    fn check_no_diagnostic_for_target_file(fixture: &str) {
-        let (analysis, file_position) = analysis_and_position(fixture);
-        let diagnostics = analysis.diagnostics(file_position.file_id).unwrap();
-        assert_eq!(diagnostics.len(), 0);
-    }
-
     fn check_no_diagnostic(content: &str) {
         let (analysis, file_id) = single_file(content);
         let diagnostics = analysis.diagnostics(file_id).unwrap();
         assert_eq!(diagnostics.len(), 0);
     }
 
-    #[test]
-    fn test_wrap_return_type() {
-        let before = r#"
-            //- /main.rs
-            use std::{string::String, result::Result::{self, Ok, Err}};
-
-            fn div(x: i32, y: i32) -> Result<i32, String> {
-                if y == 0 {
-                    return Err("div by zero".into());
-                }
-                x / y<|>
-            }
-
-            //- /std/lib.rs
-            pub mod string {
-                pub struct String { }
-            }
-            pub mod result {
-                pub enum Result<T, E> { Ok(T), Err(E) }
-            }
-        "#;
-        let after = r#"
-            use std::{string::String, result::Result::{self, Ok, Err}};
-
-            fn div(x: i32, y: i32) -> Result<i32, String> {
-                if y == 0 {
-                    return Err("div by zero".into());
-                }
-                Ok(x / y)
-            }
-        "#;
-        check_apply_diagnostic_fix_from_position(before, after);
-    }
-
-    #[test]
-    fn test_wrap_return_type_handles_generic_functions() {
-        let before = r#"
-            //- /main.rs
-            use std::result::Result::{self, Ok, Err};
-
-            fn div<T>(x: T) -> Result<T, i32> {
-                if x == 0 {
-                    return Err(7);
-                }
-                <|>x
-            }
-
-            //- /std/lib.rs
-            pub mod result {
-                pub enum Result<T, E> { Ok(T), Err(E) }
-            }
-        "#;
-        let after = r#"
-            use std::result::Result::{self, Ok, Err};
-
-            fn div<T>(x: T) -> Result<T, i32> {
-                if x == 0 {
-                    return Err(7);
-                }
-                Ok(x)
-            }
-        "#;
-        check_apply_diagnostic_fix_from_position(before, after);
-    }
-
-    #[test]
-    fn test_wrap_return_type_handles_type_aliases() {
-        let before = r#"
-            //- /main.rs
-            use std::{string::String, result::Result::{self, Ok, Err}};
-
-            type MyResult<T> = Result<T, String>;
-
-            fn div(x: i32, y: i32) -> MyResult<i32> {
-                if y == 0 {
-                    return Err("div by zero".into());
-                }
-                x <|>/ y
-            }
-
-            //- /std/lib.rs
-            pub mod string {
-                pub struct String { }
-            }
-            pub mod result {
-                pub enum Result<T, E> { Ok(T), Err(E) }
-            }
-        "#;
-        let after = r#"
-            use std::{string::String, result::Result::{self, Ok, Err}};
-
-            type MyResult<T> = Result<T, String>;
-            fn div(x: i32, y: i32) -> MyResult<i32> {
-                if y == 0 {
-                    return Err("div by zero".into());
-                }
-                Ok(x / y)
-            }
-        "#;
-        check_apply_diagnostic_fix_from_position(before, after);
-    }
-
-    #[test]
-    fn test_wrap_return_type_not_applicable_when_expr_type_does_not_match_ok_type() {
-        let content = r#"
-            //- /main.rs
-            use std::{string::String, result::Result::{self, Ok, Err}};
-
-            fn foo() -> Result<String, i32> {
-                0<|>
-            }
-
-            //- /std/lib.rs
-            pub mod string {
-                pub struct String { }
-            }
-            pub mod result {
-                pub enum Result<T, E> { Ok(T), Err(E) }
-            }
-        "#;
-        check_no_diagnostic_for_target_file(content);
-    }
-
-    #[test]
-    fn test_wrap_return_type_not_applicable_when_return_type_is_not_result() {
-        let content = r#"
-            //- /main.rs
-            use std::{string::String, result::Result::{self, Ok, Err}};
-
-            enum SomeOtherEnum {
-                Ok(i32),
-                Err(String),
-            }
-
-            fn foo() -> SomeOtherEnum {
-                0<|>
-            }
-
-            //- /std/lib.rs
-            pub mod string {
-                pub struct String { }
-            }
-            pub mod result {
-                pub enum Result<T, E> { Ok(T), Err(E) }
-            }
-        "#;
-        check_no_diagnostic_for_target_file(content);
-    }
-
     #[test]
     fn test_fill_struct_fields_empty() {
         let before = r"
diff --git a/crates/ra_ide_api/src/display/navigation_target.rs b/crates/ra_ide_api/src/display/navigation_target.rs
index c85214bb35..84fabdb9e1 100644
--- a/crates/ra_ide_api/src/display/navigation_target.rs
+++ b/crates/ra_ide_api/src/display/navigation_target.rs
@@ -314,7 +314,7 @@ pub(crate) fn docs_from_symbol(db: &RootDatabase, symbol: &FileSymbol) -> Option
         .visit(|it: ast::TypeAliasDef| it.doc_comment_text())
         .visit(|it: ast::ConstDef| it.doc_comment_text())
         .visit(|it: ast::StaticDef| it.doc_comment_text())
-        .visit(|it: ast::RecordFieldDef| it.doc_comment_text())
+        .visit(|it: ast::NamedFieldDef| it.doc_comment_text())
         .visit(|it: ast::EnumVariant| it.doc_comment_text())
         .visit(|it: ast::MacroCall| it.doc_comment_text())
         .accept(&node)?
@@ -336,7 +336,7 @@ pub(crate) fn description_from_symbol(db: &RootDatabase, symbol: &FileSymbol) ->
         .visit(|node: ast::TypeAliasDef| node.short_label())
         .visit(|node: ast::ConstDef| node.short_label())
         .visit(|node: ast::StaticDef| node.short_label())
-        .visit(|node: ast::RecordFieldDef| node.short_label())
+        .visit(|node: ast::NamedFieldDef| node.short_label())
         .visit(|node: ast::EnumVariant| node.short_label())
         .accept(&node)?
 }
diff --git a/crates/ra_ide_api/src/display/short_label.rs b/crates/ra_ide_api/src/display/short_label.rs
index b16d504e14..825a033eed 100644
--- a/crates/ra_ide_api/src/display/short_label.rs
+++ b/crates/ra_ide_api/src/display/short_label.rs
@@ -53,7 +53,7 @@ impl ShortLabel for ast::StaticDef {
     }
 }
 
-impl ShortLabel for ast::RecordFieldDef {
+impl ShortLabel for ast::NamedFieldDef {
     fn short_label(&self) -> Option<String> {
         short_label_from_ascribed_node(self, "")
     }
diff --git a/crates/ra_ide_api/src/display/structure.rs b/crates/ra_ide_api/src/display/structure.rs
index a2025ed591..b026dfa59d 100644
--- a/crates/ra_ide_api/src/display/structure.rs
+++ b/crates/ra_ide_api/src/display/structure.rs
@@ -124,7 +124,7 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
             let ty = td.type_ref();
             decl_with_type_ref(td, ty)
         })
-        .visit(decl_with_ascription::<ast::RecordFieldDef>)
+        .visit(decl_with_ascription::<ast::NamedFieldDef>)
         .visit(decl_with_ascription::<ast::ConstDef>)
         .visit(decl_with_ascription::<ast::StaticDef>)
         .visit(|im: ast::ImplBlock| {
@@ -222,7 +222,7 @@ fn very_obsolete() {}
         label: "x",
         navigation_range: [18; 19),
         node_range: [18; 24),
-        kind: RECORD_FIELD_DEF,
+        kind: NAMED_FIELD_DEF,
         detail: Some(
             "i32",
         ),
diff --git a/crates/ra_ide_api/src/extend_selection.rs b/crates/ra_ide_api/src/extend_selection.rs
index e990eb0d13..edbf622c11 100644
--- a/crates/ra_ide_api/src/extend_selection.rs
+++ b/crates/ra_ide_api/src/extend_selection.rs
@@ -18,11 +18,11 @@ pub(crate) fn extend_selection(db: &RootDatabase, frange: FileRange) -> TextRang
 fn try_extend_selection(root: &SyntaxNode, range: TextRange) -> Option<TextRange> {
     let string_kinds = [COMMENT, STRING, RAW_STRING, BYTE_STRING, RAW_BYTE_STRING];
     let list_kinds = [
-        RECORD_FIELD_PAT_LIST,
+        FIELD_PAT_LIST,
         MATCH_ARM_LIST,
-        RECORD_FIELD_DEF_LIST,
-        TUPLE_FIELD_DEF_LIST,
-        RECORD_FIELD_LIST,
+        NAMED_FIELD_DEF_LIST,
+        POS_FIELD_DEF_LIST,
+        NAMED_FIELD_LIST,
         ENUM_VARIANT_LIST,
         USE_TREE_LIST,
         TYPE_PARAM_LIST,
diff --git a/crates/ra_ide_api/src/folding_ranges.rs b/crates/ra_ide_api/src/folding_ranges.rs
index 3ab6c195e6..e60ae8cf62 100644
--- a/crates/ra_ide_api/src/folding_ranges.rs
+++ b/crates/ra_ide_api/src/folding_ranges.rs
@@ -81,14 +81,8 @@ fn fold_kind(kind: SyntaxKind) -> Option<FoldKind> {
     match kind {
         COMMENT => Some(FoldKind::Comment),
         USE_ITEM => Some(FoldKind::Imports),
-        RECORD_FIELD_DEF_LIST
-        | RECORD_FIELD_PAT_LIST
-        | ITEM_LIST
-        | EXTERN_ITEM_LIST
-        | USE_TREE_LIST
-        | BLOCK
-        | ENUM_VARIANT_LIST
-        | TOKEN_TREE => Some(FoldKind::Block),
+        NAMED_FIELD_DEF_LIST | FIELD_PAT_LIST | ITEM_LIST | EXTERN_ITEM_LIST | USE_TREE_LIST
+        | BLOCK | ENUM_VARIANT_LIST | TOKEN_TREE => Some(FoldKind::Block),
         _ => None,
     }
 }
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs
index 28529a2de0..ddd55a9c15 100644
--- a/crates/ra_ide_api/src/goto_definition.rs
+++ b/crates/ra_ide_api/src/goto_definition.rs
@@ -178,7 +178,7 @@ fn named_target(file_id: FileId, node: &SyntaxNode) -> Option<NavigationTarget>
                 node.short_label(),
             )
         })
-        .visit(|node: ast::RecordFieldDef| {
+        .visit(|node: ast::NamedFieldDef| {
             NavigationTarget::from_named(
                 file_id,
                 &node,
@@ -344,13 +344,13 @@ mod tests {
                 foo.spam<|>;
             }
             ",
-            "spam RECORD_FIELD_DEF FileId(1) [17; 26) [17; 21)",
+            "spam NAMED_FIELD_DEF FileId(1) [17; 26) [17; 21)",
         );
     }
 
     #[test]
-    fn goto_definition_works_for_record_fields() {
-        covers!(goto_definition_works_for_record_fields);
+    fn goto_definition_works_for_named_fields() {
+        covers!(goto_definition_works_for_named_fields);
         check_goto(
             "
             //- /lib.rs
@@ -364,7 +364,7 @@ mod tests {
                 }
             }
             ",
-            "spam RECORD_FIELD_DEF FileId(1) [17; 26) [17; 21)",
+            "spam NAMED_FIELD_DEF FileId(1) [17; 26) [17; 21)",
         );
     }
     #[test]
@@ -473,7 +473,7 @@ mod tests {
                 field<|>: string,
             }
             "#,
-            "field RECORD_FIELD_DEF FileId(1) [17; 30) [17; 22)",
+            "field NAMED_FIELD_DEF FileId(1) [17; 30) [17; 22)",
         );
 
         check_goto(
diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs
index 1981e62d35..2a5ac78215 100644
--- a/crates/ra_ide_api/src/hover.rs
+++ b/crates/ra_ide_api/src/hover.rs
@@ -197,7 +197,7 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
                 .visit(|node: ast::TraitDef| {
                     hover_text(node.doc_comment_text(), node.short_label())
                 })
-                .visit(|node: ast::RecordFieldDef| {
+                .visit(|node: ast::NamedFieldDef| {
                     hover_text(node.doc_comment_text(), node.short_label())
                 })
                 .visit(|node: ast::Module| hover_text(node.doc_comment_text(), node.short_label()))
diff --git a/crates/ra_ide_api/src/inlay_hints.rs b/crates/ra_ide_api/src/inlay_hints.rs
index 61ccb74b61..735f3166c5 100644
--- a/crates/ra_ide_api/src/inlay_hints.rs
+++ b/crates/ra_ide_api/src/inlay_hints.rs
@@ -125,13 +125,13 @@ fn get_leaf_pats(root_pat: ast::Pat) -> Vec<ast::Pat> {
                     pats_to_process.push_back(arg_pat);
                 }
             }
-            ast::Pat::RecordPat(record_pat) => {
-                if let Some(pat_list) = record_pat.record_field_pat_list() {
+            ast::Pat::StructPat(struct_pat) => {
+                if let Some(pat_list) = struct_pat.field_pat_list() {
                     pats_to_process.extend(
                         pat_list
-                            .record_field_pats()
-                            .filter_map(|record_field_pat| {
-                                record_field_pat
+                            .field_pats()
+                            .filter_map(|field_pat| {
+                                field_pat
                                     .pat()
                                     .filter(|pat| pat.syntax().kind() != SyntaxKind::BIND_PAT)
                             })
diff --git a/crates/ra_ide_api/src/marks.rs b/crates/ra_ide_api/src/marks.rs
index c3752cc541..9cb991de5e 100644
--- a/crates/ra_ide_api/src/marks.rs
+++ b/crates/ra_ide_api/src/marks.rs
@@ -3,7 +3,7 @@ test_utils::marks!(
     goto_definition_works_for_macros
     goto_definition_works_for_methods
     goto_definition_works_for_fields
-    goto_definition_works_for_record_fields
+    goto_definition_works_for_named_fields
     call_info_bad_offset
     dont_complete_current_use
     dont_complete_primitive_in_use
diff --git a/crates/ra_ide_api/src/name_ref_kind.rs b/crates/ra_ide_api/src/name_ref_kind.rs
index 34a8bcc365..f7db6c826b 100644
--- a/crates/ra_ide_api/src/name_ref_kind.rs
+++ b/crates/ra_ide_api/src/name_ref_kind.rs
@@ -54,12 +54,12 @@ pub(crate) fn classify_name_ref(
     }
 
     // It could also be a named field
-    if let Some(field_expr) = name_ref.syntax().parent().and_then(ast::RecordField::cast) {
-        tested_by!(goto_definition_works_for_record_fields);
+    if let Some(field_expr) = name_ref.syntax().parent().and_then(ast::NamedField::cast) {
+        tested_by!(goto_definition_works_for_named_fields);
 
-        let record_lit = field_expr.syntax().ancestors().find_map(ast::RecordLit::cast);
+        let struct_lit = field_expr.syntax().ancestors().find_map(ast::StructLit::cast);
 
-        if let Some(ty) = record_lit.and_then(|lit| analyzer.type_of(db, &lit.into())) {
+        if let Some(ty) = struct_lit.and_then(|lit| analyzer.type_of(db, &lit.into())) {
             if let Some((hir::AdtDef::Struct(s), _)) = ty.as_adt() {
                 let hir_path = hir::Path::from_name_ref(name_ref);
                 let hir_name = hir_path.as_ident().unwrap();
diff --git a/crates/ra_ide_api/src/syntax_highlighting.rs b/crates/ra_ide_api/src/syntax_highlighting.rs
index 06ccf07286..448acffc86 100644
--- a/crates/ra_ide_api/src/syntax_highlighting.rs
+++ b/crates/ra_ide_api/src/syntax_highlighting.rs
@@ -165,7 +165,7 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRa
                                 TYPE_PARAM | STRUCT_DEF | ENUM_DEF | TRAIT_DEF | TYPE_ALIAS_DEF => {
                                     "type"
                                 }
-                                RECORD_FIELD_DEF => "field",
+                                NAMED_FIELD_DEF => "field",
                                 _ => "function",
                             })
                             .unwrap_or("function")
diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml
index e271c257bc..afeac0d8a4 100644
--- a/crates/ra_lsp_server/Cargo.toml
+++ b/crates/ra_lsp_server/Cargo.toml
@@ -16,7 +16,7 @@ lsp-types = { version = "0.60.0", features = ["proposed"] }
 rustc-hash = "1.0"
 parking_lot = "0.9.0"
 
-ra_vfs = "0.3.0"
+ra_vfs = "0.2.7"
 thread_worker = { path = "../thread_worker" }
 ra_syntax = { path = "../ra_syntax" }
 ra_text_edit = { path = "../ra_text_edit" }
diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs
index 5fa52ec1b4..0ad2ea10f4 100644
--- a/crates/ra_lsp_server/src/conv.rs
+++ b/crates/ra_lsp_server/src/conv.rs
@@ -42,7 +42,7 @@ impl Conv for SyntaxKind {
             SyntaxKind::TRAIT_DEF => SymbolKind::Interface,
             SyntaxKind::MODULE => SymbolKind::Module,
             SyntaxKind::TYPE_ALIAS_DEF => SymbolKind::TypeParameter,
-            SyntaxKind::RECORD_FIELD_DEF => SymbolKind::Field,
+            SyntaxKind::NAMED_FIELD_DEF => SymbolKind::Field,
             SyntaxKind::STATIC_DEF => SymbolKind::Constant,
             SyntaxKind::CONST_DEF => SymbolKind::Constant,
             SyntaxKind::IMPL_BLOCK => SymbolKind::Object,
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs
index 45bd52769b..ce25ff162a 100644
--- a/crates/ra_lsp_server/src/main_loop.rs
+++ b/crates/ra_lsp_server/src/main_loop.rs
@@ -217,7 +217,7 @@ fn main_loop_inner(
                 Err(RecvError) => Err("client exited without shutdown")?,
             },
             recv(task_receiver) -> task => Event::Task(task.unwrap()),
-            recv(state.task_receiver) -> task => match task {
+            recv(state.vfs.read().task_receiver()) -> task => match task {
                 Ok(task) => Event::Vfs(task),
                 Err(RecvError) => Err("vfs died")?,
             },
diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs
index cc79644698..6696dff71c 100644
--- a/crates/ra_lsp_server/src/world.rs
+++ b/crates/ra_lsp_server/src/world.rs
@@ -3,7 +3,6 @@ use std::{
     sync::Arc,
 };
 
-use crossbeam_channel::{unbounded, Receiver};
 use gen_lsp_server::ErrorCode;
 use lsp_types::Url;
 use parking_lot::RwLock;
@@ -11,7 +10,7 @@ use ra_ide_api::{
     Analysis, AnalysisChange, AnalysisHost, CrateGraph, FeatureFlags, FileId, LibraryData,
     SourceRootId,
 };
-use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot, VfsTask};
+use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot};
 use ra_vfs_glob::{Glob, RustPackageFilterBuilder};
 use relative_path::RelativePathBuf;
 
@@ -40,7 +39,6 @@ pub struct WorldState {
     pub workspaces: Arc<Vec<ProjectWorkspace>>,
     pub analysis_host: AnalysisHost,
     pub vfs: Arc<RwLock<Vfs>>,
-    pub task_receiver: Receiver<VfsTask>,
     pub latest_requests: Arc<RwLock<LatestRequests>>,
 }
 
@@ -82,9 +80,8 @@ impl WorldState {
                 RootEntry::new(pkg_root.path().clone(), filter.into_vfs_filter())
             }));
         }
-        let (task_sender, task_receiver) = unbounded();
-        let task_sender = Box::new(move |t| task_sender.send(t).unwrap());
-        let (mut vfs, vfs_roots) = Vfs::new(roots, task_sender);
+
+        let (mut vfs, vfs_roots) = Vfs::new(roots);
         let roots_to_scan = vfs_roots.len();
         for r in vfs_roots {
             let vfs_root_path = vfs.root2path(r);
@@ -112,7 +109,6 @@ impl WorldState {
             workspaces: Arc::new(workspaces),
             analysis_host,
             vfs: Arc::new(RwLock::new(vfs)),
-            task_receiver,
             latest_requests: Default::default(),
         }
     }
diff --git a/crates/ra_parser/src/grammar.rs b/crates/ra_parser/src/grammar.rs
index dee3a229d6..beedac4572 100644
--- a/crates/ra_parser/src/grammar.rs
+++ b/crates/ra_parser/src/grammar.rs
@@ -150,8 +150,8 @@ pub(crate) fn reparser(
 ) -> Option<fn(&mut Parser)> {
     let res = match node {
         BLOCK => expressions::block,
-        RECORD_FIELD_DEF_LIST => items::record_field_def_list,
-        RECORD_FIELD_LIST => items::record_field_list,
+        NAMED_FIELD_DEF_LIST => items::named_field_def_list,
+        NAMED_FIELD_LIST => items::named_field_list,
         ENUM_VARIANT_LIST => items::enum_variant_list,
         MATCH_ARM_LIST => items::match_arm_list,
         USE_TREE_LIST => items::use_tree_list,
diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs
index 783d6a6f08..0495f34aeb 100644
--- a/crates/ra_parser/src/grammar/expressions.rs
+++ b/crates/ra_parser/src/grammar/expressions.rs
@@ -559,8 +559,8 @@ fn path_expr(p: &mut Parser, r: Restrictions) -> (CompletedMarker, BlockLike) {
     paths::expr_path(p);
     match p.current() {
         T!['{'] if !r.forbid_structs => {
-            record_field_list(p);
-            (m.complete(p, RECORD_LIT), BlockLike::NotBlock)
+            named_field_list(p);
+            (m.complete(p, STRUCT_LIT), BlockLike::NotBlock)
         }
         T![!] => {
             let block_like = items::macro_call_after_excl(p);
@@ -570,20 +570,20 @@ fn path_expr(p: &mut Parser, r: Restrictions) -> (CompletedMarker, BlockLike) {
     }
 }
 
-// test record_lit
+// test struct_lit
 // fn foo() {
 //     S {};
 //     S { x, y: 32, };
 //     S { x, y: 32, ..Default::default() };
 //     TupleStruct { 0: 1 };
 // }
-pub(crate) fn record_field_list(p: &mut Parser) {
+pub(crate) fn named_field_list(p: &mut Parser) {
     assert!(p.at(T!['{']));
     let m = p.start();
     p.bump();
     while !p.at(EOF) && !p.at(T!['}']) {
         match p.current() {
-            // test record_literal_field_with_attr
+            // test struct_literal_field_with_attr
             // fn main() {
             //     S { #[cfg(test)] field: 1 }
             // }
@@ -594,7 +594,7 @@ pub(crate) fn record_field_list(p: &mut Parser) {
                 if p.eat(T![:]) {
                     expr(p);
                 }
-                m.complete(p, RECORD_FIELD);
+                m.complete(p, NAMED_FIELD);
             }
             T![..] => {
                 p.bump();
@@ -608,5 +608,5 @@ pub(crate) fn record_field_list(p: &mut Parser) {
         }
     }
     p.expect(T!['}']);
-    m.complete(p, RECORD_FIELD_LIST);
+    m.complete(p, NAMED_FIELD_LIST);
 }
diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs
index bc942ae010..ab8fb9f6e9 100644
--- a/crates/ra_parser/src/grammar/expressions/atom.rs
+++ b/crates/ra_parser/src/grammar/expressions/atom.rs
@@ -414,6 +414,8 @@ pub(crate) fn match_arm_list(p: &mut Parser) {
 //         X | Y if Z => (),
 //         | X | Y if Z => (),
 //         | X => (),
+//         box X => (),
+//         Some(box X) => (),
 //     };
 // }
 fn match_arm(p: &mut Parser) -> BlockLike {
diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs
index 6d426206e9..b7da44758d 100644
--- a/crates/ra_parser/src/grammar/items.rs
+++ b/crates/ra_parser/src/grammar/items.rs
@@ -4,8 +4,8 @@ mod traits;
 mod use_item;
 
 pub(crate) use self::{
-    expressions::{match_arm_list, record_field_list},
-    nominal::{enum_variant_list, record_field_def_list},
+    expressions::{match_arm_list, named_field_list},
+    nominal::{enum_variant_list, named_field_def_list},
     traits::{impl_item_list, trait_item_list},
     use_item::use_tree_list,
 };
diff --git a/crates/ra_parser/src/grammar/items/nominal.rs b/crates/ra_parser/src/grammar/items/nominal.rs
index 54f02c7c93..bd4edab890 100644
--- a/crates/ra_parser/src/grammar/items/nominal.rs
+++ b/crates/ra_parser/src/grammar/items/nominal.rs
@@ -13,7 +13,7 @@ pub(super) fn struct_def(p: &mut Parser, m: Marker, kind: SyntaxKind) {
                 T![;] => {
                     p.bump();
                 }
-                T!['{'] => record_field_def_list(p),
+                T!['{'] => named_field_def_list(p),
                 _ => {
                     //FIXME: special case `(` error message
                     p.error("expected `;` or `{`");
@@ -23,9 +23,9 @@ pub(super) fn struct_def(p: &mut Parser, m: Marker, kind: SyntaxKind) {
         T![;] if kind == T![struct] => {
             p.bump();
         }
-        T!['{'] => record_field_def_list(p),
+        T!['{'] => named_field_def_list(p),
         T!['('] if kind == T![struct] => {
-            tuple_field_def_list(p);
+            pos_field_def_list(p);
             // test tuple_struct_where
             // struct Test<T>(T) where T: Clone;
             // struct Test<T>(T);
@@ -70,8 +70,8 @@ pub(crate) fn enum_variant_list(p: &mut Parser) {
         if p.at(IDENT) {
             name(p);
             match p.current() {
-                T!['{'] => record_field_def_list(p),
-                T!['('] => tuple_field_def_list(p),
+                T!['{'] => named_field_def_list(p),
+                T!['('] => pos_field_def_list(p),
                 T![=] => {
                     p.bump();
                     expressions::expr(p);
@@ -91,7 +91,7 @@ pub(crate) fn enum_variant_list(p: &mut Parser) {
     m.complete(p, ENUM_VARIANT_LIST);
 }
 
-pub(crate) fn record_field_def_list(p: &mut Parser) {
+pub(crate) fn named_field_def_list(p: &mut Parser) {
     assert!(p.at(T!['{']));
     let m = p.start();
     p.bump();
@@ -100,17 +100,17 @@ pub(crate) fn record_field_def_list(p: &mut Parser) {
             error_block(p, "expected field");
             continue;
         }
-        record_field_def(p);
+        named_field_def(p);
         if !p.at(T!['}']) {
             p.expect(T![,]);
         }
     }
     p.expect(T!['}']);
-    m.complete(p, RECORD_FIELD_DEF_LIST);
+    m.complete(p, NAMED_FIELD_DEF_LIST);
 
-    fn record_field_def(p: &mut Parser) {
+    fn named_field_def(p: &mut Parser) {
         let m = p.start();
-        // test record_field_attrs
+        // test field_attrs
         // struct S {
         //     #[serde(with = "url_serde")]
         //     pub uri: Uri,
@@ -121,7 +121,7 @@ pub(crate) fn record_field_def_list(p: &mut Parser) {
             name(p);
             p.expect(T![:]);
             types::type_(p);
-            m.complete(p, RECORD_FIELD_DEF);
+            m.complete(p, NAMED_FIELD_DEF);
         } else {
             m.abandon(p);
             p.err_and_bump("expected field declaration");
@@ -129,7 +129,7 @@ pub(crate) fn record_field_def_list(p: &mut Parser) {
     }
 }
 
-fn tuple_field_def_list(p: &mut Parser) {
+fn pos_field_def_list(p: &mut Parser) {
     assert!(p.at(T!['(']));
     let m = p.start();
     if !p.expect(T!['(']) {
@@ -137,7 +137,7 @@ fn tuple_field_def_list(p: &mut Parser) {
     }
     while !p.at(T![')']) && !p.at(EOF) {
         let m = p.start();
-        // test tuple_field_attrs
+        // test pos_field_attrs
         // struct S (
         //     #[serde(with = "url_serde")]
         //     pub Uri,
@@ -154,12 +154,12 @@ fn tuple_field_def_list(p: &mut Parser) {
             break;
         }
         types::type_(p);
-        m.complete(p, TUPLE_FIELD_DEF);
+        m.complete(p, POS_FIELD_DEF);
 
         if !p.at(T![')']) {
             p.expect(T![,]);
         }
     }
     p.expect(T![')']);
-    m.complete(p, TUPLE_FIELD_DEF_LIST);
+    m.complete(p, POS_FIELD_DEF_LIST);
 }
diff --git a/crates/ra_parser/src/grammar/patterns.rs b/crates/ra_parser/src/grammar/patterns.rs
index eae70ab85f..1f6a6fd48b 100644
--- a/crates/ra_parser/src/grammar/patterns.rs
+++ b/crates/ra_parser/src/grammar/patterns.rs
@@ -56,33 +56,37 @@ const PAT_RECOVERY_SET: TokenSet =
     token_set![LET_KW, IF_KW, WHILE_KW, LOOP_KW, MATCH_KW, R_PAREN, COMMA];
 
 fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option<CompletedMarker> {
-    // Checks the token after an IDENT to see if a pattern is a path (Struct { .. }) or macro
-    // (T![x]).
-    let is_path_or_macro_pat =
-        |la1| la1 == T![::] || la1 == T!['('] || la1 == T!['{'] || la1 == T![!];
-
-    let m = match p.nth(0) {
-        T![box] => box_pat(p),
-        T![ref] | T![mut] | IDENT if !is_path_or_macro_pat(p.nth(1)) => bind_pat(p, true),
+    let la0 = p.nth(0);
+    let la1 = p.nth(1);
+    if la0 == T![ref]
+        || la0 == T![mut]
+        || la0 == T![box]
+        || (la0 == IDENT && !(la1 == T![::] || la1 == T!['('] || la1 == T!['{'] || la1 == T![!]))
+    {
+        return Some(bind_pat(p, true));
+    }
+    if paths::is_use_path_start(p) {
+        return Some(path_pat(p));
+    }
 
-        _ if paths::is_use_path_start(p) => path_pat(p),
-        _ if is_literal_pat_start(p) => literal_pat(p),
+    if is_literal_pat_start(p) {
+        return Some(literal_pat(p));
+    }
 
+    let m = match la0 {
         T![_] => placeholder_pat(p),
         T![&] => ref_pat(p),
         T!['('] => tuple_pat(p),
         T!['['] => slice_pat(p),
-
         _ => {
             p.err_recover("expected pattern", recovery_set);
             return None;
         }
     };
-
     Some(m)
 }
 
-fn is_literal_pat_start(p: &Parser) -> bool {
+fn is_literal_pat_start(p: &mut Parser) -> bool {
     p.at(T![-]) && (p.nth(1) == INT_NUMBER || p.nth(1) == FLOAT_NUMBER)
         || p.at_ts(expressions::LITERAL_FIRST)
 }
@@ -123,8 +127,8 @@ fn path_pat(p: &mut Parser) -> CompletedMarker {
             TUPLE_STRUCT_PAT
         }
         T!['{'] => {
-            record_field_pat_list(p);
-            RECORD_PAT
+            field_pat_list(p);
+            STRUCT_PAT
         }
         _ => PATH_PAT,
     };
@@ -145,25 +149,22 @@ fn tuple_pat_fields(p: &mut Parser) {
     p.expect(T![')']);
 }
 
-// test record_field_pat_list
+// test field_pat_list
 // fn foo() {
 //     let S {} = ();
 //     let S { f, ref mut g } = ();
 //     let S { h: _, ..} = ();
 //     let S { h: _, } = ();
 // }
-fn record_field_pat_list(p: &mut Parser) {
+fn field_pat_list(p: &mut Parser) {
     assert!(p.at(T!['{']));
     let m = p.start();
     p.bump();
     while !p.at(EOF) && !p.at(T!['}']) {
         match p.current() {
             T![..] => p.bump(),
-            IDENT if p.nth(1) == T![:] => record_field_pat(p),
+            IDENT if p.nth(1) == T![:] => field_pat(p),
             T!['{'] => error_block(p, "expected ident"),
-            T![box] => {
-                box_pat(p);
-            }
             _ => {
                 bind_pat(p, false);
             }
@@ -173,10 +174,10 @@ fn record_field_pat_list(p: &mut Parser) {
         }
     }
     p.expect(T!['}']);
-    m.complete(p, RECORD_FIELD_PAT_LIST);
+    m.complete(p, FIELD_PAT_LIST);
 }
 
-fn record_field_pat(p: &mut Parser) {
+fn field_pat(p: &mut Parser) {
     assert!(p.at(IDENT));
     assert!(p.nth(1) == T![:]);
 
@@ -184,7 +185,7 @@ fn record_field_pat(p: &mut Parser) {
     name(p);
     p.bump();
     pattern(p);
-    m.complete(p, RECORD_FIELD_PAT);
+    m.complete(p, FIELD_PAT);
 }
 
 // test placeholder_pat
@@ -260,9 +261,11 @@ fn pat_list(p: &mut Parser, ket: SyntaxKind) {
 //     let ref mut d = ();
 //     let e @ _ = ();
 //     let ref mut f @ g @ _ = ();
+//     let box i = Box::new(1i32);
 // }
 fn bind_pat(p: &mut Parser, with_at: bool) -> CompletedMarker {
     let m = p.start();
+    p.eat(T![box]);
     p.eat(T![ref]);
     p.eat(T![mut]);
     name(p);
@@ -271,17 +274,3 @@ fn bind_pat(p: &mut Parser, with_at: bool) -> CompletedMarker {
     }
     m.complete(p, BIND_PAT)
 }
-
-// test box_pat
-// fn main() {
-//     let box i = ();
-//     let box Outer { box i, j: box Inner(box &x) } = ();
-//     let box ref mut i = ();
-// }
-fn box_pat(p: &mut Parser) -> CompletedMarker {
-    assert!(p.at(T![box]));
-    let m = p.start();
-    p.bump();
-    pattern(p);
-    m.complete(p, BOX_PAT)
-}
diff --git a/crates/ra_parser/src/syntax_kind/generated.rs b/crates/ra_parser/src/syntax_kind/generated.rs
index 8ba29ebf83..3a67d7dddd 100644
--- a/crates/ra_parser/src/syntax_kind/generated.rs
+++ b/crates/ra_parser/src/syntax_kind/generated.rs
@@ -149,13 +149,12 @@ pub enum SyntaxKind {
     IMPL_TRAIT_TYPE,
     DYN_TRAIT_TYPE,
     REF_PAT,
-    BOX_PAT,
     BIND_PAT,
     PLACEHOLDER_PAT,
     PATH_PAT,
-    RECORD_PAT,
-    RECORD_FIELD_PAT_LIST,
-    RECORD_FIELD_PAT,
+    STRUCT_PAT,
+    FIELD_PAT_LIST,
+    FIELD_PAT,
     TUPLE_STRUCT_PAT,
     TUPLE_PAT,
     SLICE_PAT,
@@ -180,9 +179,9 @@ pub enum SyntaxKind {
     MATCH_ARM_LIST,
     MATCH_ARM,
     MATCH_GUARD,
-    RECORD_LIT,
-    RECORD_FIELD_LIST,
-    RECORD_FIELD,
+    STRUCT_LIT,
+    NAMED_FIELD_LIST,
+    NAMED_FIELD,
     TRY_BLOCK_EXPR,
     BOX_EXPR,
     CALL_EXPR,
@@ -200,10 +199,10 @@ pub enum SyntaxKind {
     EXTERN_BLOCK,
     EXTERN_ITEM_LIST,
     ENUM_VARIANT,
-    RECORD_FIELD_DEF_LIST,
-    RECORD_FIELD_DEF,
-    TUPLE_FIELD_DEF_LIST,
-    TUPLE_FIELD_DEF,
+    NAMED_FIELD_DEF_LIST,
+    NAMED_FIELD_DEF,
+    POS_FIELD_DEF_LIST,
+    POS_FIELD_DEF,
     ENUM_VARIANT_LIST,
     ITEM_LIST,
     ATTR,
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs
index a2f8628699..afdfca66e3 100644
--- a/crates/ra_syntax/src/ast.rs
+++ b/crates/ra_syntax/src/ast.rs
@@ -25,23 +25,15 @@ pub use self::{
 /// conversion itself has zero runtime cost: ast and syntax nodes have exactly
 /// the same representation: a pointer to the tree root and a pointer to the
 /// node itself.
-pub trait AstNode {
-    fn can_cast(kind: SyntaxKind) -> bool
-    where
-        Self: Sized;
+pub trait AstNode: Clone {
+    fn can_cast(kind: SyntaxKind) -> bool;
 
     fn cast(syntax: SyntaxNode) -> Option<Self>
     where
         Self: Sized;
-
     fn syntax(&self) -> &SyntaxNode;
 }
 
-#[test]
-fn assert_ast_is_object_safe() {
-    fn _f(_: &dyn AstNode, _: &dyn NameOwner) {}
-}
-
 /// Like `AstNode`, but wraps tokens rather than interior nodes.
 pub trait AstToken {
     fn cast(token: SyntaxToken) -> Option<Self>
diff --git a/crates/ra_syntax/src/ast/expr_extensions.rs b/crates/ra_syntax/src/ast/expr_extensions.rs
index d7ea4354df..cf5b6f2510 100644
--- a/crates/ra_syntax/src/ast/expr_extensions.rs
+++ b/crates/ra_syntax/src/ast/expr_extensions.rs
@@ -296,8 +296,8 @@ fn test_literal_with_attr() {
     assert_eq!(lit.token().text(), r#""Hello""#);
 }
 
-impl ast::RecordField {
-    pub fn parent_record_lit(&self) -> ast::RecordLit {
-        self.syntax().ancestors().find_map(ast::RecordLit::cast).unwrap()
+impl ast::NamedField {
+    pub fn parent_struct_lit(&self) -> ast::StructLit {
+        self.syntax().ancestors().find_map(ast::StructLit::cast).unwrap()
     }
 }
diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs
index d3a375f879..e0ea3e5ab1 100644
--- a/crates/ra_syntax/src/ast/extensions.rs
+++ b/crates/ra_syntax/src/ast/extensions.rs
@@ -195,16 +195,16 @@ impl ast::ImplBlock {
 
 #[derive(Debug, Clone, PartialEq, Eq)]
 pub enum StructKind {
-    Tuple(ast::TupleFieldDefList),
-    Named(ast::RecordFieldDefList),
+    Tuple(ast::PosFieldDefList),
+    Named(ast::NamedFieldDefList),
     Unit,
 }
 
 impl StructKind {
     fn from_node<N: AstNode>(node: &N) -> StructKind {
-        if let Some(nfdl) = child_opt::<_, ast::RecordFieldDefList>(node) {
+        if let Some(nfdl) = child_opt::<_, ast::NamedFieldDefList>(node) {
             StructKind::Named(nfdl)
-        } else if let Some(pfl) = child_opt::<_, ast::TupleFieldDefList>(node) {
+        } else if let Some(pfl) = child_opt::<_, ast::PosFieldDefList>(node) {
             StructKind::Tuple(pfl)
         } else {
             StructKind::Unit
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index 90480b6ca5..9c57897013 100644
--- a/crates/ra_syntax/src/ast/generated.rs
+++ b/crates/ra_syntax/src/ast/generated.rs
@@ -307,33 +307,6 @@ impl BlockExpr {
     }
 }
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct BoxPat {
-    pub(crate) syntax: SyntaxNode,
-}
-impl AstNode for BoxPat {
-    fn can_cast(kind: SyntaxKind) -> bool {
-        match kind {
-            BOX_PAT => true,
-            _ => false,
-        }
-    }
-    fn cast(syntax: SyntaxNode) -> Option<Self> {
-        if Self::can_cast(syntax.kind()) {
-            Some(Self { syntax })
-        } else {
-            None
-        }
-    }
-    fn syntax(&self) -> &SyntaxNode {
-        &self.syntax
-    }
-}
-impl BoxPat {
-    pub fn pat(&self) -> Option<Pat> {
-        AstChildren::new(&self.syntax).next()
-    }
-}
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct BreakExpr {
     pub(crate) syntax: SyntaxNode,
 }
@@ -634,7 +607,7 @@ pub enum Expr {
     BlockExpr(BlockExpr),
     ReturnExpr(ReturnExpr),
     MatchExpr(MatchExpr),
-    RecordLit(RecordLit),
+    StructLit(StructLit),
     CallExpr(CallExpr),
     IndexExpr(IndexExpr),
     MethodCallExpr(MethodCallExpr),
@@ -725,9 +698,9 @@ impl From<MatchExpr> for Expr {
         Expr::MatchExpr(node)
     }
 }
-impl From<RecordLit> for Expr {
-    fn from(node: RecordLit) -> Expr {
-        Expr::RecordLit(node)
+impl From<StructLit> for Expr {
+    fn from(node: StructLit) -> Expr {
+        Expr::StructLit(node)
     }
 }
 impl From<CallExpr> for Expr {
@@ -805,7 +778,7 @@ impl AstNode for Expr {
         match kind {
             TUPLE_EXPR | ARRAY_EXPR | PAREN_EXPR | PATH_EXPR | LAMBDA_EXPR | IF_EXPR
             | LOOP_EXPR | FOR_EXPR | WHILE_EXPR | CONTINUE_EXPR | BREAK_EXPR | LABEL
-            | BLOCK_EXPR | RETURN_EXPR | MATCH_EXPR | RECORD_LIT | CALL_EXPR | INDEX_EXPR
+            | BLOCK_EXPR | RETURN_EXPR | MATCH_EXPR | STRUCT_LIT | CALL_EXPR | INDEX_EXPR
             | METHOD_CALL_EXPR | FIELD_EXPR | AWAIT_EXPR | TRY_EXPR | TRY_BLOCK_EXPR
             | CAST_EXPR | REF_EXPR | PREFIX_EXPR | RANGE_EXPR | BIN_EXPR | LITERAL | MACRO_CALL => {
                 true
@@ -830,7 +803,7 @@ impl AstNode for Expr {
             BLOCK_EXPR => Expr::BlockExpr(BlockExpr { syntax }),
             RETURN_EXPR => Expr::ReturnExpr(ReturnExpr { syntax }),
             MATCH_EXPR => Expr::MatchExpr(MatchExpr { syntax }),
-            RECORD_LIT => Expr::RecordLit(RecordLit { syntax }),
+            STRUCT_LIT => Expr::StructLit(StructLit { syntax }),
             CALL_EXPR => Expr::CallExpr(CallExpr { syntax }),
             INDEX_EXPR => Expr::IndexExpr(IndexExpr { syntax }),
             METHOD_CALL_EXPR => Expr::MethodCallExpr(MethodCallExpr { syntax }),
@@ -866,7 +839,7 @@ impl AstNode for Expr {
             Expr::BlockExpr(it) => &it.syntax,
             Expr::ReturnExpr(it) => &it.syntax,
             Expr::MatchExpr(it) => &it.syntax,
-            Expr::RecordLit(it) => &it.syntax,
+            Expr::StructLit(it) => &it.syntax,
             Expr::CallExpr(it) => &it.syntax,
             Expr::IndexExpr(it) => &it.syntax,
             Expr::MethodCallExpr(it) => &it.syntax,
@@ -973,6 +946,64 @@ impl FieldExpr {
     }
 }
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct FieldPat {
+    pub(crate) syntax: SyntaxNode,
+}
+impl AstNode for FieldPat {
+    fn can_cast(kind: SyntaxKind) -> bool {
+        match kind {
+            FIELD_PAT => true,
+            _ => false,
+        }
+    }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode {
+        &self.syntax
+    }
+}
+impl ast::NameOwner for FieldPat {}
+impl FieldPat {
+    pub fn pat(&self) -> Option<Pat> {
+        AstChildren::new(&self.syntax).next()
+    }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct FieldPatList {
+    pub(crate) syntax: SyntaxNode,
+}
+impl AstNode for FieldPatList {
+    fn can_cast(kind: SyntaxKind) -> bool {
+        match kind {
+            FIELD_PAT_LIST => true,
+            _ => false,
+        }
+    }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode {
+        &self.syntax
+    }
+}
+impl FieldPatList {
+    pub fn field_pats(&self) -> AstChildren<FieldPat> {
+        AstChildren::new(&self.syntax)
+    }
+    pub fn bind_pats(&self) -> AstChildren<BindPat> {
+        AstChildren::new(&self.syntax)
+    }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct FnDef {
     pub(crate) syntax: SyntaxNode,
 }
@@ -1911,6 +1942,121 @@ impl AstNode for NameRef {
 }
 impl NameRef {}
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct NamedField {
+    pub(crate) syntax: SyntaxNode,
+}
+impl AstNode for NamedField {
+    fn can_cast(kind: SyntaxKind) -> bool {
+        match kind {
+            NAMED_FIELD => true,
+            _ => false,
+        }
+    }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode {
+        &self.syntax
+    }
+}
+impl NamedField {
+    pub fn name_ref(&self) -> Option<NameRef> {
+        AstChildren::new(&self.syntax).next()
+    }
+    pub fn expr(&self) -> Option<Expr> {
+        AstChildren::new(&self.syntax).next()
+    }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct NamedFieldDef {
+    pub(crate) syntax: SyntaxNode,
+}
+impl AstNode for NamedFieldDef {
+    fn can_cast(kind: SyntaxKind) -> bool {
+        match kind {
+            NAMED_FIELD_DEF => true,
+            _ => false,
+        }
+    }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode {
+        &self.syntax
+    }
+}
+impl ast::VisibilityOwner for NamedFieldDef {}
+impl ast::NameOwner for NamedFieldDef {}
+impl ast::AttrsOwner for NamedFieldDef {}
+impl ast::DocCommentsOwner for NamedFieldDef {}
+impl ast::TypeAscriptionOwner for NamedFieldDef {}
+impl NamedFieldDef {}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct NamedFieldDefList {
+    pub(crate) syntax: SyntaxNode,
+}
+impl AstNode for NamedFieldDefList {
+    fn can_cast(kind: SyntaxKind) -> bool {
+        match kind {
+            NAMED_FIELD_DEF_LIST => true,
+            _ => false,
+        }
+    }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode {
+        &self.syntax
+    }
+}
+impl NamedFieldDefList {
+    pub fn fields(&self) -> AstChildren<NamedFieldDef> {
+        AstChildren::new(&self.syntax)
+    }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct NamedFieldList {
+    pub(crate) syntax: SyntaxNode,
+}
+impl AstNode for NamedFieldList {
+    fn can_cast(kind: SyntaxKind) -> bool {
+        match kind {
+            NAMED_FIELD_LIST => true,
+            _ => false,
+        }
+    }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode {
+        &self.syntax
+    }
+}
+impl NamedFieldList {
+    pub fn fields(&self) -> AstChildren<NamedField> {
+        AstChildren::new(&self.syntax)
+    }
+    pub fn spread(&self) -> Option<Expr> {
+        AstChildren::new(&self.syntax).next()
+    }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct NeverType {
     pub(crate) syntax: SyntaxNode,
 }
@@ -2090,11 +2236,10 @@ impl ParenType {
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub enum Pat {
     RefPat(RefPat),
-    BoxPat(BoxPat),
     BindPat(BindPat),
     PlaceholderPat(PlaceholderPat),
     PathPat(PathPat),
-    RecordPat(RecordPat),
+    StructPat(StructPat),
     TupleStructPat(TupleStructPat),
     TuplePat(TuplePat),
     SlicePat(SlicePat),
@@ -2106,11 +2251,6 @@ impl From<RefPat> for Pat {
         Pat::RefPat(node)
     }
 }
-impl From<BoxPat> for Pat {
-    fn from(node: BoxPat) -> Pat {
-        Pat::BoxPat(node)
-    }
-}
 impl From<BindPat> for Pat {
     fn from(node: BindPat) -> Pat {
         Pat::BindPat(node)
@@ -2126,9 +2266,9 @@ impl From<PathPat> for Pat {
         Pat::PathPat(node)
     }
 }
-impl From<RecordPat> for Pat {
-    fn from(node: RecordPat) -> Pat {
-        Pat::RecordPat(node)
+impl From<StructPat> for Pat {
+    fn from(node: StructPat) -> Pat {
+        Pat::StructPat(node)
     }
 }
 impl From<TupleStructPat> for Pat {
@@ -2159,19 +2299,18 @@ impl From<LiteralPat> for Pat {
 impl AstNode for Pat {
     fn can_cast(kind: SyntaxKind) -> bool {
         match kind {
-            REF_PAT | BOX_PAT | BIND_PAT | PLACEHOLDER_PAT | PATH_PAT | RECORD_PAT
-            | TUPLE_STRUCT_PAT | TUPLE_PAT | SLICE_PAT | RANGE_PAT | LITERAL_PAT => true,
+            REF_PAT | BIND_PAT | PLACEHOLDER_PAT | PATH_PAT | STRUCT_PAT | TUPLE_STRUCT_PAT
+            | TUPLE_PAT | SLICE_PAT | RANGE_PAT | LITERAL_PAT => true,
             _ => false,
         }
     }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         let res = match syntax.kind() {
             REF_PAT => Pat::RefPat(RefPat { syntax }),
-            BOX_PAT => Pat::BoxPat(BoxPat { syntax }),
             BIND_PAT => Pat::BindPat(BindPat { syntax }),
             PLACEHOLDER_PAT => Pat::PlaceholderPat(PlaceholderPat { syntax }),
             PATH_PAT => Pat::PathPat(PathPat { syntax }),
-            RECORD_PAT => Pat::RecordPat(RecordPat { syntax }),
+            STRUCT_PAT => Pat::StructPat(StructPat { syntax }),
             TUPLE_STRUCT_PAT => Pat::TupleStructPat(TupleStructPat { syntax }),
             TUPLE_PAT => Pat::TuplePat(TuplePat { syntax }),
             SLICE_PAT => Pat::SlicePat(SlicePat { syntax }),
@@ -2184,11 +2323,10 @@ impl AstNode for Pat {
     fn syntax(&self) -> &SyntaxNode {
         match self {
             Pat::RefPat(it) => &it.syntax,
-            Pat::BoxPat(it) => &it.syntax,
             Pat::BindPat(it) => &it.syntax,
             Pat::PlaceholderPat(it) => &it.syntax,
             Pat::PathPat(it) => &it.syntax,
-            Pat::RecordPat(it) => &it.syntax,
+            Pat::StructPat(it) => &it.syntax,
             Pat::TupleStructPat(it) => &it.syntax,
             Pat::TuplePat(it) => &it.syntax,
             Pat::SlicePat(it) => &it.syntax,
@@ -2413,13 +2551,13 @@ impl PointerType {
     }
 }
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct PrefixExpr {
+pub struct PosFieldDef {
     pub(crate) syntax: SyntaxNode,
 }
-impl AstNode for PrefixExpr {
+impl AstNode for PosFieldDef {
     fn can_cast(kind: SyntaxKind) -> bool {
         match kind {
-            PREFIX_EXPR => true,
+            POS_FIELD_DEF => true,
             _ => false,
         }
     }
@@ -2434,95 +2572,21 @@ impl AstNode for PrefixExpr {
         &self.syntax
     }
 }
-impl PrefixExpr {
-    pub fn expr(&self) -> Option<Expr> {
-        AstChildren::new(&self.syntax).next()
-    }
-}
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct RangeExpr {
-    pub(crate) syntax: SyntaxNode,
-}
-impl AstNode for RangeExpr {
-    fn can_cast(kind: SyntaxKind) -> bool {
-        match kind {
-            RANGE_EXPR => true,
-            _ => false,
-        }
-    }
-    fn cast(syntax: SyntaxNode) -> Option<Self> {
-        if Self::can_cast(syntax.kind()) {
-            Some(Self { syntax })
-        } else {
-            None
-        }
-    }
-    fn syntax(&self) -> &SyntaxNode {
-        &self.syntax
-    }
-}
-impl RangeExpr {}
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct RangePat {
-    pub(crate) syntax: SyntaxNode,
-}
-impl AstNode for RangePat {
-    fn can_cast(kind: SyntaxKind) -> bool {
-        match kind {
-            RANGE_PAT => true,
-            _ => false,
-        }
-    }
-    fn cast(syntax: SyntaxNode) -> Option<Self> {
-        if Self::can_cast(syntax.kind()) {
-            Some(Self { syntax })
-        } else {
-            None
-        }
-    }
-    fn syntax(&self) -> &SyntaxNode {
-        &self.syntax
-    }
-}
-impl RangePat {}
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct RecordField {
-    pub(crate) syntax: SyntaxNode,
-}
-impl AstNode for RecordField {
-    fn can_cast(kind: SyntaxKind) -> bool {
-        match kind {
-            RECORD_FIELD => true,
-            _ => false,
-        }
-    }
-    fn cast(syntax: SyntaxNode) -> Option<Self> {
-        if Self::can_cast(syntax.kind()) {
-            Some(Self { syntax })
-        } else {
-            None
-        }
-    }
-    fn syntax(&self) -> &SyntaxNode {
-        &self.syntax
-    }
-}
-impl RecordField {
-    pub fn name_ref(&self) -> Option<NameRef> {
-        AstChildren::new(&self.syntax).next()
-    }
-    pub fn expr(&self) -> Option<Expr> {
+impl ast::VisibilityOwner for PosFieldDef {}
+impl ast::AttrsOwner for PosFieldDef {}
+impl PosFieldDef {
+    pub fn type_ref(&self) -> Option<TypeRef> {
         AstChildren::new(&self.syntax).next()
     }
 }
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct RecordFieldDef {
+pub struct PosFieldDefList {
     pub(crate) syntax: SyntaxNode,
 }
-impl AstNode for RecordFieldDef {
+impl AstNode for PosFieldDefList {
     fn can_cast(kind: SyntaxKind) -> bool {
         match kind {
-            RECORD_FIELD_DEF => true,
+            POS_FIELD_DEF_LIST => true,
             _ => false,
         }
     }
@@ -2537,77 +2601,19 @@ impl AstNode for RecordFieldDef {
         &self.syntax
     }
 }
-impl ast::VisibilityOwner for RecordFieldDef {}
-impl ast::NameOwner for RecordFieldDef {}
-impl ast::AttrsOwner for RecordFieldDef {}
-impl ast::DocCommentsOwner for RecordFieldDef {}
-impl ast::TypeAscriptionOwner for RecordFieldDef {}
-impl RecordFieldDef {}
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct RecordFieldDefList {
-    pub(crate) syntax: SyntaxNode,
-}
-impl AstNode for RecordFieldDefList {
-    fn can_cast(kind: SyntaxKind) -> bool {
-        match kind {
-            RECORD_FIELD_DEF_LIST => true,
-            _ => false,
-        }
-    }
-    fn cast(syntax: SyntaxNode) -> Option<Self> {
-        if Self::can_cast(syntax.kind()) {
-            Some(Self { syntax })
-        } else {
-            None
-        }
-    }
-    fn syntax(&self) -> &SyntaxNode {
-        &self.syntax
-    }
-}
-impl RecordFieldDefList {
-    pub fn fields(&self) -> AstChildren<RecordFieldDef> {
+impl PosFieldDefList {
+    pub fn fields(&self) -> AstChildren<PosFieldDef> {
         AstChildren::new(&self.syntax)
     }
 }
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct RecordFieldList {
-    pub(crate) syntax: SyntaxNode,
-}
-impl AstNode for RecordFieldList {
-    fn can_cast(kind: SyntaxKind) -> bool {
-        match kind {
-            RECORD_FIELD_LIST => true,
-            _ => false,
-        }
-    }
-    fn cast(syntax: SyntaxNode) -> Option<Self> {
-        if Self::can_cast(syntax.kind()) {
-            Some(Self { syntax })
-        } else {
-            None
-        }
-    }
-    fn syntax(&self) -> &SyntaxNode {
-        &self.syntax
-    }
-}
-impl RecordFieldList {
-    pub fn fields(&self) -> AstChildren<RecordField> {
-        AstChildren::new(&self.syntax)
-    }
-    pub fn spread(&self) -> Option<Expr> {
-        AstChildren::new(&self.syntax).next()
-    }
-}
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct RecordFieldPat {
+pub struct PrefixExpr {
     pub(crate) syntax: SyntaxNode,
 }
-impl AstNode for RecordFieldPat {
+impl AstNode for PrefixExpr {
     fn can_cast(kind: SyntaxKind) -> bool {
         match kind {
-            RECORD_FIELD_PAT => true,
+            PREFIX_EXPR => true,
             _ => false,
         }
     }
@@ -2622,50 +2628,19 @@ impl AstNode for RecordFieldPat {
         &self.syntax
     }
 }
-impl ast::NameOwner for RecordFieldPat {}
-impl RecordFieldPat {
-    pub fn pat(&self) -> Option<Pat> {
+impl PrefixExpr {
+    pub fn expr(&self) -> Option<Expr> {
         AstChildren::new(&self.syntax).next()
     }
 }
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct RecordFieldPatList {
-    pub(crate) syntax: SyntaxNode,
-}
-impl AstNode for RecordFieldPatList {
-    fn can_cast(kind: SyntaxKind) -> bool {
-        match kind {
-            RECORD_FIELD_PAT_LIST => true,
-            _ => false,
-        }
-    }
-    fn cast(syntax: SyntaxNode) -> Option<Self> {
-        if Self::can_cast(syntax.kind()) {
-            Some(Self { syntax })
-        } else {
-            None
-        }
-    }
-    fn syntax(&self) -> &SyntaxNode {
-        &self.syntax
-    }
-}
-impl RecordFieldPatList {
-    pub fn record_field_pats(&self) -> AstChildren<RecordFieldPat> {
-        AstChildren::new(&self.syntax)
-    }
-    pub fn bind_pats(&self) -> AstChildren<BindPat> {
-        AstChildren::new(&self.syntax)
-    }
-}
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct RecordLit {
+pub struct RangeExpr {
     pub(crate) syntax: SyntaxNode,
 }
-impl AstNode for RecordLit {
+impl AstNode for RangeExpr {
     fn can_cast(kind: SyntaxKind) -> bool {
         match kind {
-            RECORD_LIT => true,
+            RANGE_EXPR => true,
             _ => false,
         }
     }
@@ -2680,22 +2655,15 @@ impl AstNode for RecordLit {
         &self.syntax
     }
 }
-impl RecordLit {
-    pub fn path(&self) -> Option<Path> {
-        AstChildren::new(&self.syntax).next()
-    }
-    pub fn record_field_list(&self) -> Option<RecordFieldList> {
-        AstChildren::new(&self.syntax).next()
-    }
-}
+impl RangeExpr {}
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct RecordPat {
+pub struct RangePat {
     pub(crate) syntax: SyntaxNode,
 }
-impl AstNode for RecordPat {
+impl AstNode for RangePat {
     fn can_cast(kind: SyntaxKind) -> bool {
         match kind {
-            RECORD_PAT => true,
+            RANGE_PAT => true,
             _ => false,
         }
     }
@@ -2710,14 +2678,7 @@ impl AstNode for RecordPat {
         &self.syntax
     }
 }
-impl RecordPat {
-    pub fn record_field_pat_list(&self) -> Option<RecordFieldPatList> {
-        AstChildren::new(&self.syntax).next()
-    }
-    pub fn path(&self) -> Option<Path> {
-        AstChildren::new(&self.syntax).next()
-    }
-}
+impl RangePat {}
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct RefExpr {
     pub(crate) syntax: SyntaxNode,
@@ -3057,13 +3018,13 @@ impl ast::AttrsOwner for StructDef {}
 impl ast::DocCommentsOwner for StructDef {}
 impl StructDef {}
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct TokenTree {
+pub struct StructLit {
     pub(crate) syntax: SyntaxNode,
 }
-impl AstNode for TokenTree {
+impl AstNode for StructLit {
     fn can_cast(kind: SyntaxKind) -> bool {
         match kind {
-            TOKEN_TREE => true,
+            STRUCT_LIT => true,
             _ => false,
         }
     }
@@ -3078,15 +3039,22 @@ impl AstNode for TokenTree {
         &self.syntax
     }
 }
-impl TokenTree {}
+impl StructLit {
+    pub fn path(&self) -> Option<Path> {
+        AstChildren::new(&self.syntax).next()
+    }
+    pub fn named_field_list(&self) -> Option<NamedFieldList> {
+        AstChildren::new(&self.syntax).next()
+    }
+}
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct TraitDef {
+pub struct StructPat {
     pub(crate) syntax: SyntaxNode,
 }
-impl AstNode for TraitDef {
+impl AstNode for StructPat {
     fn can_cast(kind: SyntaxKind) -> bool {
         match kind {
-            TRAIT_DEF => true,
+            STRUCT_PAT => true,
             _ => false,
         }
     }
@@ -3101,25 +3069,22 @@ impl AstNode for TraitDef {
         &self.syntax
     }
 }
-impl ast::VisibilityOwner for TraitDef {}
-impl ast::NameOwner for TraitDef {}
-impl ast::AttrsOwner for TraitDef {}
-impl ast::DocCommentsOwner for TraitDef {}
-impl ast::TypeParamsOwner for TraitDef {}
-impl ast::TypeBoundsOwner for TraitDef {}
-impl TraitDef {
-    pub fn item_list(&self) -> Option<ItemList> {
+impl StructPat {
+    pub fn field_pat_list(&self) -> Option<FieldPatList> {
+        AstChildren::new(&self.syntax).next()
+    }
+    pub fn path(&self) -> Option<Path> {
         AstChildren::new(&self.syntax).next()
     }
 }
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct TryBlockExpr {
+pub struct TokenTree {
     pub(crate) syntax: SyntaxNode,
 }
-impl AstNode for TryBlockExpr {
+impl AstNode for TokenTree {
     fn can_cast(kind: SyntaxKind) -> bool {
         match kind {
-            TRY_BLOCK_EXPR => true,
+            TOKEN_TREE => true,
             _ => false,
         }
     }
@@ -3134,16 +3099,15 @@ impl AstNode for TryBlockExpr {
         &self.syntax
     }
 }
-impl ast::TryBlockBodyOwner for TryBlockExpr {}
-impl TryBlockExpr {}
+impl TokenTree {}
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct TryExpr {
+pub struct TraitDef {
     pub(crate) syntax: SyntaxNode,
 }
-impl AstNode for TryExpr {
+impl AstNode for TraitDef {
     fn can_cast(kind: SyntaxKind) -> bool {
         match kind {
-            TRY_EXPR => true,
+            TRAIT_DEF => true,
             _ => false,
         }
     }
@@ -3158,19 +3122,25 @@ impl AstNode for TryExpr {
         &self.syntax
     }
 }
-impl TryExpr {
-    pub fn expr(&self) -> Option<Expr> {
+impl ast::VisibilityOwner for TraitDef {}
+impl ast::NameOwner for TraitDef {}
+impl ast::AttrsOwner for TraitDef {}
+impl ast::DocCommentsOwner for TraitDef {}
+impl ast::TypeParamsOwner for TraitDef {}
+impl ast::TypeBoundsOwner for TraitDef {}
+impl TraitDef {
+    pub fn item_list(&self) -> Option<ItemList> {
         AstChildren::new(&self.syntax).next()
     }
 }
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct TupleExpr {
+pub struct TryBlockExpr {
     pub(crate) syntax: SyntaxNode,
 }
-impl AstNode for TupleExpr {
+impl AstNode for TryBlockExpr {
     fn can_cast(kind: SyntaxKind) -> bool {
         match kind {
-            TUPLE_EXPR => true,
+            TRY_BLOCK_EXPR => true,
             _ => false,
         }
     }
@@ -3185,19 +3155,16 @@ impl AstNode for TupleExpr {
         &self.syntax
     }
 }
-impl TupleExpr {
-    pub fn exprs(&self) -> AstChildren<Expr> {
-        AstChildren::new(&self.syntax)
-    }
-}
+impl ast::TryBlockBodyOwner for TryBlockExpr {}
+impl TryBlockExpr {}
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct TupleFieldDef {
+pub struct TryExpr {
     pub(crate) syntax: SyntaxNode,
 }
-impl AstNode for TupleFieldDef {
+impl AstNode for TryExpr {
     fn can_cast(kind: SyntaxKind) -> bool {
         match kind {
-            TUPLE_FIELD_DEF => true,
+            TRY_EXPR => true,
             _ => false,
         }
     }
@@ -3212,21 +3179,19 @@ impl AstNode for TupleFieldDef {
         &self.syntax
     }
 }
-impl ast::VisibilityOwner for TupleFieldDef {}
-impl ast::AttrsOwner for TupleFieldDef {}
-impl TupleFieldDef {
-    pub fn type_ref(&self) -> Option<TypeRef> {
+impl TryExpr {
+    pub fn expr(&self) -> Option<Expr> {
         AstChildren::new(&self.syntax).next()
     }
 }
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct TupleFieldDefList {
+pub struct TupleExpr {
     pub(crate) syntax: SyntaxNode,
 }
-impl AstNode for TupleFieldDefList {
+impl AstNode for TupleExpr {
     fn can_cast(kind: SyntaxKind) -> bool {
         match kind {
-            TUPLE_FIELD_DEF_LIST => true,
+            TUPLE_EXPR => true,
             _ => false,
         }
     }
@@ -3241,8 +3206,8 @@ impl AstNode for TupleFieldDefList {
         &self.syntax
     }
 }
-impl TupleFieldDefList {
-    pub fn fields(&self) -> AstChildren<TupleFieldDef> {
+impl TupleExpr {
+    pub fn exprs(&self) -> AstChildren<Expr> {
         AstChildren::new(&self.syntax)
     }
 }
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
index 1836862fe0..26efeeba99 100644
--- a/crates/ra_syntax/src/grammar.ron
+++ b/crates/ra_syntax/src/grammar.ron
@@ -158,13 +158,12 @@ Grammar(
         "DYN_TRAIT_TYPE",
 
         "REF_PAT",
-        "BOX_PAT",
         "BIND_PAT",
         "PLACEHOLDER_PAT",
         "PATH_PAT",
-        "RECORD_PAT",
-        "RECORD_FIELD_PAT_LIST",
-        "RECORD_FIELD_PAT",
+        "STRUCT_PAT",
+        "FIELD_PAT_LIST",
+        "FIELD_PAT",
         "TUPLE_STRUCT_PAT",
         "TUPLE_PAT",
         "SLICE_PAT",
@@ -191,9 +190,9 @@ Grammar(
         "MATCH_ARM_LIST",
         "MATCH_ARM",
         "MATCH_GUARD",
-        "RECORD_LIT",
-        "RECORD_FIELD_LIST",
-        "RECORD_FIELD",
+        "STRUCT_LIT",
+        "NAMED_FIELD_LIST",
+        "NAMED_FIELD",
         "TRY_BLOCK_EXPR",
         "BOX_EXPR",
 
@@ -217,10 +216,10 @@ Grammar(
         "EXTERN_BLOCK",
         "EXTERN_ITEM_LIST",
         "ENUM_VARIANT",
-        "RECORD_FIELD_DEF_LIST",
-        "RECORD_FIELD_DEF",
-        "TUPLE_FIELD_DEF_LIST",
-        "TUPLE_FIELD_DEF",
+        "NAMED_FIELD_DEF_LIST",
+        "NAMED_FIELD_DEF",
+        "POS_FIELD_DEF_LIST",
+        "POS_FIELD_DEF",
         "ENUM_VARIANT_LIST",
         "ITEM_LIST",
         "ATTR",
@@ -287,8 +286,8 @@ Grammar(
                 "DocCommentsOwner"
             ]
         ),
-        "RecordFieldDefList": (collections: [("fields", "RecordFieldDef")]),
-        "RecordFieldDef": (
+        "NamedFieldDefList": (collections: [("fields", "NamedFieldDef")]),
+        "NamedFieldDef": (
             traits: [
                 "VisibilityOwner",
                 "NameOwner",
@@ -297,8 +296,8 @@ Grammar(
                 "TypeAscriptionOwner"
             ]
         ),
-        "TupleFieldDefList": (collections: [("fields", "TupleFieldDef")]),
-        "TupleFieldDef": ( traits: ["VisibilityOwner", "AttrsOwner"], options: ["TypeRef"]),
+        "PosFieldDefList": (collections: [("fields", "PosFieldDef")]),
+        "PosFieldDef": ( traits: ["VisibilityOwner", "AttrsOwner"], options: ["TypeRef"]),
         "EnumDef": ( traits: [
             "VisibilityOwner",
             "NameOwner",
@@ -462,12 +461,12 @@ Grammar(
             traits: [ "AttrsOwner" ]
         ),
         "MatchGuard": (options: ["Expr"]),
-        "RecordLit": (options: ["Path", "RecordFieldList"]),
-        "RecordFieldList": (
-            collections: [ ("fields", "RecordField") ],
+        "StructLit": (options: ["Path", "NamedFieldList"]),
+        "NamedFieldList": (
+            collections: [ ("fields", "NamedField") ],
             options: [["spread", "Expr"]]
         ),
-        "RecordField": (options: ["NameRef", "Expr"]),
+        "NamedField": (options: ["NameRef", "Expr"]),
         "CallExpr": (
             traits: ["ArgListOwner"],
             options: [ "Expr" ],
@@ -505,7 +504,7 @@ Grammar(
                 "BlockExpr",
                 "ReturnExpr",
                 "MatchExpr",
-                "RecordLit",
+                "StructLit",
                 "CallExpr",
                 "IndexExpr",
                 "MethodCallExpr",
@@ -524,21 +523,20 @@ Grammar(
         ),
 
         "RefPat": ( options: [ "Pat" ]),
-        "BoxPat": ( options: [ "Pat" ]),
         "BindPat": (
             options: [ "Pat" ],
             traits: ["NameOwner"]
         ),
         "PlaceholderPat": (),
         "PathPat": ( options: [ "Path" ] ),
-        "RecordPat": ( options: ["RecordFieldPatList", "Path"] ),
-        "RecordFieldPatList": (
+        "StructPat": ( options: ["FieldPatList", "Path"] ),
+        "FieldPatList": (
             collections: [
-                ("record_field_pats", "RecordFieldPat"),
+                ("field_pats", "FieldPat"),
                 ("bind_pats", "BindPat"),
             ]
         ),
-        "RecordFieldPat": (
+        "FieldPat": (
             traits: ["NameOwner"],
             options: ["Pat"]
         ),
@@ -554,11 +552,10 @@ Grammar(
         "Pat": (
             enum: [
                 "RefPat",
-                "BoxPat",
                 "BindPat",
                 "PlaceholderPat",
                 "PathPat",
-                "RecordPat",
+                "StructPat",
                 "TupleStructPat",
                 "TuplePat",
                 "SlicePat",
diff --git a/crates/ra_syntax/src/parsing/text_tree_sink.rs b/crates/ra_syntax/src/parsing/text_tree_sink.rs
index f59c559e95..bf1b35c95a 100644
--- a/crates/ra_syntax/src/parsing/text_tree_sink.rs
+++ b/crates/ra_syntax/src/parsing/text_tree_sink.rs
@@ -145,7 +145,7 @@ fn n_attached_trivias<'a>(
 ) -> usize {
     match kind {
         CONST_DEF | TYPE_ALIAS_DEF | STRUCT_DEF | ENUM_DEF | ENUM_VARIANT | FN_DEF | TRAIT_DEF
-        | MODULE | RECORD_FIELD_DEF => {
+        | MODULE | NAMED_FIELD_DEF => {
             let mut res = 0;
             for (i, (kind, text)) in trivias.enumerate() {
                 match kind {
diff --git a/crates/ra_syntax/src/ptr.rs b/crates/ra_syntax/src/ptr.rs
index 992034ef0f..8665c8976a 100644
--- a/crates/ra_syntax/src/ptr.rs
+++ b/crates/ra_syntax/src/ptr.rs
@@ -31,13 +31,6 @@ impl SyntaxNodePtr {
     pub fn kind(self) -> SyntaxKind {
         self.kind
     }
-
-    pub fn cast<N: AstNode>(self) -> Option<AstPtr<N>> {
-        if !N::can_cast(self.kind()) {
-            return None;
-        }
-        Some(AstPtr { raw: self, _ty: PhantomData })
-    }
 }
 
 /// Like `SyntaxNodePtr`, but remembers the type of node
@@ -87,7 +80,7 @@ fn test_local_syntax_ptr() {
     use crate::{ast, AstNode, SourceFile};
 
     let file = SourceFile::parse("struct Foo { f: u32, }").ok().unwrap();
-    let field = file.syntax().descendants().find_map(ast::RecordFieldDef::cast).unwrap();
+    let field = file.syntax().descendants().find_map(ast::NamedFieldDef::cast).unwrap();
     let ptr = SyntaxNodePtr::new(field.syntax());
     let field_syntax = ptr.to_node(file.syntax());
     assert_eq!(field.syntax(), &field_syntax);
diff --git a/crates/ra_syntax/src/validation.rs b/crates/ra_syntax/src/validation.rs
index ee87974109..a8c789e0ca 100644
--- a/crates/ra_syntax/src/validation.rs
+++ b/crates/ra_syntax/src/validation.rs
@@ -99,7 +99,7 @@ pub(crate) fn validate(root: &SyntaxNode) -> Vec<SyntaxError> {
             .visit::<ast::Literal, _>(validate_literal)
             .visit::<ast::Block, _>(block::validate_block_node)
             .visit::<ast::FieldExpr, _>(|it, errors| validate_numeric_name(it.name_ref(), errors))
-            .visit::<ast::RecordField, _>(|it, errors| validate_numeric_name(it.name_ref(), errors))
+            .visit::<ast::NamedField, _>(|it, errors| validate_numeric_name(it.name_ref(), errors))
             .accept(&node);
     }
     errors
diff --git a/crates/ra_vfs_glob/Cargo.toml b/crates/ra_vfs_glob/Cargo.toml
index 09ba3d3bfe..0390d7da16 100644
--- a/crates/ra_vfs_glob/Cargo.toml
+++ b/crates/ra_vfs_glob/Cargo.toml
@@ -5,5 +5,5 @@ version = "0.1.0"
 authors = ["rust-analyzer developers"]
 
 [dependencies]
-ra_vfs = "0.3.0"
+ra_vfs = "0.2.0"
 globset = "0.4.4"
diff --git a/editors/code/package-lock.json b/editors/code/package-lock.json
index 56cac1b494..5ffd8b0bd0 100644
--- a/editors/code/package-lock.json
+++ b/editors/code/package-lock.json
@@ -24,6 +24,29 @@
                 "js-tokens": "^4.0.0"
             }
         },
+        "@types/events": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz",
+            "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==",
+            "dev": true
+        },
+        "@types/glob": {
+            "version": "7.1.1",
+            "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz",
+            "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==",
+            "dev": true,
+            "requires": {
+                "@types/events": "*",
+                "@types/minimatch": "*",
+                "@types/node": "*"
+            }
+        },
+        "@types/minimatch": {
+            "version": "3.0.3",
+            "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
+            "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==",
+            "dev": true
+        },
         "@types/mocha": {
             "version": "5.2.7",
             "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz",
@@ -42,6 +65,12 @@
             "integrity": "sha512-SMA+fUwULwK7sd/ZJicUztiPs8F1yCPwF3O23Z9uQ32ME5Ha0NmDK9+QTsYE4O2tHXChzXomSWWeIhCnoN1LqA==",
             "dev": true
         },
+        "@types/vscode": {
+            "version": "1.37.0",
+            "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.37.0.tgz",
+            "integrity": "sha512-PRfeuqYuzk3vjf+puzxltIUWC+AhEGYpFX29/37w30DQSQnpf5AgMVf7GDBAdmTbWTBou+EMFz/Ne6XCM/KxzQ==",
+            "dev": true
+        },
         "agent-base": {
             "version": "4.3.0",
             "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz",
@@ -51,17 +80,17 @@
                 "es6-promisify": "^5.0.0"
             }
         },
-        "ajv": {
-            "version": "6.10.2",
-            "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
-            "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
-            "dev": true,
-            "requires": {
-                "fast-deep-equal": "^2.0.1",
-                "fast-json-stable-stringify": "^2.0.0",
-                "json-schema-traverse": "^0.4.1",
-                "uri-js": "^4.2.2"
-            }
+        "ansi-colors": {
+            "version": "3.2.3",
+            "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz",
+            "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==",
+            "dev": true
+        },
+        "ansi-regex": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+            "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+            "dev": true
         },
         "ansi-styles": {
             "version": "3.2.1",
@@ -81,39 +110,6 @@
                 "sprintf-js": "~1.0.2"
             }
         },
-        "asn1": {
-            "version": "0.2.4",
-            "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
-            "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
-            "dev": true,
-            "requires": {
-                "safer-buffer": "~2.1.0"
-            }
-        },
-        "assert-plus": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
-            "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
-            "dev": true
-        },
-        "asynckit": {
-            "version": "0.4.0",
-            "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
-            "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
-            "dev": true
-        },
-        "aws-sign2": {
-            "version": "0.7.0",
-            "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
-            "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
-            "dev": true
-        },
-        "aws4": {
-            "version": "1.8.0",
-            "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
-            "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==",
-            "dev": true
-        },
         "azure-devops-node-api": {
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-7.2.0.tgz",
@@ -132,15 +128,6 @@
             "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
             "dev": true
         },
-        "bcrypt-pbkdf": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
-            "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
-            "dev": true,
-            "requires": {
-                "tweetnacl": "^0.14.3"
-            }
-        },
         "boolbase": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
@@ -169,22 +156,16 @@
             "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=",
             "dev": true
         },
-        "buffer-from": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
-            "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
-            "dev": true
-        },
         "builtin-modules": {
             "version": "1.1.1",
             "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
             "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
             "dev": true
         },
-        "caseless": {
-            "version": "0.12.0",
-            "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
-            "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
+        "camelcase": {
+            "version": "5.3.1",
+            "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+            "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
             "dev": true
         },
         "chalk": {
@@ -212,6 +193,23 @@
                 "parse5": "^3.0.1"
             }
         },
+        "cliui": {
+            "version": "4.1.0",
+            "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
+            "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==",
+            "dev": true,
+            "requires": {
+                "string-width": "^2.1.1",
+                "strip-ansi": "^4.0.0",
+                "wrap-ansi": "^2.0.0"
+            }
+        },
+        "code-point-at": {
+            "version": "1.1.0",
+            "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
+            "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
+            "dev": true
+        },
         "color-convert": {
             "version": "1.9.3",
             "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
@@ -227,15 +225,6 @@
             "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
             "dev": true
         },
-        "combined-stream": {
-            "version": "1.0.8",
-            "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
-            "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
-            "dev": true,
-            "requires": {
-                "delayed-stream": "~1.0.0"
-            }
-        },
         "commander": {
             "version": "2.20.0",
             "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz",
@@ -248,11 +237,18 @@
             "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
             "dev": true
         },
-        "core-util-is": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
-            "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
-            "dev": true
+        "cross-spawn": {
+            "version": "6.0.5",
+            "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+            "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+            "dev": true,
+            "requires": {
+                "nice-try": "^1.0.4",
+                "path-key": "^2.0.1",
+                "semver": "^5.5.0",
+                "shebang-command": "^1.2.0",
+                "which": "^1.2.9"
+            }
         },
         "css-select": {
             "version": "1.2.0",
@@ -272,15 +268,6 @@
             "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==",
             "dev": true
         },
-        "dashdash": {
-            "version": "1.14.1",
-            "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
-            "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
-            "dev": true,
-            "requires": {
-                "assert-plus": "^1.0.0"
-            }
-        },
         "debug": {
             "version": "3.1.0",
             "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
@@ -290,12 +277,21 @@
                 "ms": "2.0.0"
             }
         },
-        "delayed-stream": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
-            "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
+        "decamelize": {
+            "version": "1.2.0",
+            "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+            "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
             "dev": true
         },
+        "define-properties": {
+            "version": "1.1.3",
+            "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
+            "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
+            "dev": true,
+            "requires": {
+                "object-keys": "^1.0.12"
+            }
+        },
         "denodeify": {
             "version": "1.2.1",
             "resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz",
@@ -349,14 +345,19 @@
                 "domelementtype": "1"
             }
         },
-        "ecc-jsbn": {
-            "version": "0.1.2",
-            "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
-            "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
+        "emoji-regex": {
+            "version": "7.0.3",
+            "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
+            "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
+            "dev": true
+        },
+        "end-of-stream": {
+            "version": "1.4.1",
+            "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
+            "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==",
             "dev": true,
             "requires": {
-                "jsbn": "~0.1.0",
-                "safer-buffer": "^2.1.0"
+                "once": "^1.4.0"
             }
         },
         "entities": {
@@ -365,6 +366,31 @@
             "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==",
             "dev": true
         },
+        "es-abstract": {
+            "version": "1.13.0",
+            "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz",
+            "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==",
+            "dev": true,
+            "requires": {
+                "es-to-primitive": "^1.2.0",
+                "function-bind": "^1.1.1",
+                "has": "^1.0.3",
+                "is-callable": "^1.1.4",
+                "is-regex": "^1.0.4",
+                "object-keys": "^1.0.12"
+            }
+        },
+        "es-to-primitive": {
+            "version": "1.2.0",
+            "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz",
+            "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==",
+            "dev": true,
+            "requires": {
+                "is-callable": "^1.1.4",
+                "is-date-object": "^1.0.1",
+                "is-symbol": "^1.0.2"
+            }
+        },
         "es6-object-assign": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz",
@@ -404,29 +430,20 @@
             "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
             "dev": true
         },
-        "extend": {
-            "version": "3.0.2",
-            "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
-            "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
-            "dev": true
-        },
-        "extsprintf": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
-            "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
-            "dev": true
-        },
-        "fast-deep-equal": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
-            "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
-            "dev": true
-        },
-        "fast-json-stable-stringify": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
-            "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=",
-            "dev": true
+        "execa": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
+            "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
+            "dev": true,
+            "requires": {
+                "cross-spawn": "^6.0.0",
+                "get-stream": "^4.0.0",
+                "is-stream": "^1.1.0",
+                "npm-run-path": "^2.0.0",
+                "p-finally": "^1.0.0",
+                "signal-exit": "^3.0.0",
+                "strip-eof": "^1.0.0"
+            }
         },
         "fd-slicer": {
             "version": "1.1.0",
@@ -437,21 +454,22 @@
                 "pend": "~1.2.0"
             }
         },
-        "forever-agent": {
-            "version": "0.6.1",
-            "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
-            "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
-            "dev": true
+        "find-up": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+            "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+            "dev": true,
+            "requires": {
+                "locate-path": "^3.0.0"
+            }
         },
-        "form-data": {
-            "version": "2.3.3",
-            "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
-            "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
+        "flat": {
+            "version": "4.1.0",
+            "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz",
+            "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==",
             "dev": true,
             "requires": {
-                "asynckit": "^0.4.0",
-                "combined-stream": "^1.0.6",
-                "mime-types": "^2.1.12"
+                "is-buffer": "~2.0.3"
             }
         },
         "fs.realpath": {
@@ -460,19 +478,31 @@
             "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
             "dev": true
         },
-        "getpass": {
-            "version": "0.1.7",
-            "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
-            "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
+        "function-bind": {
+            "version": "1.1.1",
+            "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+            "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+            "dev": true
+        },
+        "get-caller-file": {
+            "version": "2.0.5",
+            "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+            "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+            "dev": true
+        },
+        "get-stream": {
+            "version": "4.1.0",
+            "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
+            "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
             "dev": true,
             "requires": {
-                "assert-plus": "^1.0.0"
+                "pump": "^3.0.0"
             }
         },
         "glob": {
-            "version": "7.1.3",
-            "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
-            "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
+            "version": "7.1.4",
+            "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
+            "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
             "dev": true,
             "requires": {
                 "fs.realpath": "^1.0.0",
@@ -489,20 +519,13 @@
             "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==",
             "dev": true
         },
-        "har-schema": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
-            "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
-            "dev": true
-        },
-        "har-validator": {
-            "version": "5.1.3",
-            "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz",
-            "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==",
+        "has": {
+            "version": "1.0.3",
+            "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+            "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
             "dev": true,
             "requires": {
-                "ajv": "^6.5.5",
-                "har-schema": "^2.0.0"
+                "function-bind": "^1.1.1"
             }
         },
         "has-flag": {
@@ -511,10 +534,16 @@
             "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
             "dev": true
         },
+        "has-symbols": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
+            "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=",
+            "dev": true
+        },
         "he": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz",
-            "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=",
+            "version": "1.2.0",
+            "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
+            "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
             "dev": true
         },
         "htmlparser2": {
@@ -541,17 +570,6 @@
                 "debug": "3.1.0"
             }
         },
-        "http-signature": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
-            "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
-            "dev": true,
-            "requires": {
-                "assert-plus": "^1.0.0",
-                "jsprim": "^1.2.2",
-                "sshpk": "^1.7.0"
-            }
-        },
         "https-proxy-agent": {
             "version": "2.2.2",
             "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.2.tgz",
@@ -584,16 +602,64 @@
             "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==",
             "dev": true
         },
-        "is-typedarray": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
-            "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
+        "invert-kv": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz",
+            "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==",
             "dev": true
         },
-        "isstream": {
-            "version": "0.1.2",
-            "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
-            "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
+        "is-buffer": {
+            "version": "2.0.3",
+            "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz",
+            "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==",
+            "dev": true
+        },
+        "is-callable": {
+            "version": "1.1.4",
+            "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz",
+            "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==",
+            "dev": true
+        },
+        "is-date-object": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
+            "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=",
+            "dev": true
+        },
+        "is-fullwidth-code-point": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+            "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+            "dev": true
+        },
+        "is-regex": {
+            "version": "1.0.4",
+            "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
+            "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
+            "dev": true,
+            "requires": {
+                "has": "^1.0.1"
+            }
+        },
+        "is-stream": {
+            "version": "1.1.0",
+            "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+            "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
+            "dev": true
+        },
+        "is-symbol": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz",
+            "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==",
+            "dev": true,
+            "requires": {
+                "has-symbols": "^1.0.0"
+            }
+        },
+        "isexe": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+            "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
             "dev": true
         },
         "js-tokens": {
@@ -612,40 +678,13 @@
                 "esprima": "^4.0.0"
             }
         },
-        "jsbn": {
-            "version": "0.1.1",
-            "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
-            "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
-            "dev": true
-        },
-        "json-schema": {
-            "version": "0.2.3",
-            "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
-            "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
-            "dev": true
-        },
-        "json-schema-traverse": {
-            "version": "0.4.1",
-            "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
-            "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
-            "dev": true
-        },
-        "json-stringify-safe": {
-            "version": "5.0.1",
-            "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
-            "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
-            "dev": true
-        },
-        "jsprim": {
-            "version": "1.4.1",
-            "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
-            "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
+        "lcid": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz",
+            "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==",
             "dev": true,
             "requires": {
-                "assert-plus": "1.0.0",
-                "extsprintf": "1.3.0",
-                "json-schema": "0.2.3",
-                "verror": "1.10.0"
+                "invert-kv": "^2.0.0"
             }
         },
         "linkify-it": {
@@ -657,12 +696,40 @@
                 "uc.micro": "^1.0.1"
             }
         },
+        "locate-path": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+            "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+            "dev": true,
+            "requires": {
+                "p-locate": "^3.0.0",
+                "path-exists": "^3.0.0"
+            }
+        },
         "lodash": {
             "version": "4.17.15",
             "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
             "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
             "dev": true
         },
+        "log-symbols": {
+            "version": "2.2.0",
+            "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz",
+            "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==",
+            "dev": true,
+            "requires": {
+                "chalk": "^2.0.1"
+            }
+        },
+        "map-age-cleaner": {
+            "version": "0.1.3",
+            "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz",
+            "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==",
+            "dev": true,
+            "requires": {
+                "p-defer": "^1.0.0"
+            }
+        },
         "markdown-it": {
             "version": "8.4.2",
             "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.2.tgz",
@@ -682,27 +749,29 @@
             "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=",
             "dev": true
         },
+        "mem": {
+            "version": "4.3.0",
+            "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz",
+            "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==",
+            "dev": true,
+            "requires": {
+                "map-age-cleaner": "^0.1.1",
+                "mimic-fn": "^2.0.0",
+                "p-is-promise": "^2.0.0"
+            }
+        },
         "mime": {
             "version": "1.6.0",
             "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
             "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
             "dev": true
         },
-        "mime-db": {
-            "version": "1.40.0",
-            "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
-            "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==",
+        "mimic-fn": {
+            "version": "2.1.0",
+            "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+            "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
             "dev": true
         },
-        "mime-types": {
-            "version": "2.1.24",
-            "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
-            "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
-            "dev": true,
-            "requires": {
-                "mime-db": "1.40.0"
-            }
-        },
         "minimatch": {
             "version": "3.0.4",
             "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
@@ -728,34 +797,49 @@
             }
         },
         "mocha": {
-            "version": "5.2.0",
-            "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz",
-            "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==",
+            "version": "6.2.0",
+            "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.0.tgz",
+            "integrity": "sha512-qwfFgY+7EKAAUAdv7VYMZQknI7YJSGesxHyhn6qD52DV8UcSZs5XwCifcZGMVIE4a5fbmhvbotxC0DLQ0oKohQ==",
             "dev": true,
             "requires": {
+                "ansi-colors": "3.2.3",
                 "browser-stdout": "1.3.1",
-                "commander": "2.15.1",
-                "debug": "3.1.0",
+                "debug": "3.2.6",
                 "diff": "3.5.0",
                 "escape-string-regexp": "1.0.5",
-                "glob": "7.1.2",
+                "find-up": "3.0.0",
+                "glob": "7.1.3",
                 "growl": "1.10.5",
-                "he": "1.1.1",
+                "he": "1.2.0",
+                "js-yaml": "3.13.1",
+                "log-symbols": "2.2.0",
                 "minimatch": "3.0.4",
                 "mkdirp": "0.5.1",
-                "supports-color": "5.4.0"
+                "ms": "2.1.1",
+                "node-environment-flags": "1.0.5",
+                "object.assign": "4.1.0",
+                "strip-json-comments": "2.0.1",
+                "supports-color": "6.0.0",
+                "which": "1.3.1",
+                "wide-align": "1.1.3",
+                "yargs": "13.2.2",
+                "yargs-parser": "13.0.0",
+                "yargs-unparser": "1.5.0"
             },
             "dependencies": {
-                "commander": {
-                    "version": "2.15.1",
-                    "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
-                    "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==",
-                    "dev": true
+                "debug": {
+                    "version": "3.2.6",
+                    "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+                    "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+                    "dev": true,
+                    "requires": {
+                        "ms": "^2.1.1"
+                    }
                 },
                 "glob": {
-                    "version": "7.1.2",
-                    "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
-                    "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
+                    "version": "7.1.3",
+                    "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
+                    "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
                     "dev": true,
                     "requires": {
                         "fs.realpath": "^1.0.0",
@@ -766,10 +850,16 @@
                         "path-is-absolute": "^1.0.0"
                     }
                 },
+                "ms": {
+                    "version": "2.1.1",
+                    "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+                    "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
+                    "dev": true
+                },
                 "supports-color": {
-                    "version": "5.4.0",
-                    "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz",
-                    "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==",
+                    "version": "6.0.0",
+                    "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz",
+                    "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==",
                     "dev": true,
                     "requires": {
                         "has-flag": "^3.0.0"
@@ -789,6 +879,31 @@
             "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
             "dev": true
         },
+        "nice-try": {
+            "version": "1.0.5",
+            "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+            "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
+            "dev": true
+        },
+        "node-environment-flags": {
+            "version": "1.0.5",
+            "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz",
+            "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==",
+            "dev": true,
+            "requires": {
+                "object.getownpropertydescriptors": "^2.0.3",
+                "semver": "^5.7.0"
+            }
+        },
+        "npm-run-path": {
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
+            "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
+            "dev": true,
+            "requires": {
+                "path-key": "^2.0.0"
+            }
+        },
         "nth-check": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz",
@@ -798,12 +913,40 @@
                 "boolbase": "~1.0.0"
             }
         },
-        "oauth-sign": {
-            "version": "0.9.0",
-            "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
-            "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
+        "number-is-nan": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
+            "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
+            "dev": true
+        },
+        "object-keys": {
+            "version": "1.1.1",
+            "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+            "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
             "dev": true
         },
+        "object.assign": {
+            "version": "4.1.0",
+            "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
+            "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
+            "dev": true,
+            "requires": {
+                "define-properties": "^1.1.2",
+                "function-bind": "^1.1.1",
+                "has-symbols": "^1.0.0",
+                "object-keys": "^1.0.11"
+            }
+        },
+        "object.getownpropertydescriptors": {
+            "version": "2.0.3",
+            "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz",
+            "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=",
+            "dev": true,
+            "requires": {
+                "define-properties": "^1.1.2",
+                "es-abstract": "^1.5.1"
+            }
+        },
         "once": {
             "version": "1.4.0",
             "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@@ -825,6 +968,17 @@
             "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
             "dev": true
         },
+        "os-locale": {
+            "version": "3.1.0",
+            "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz",
+            "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==",
+            "dev": true,
+            "requires": {
+                "execa": "^1.0.0",
+                "lcid": "^2.0.0",
+                "mem": "^4.0.0"
+            }
+        },
         "os-tmpdir": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
@@ -841,6 +995,48 @@
                 "os-tmpdir": "^1.0.0"
             }
         },
+        "p-defer": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz",
+            "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=",
+            "dev": true
+        },
+        "p-finally": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
+            "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=",
+            "dev": true
+        },
+        "p-is-promise": {
+            "version": "2.1.0",
+            "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz",
+            "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==",
+            "dev": true
+        },
+        "p-limit": {
+            "version": "2.2.1",
+            "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz",
+            "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==",
+            "dev": true,
+            "requires": {
+                "p-try": "^2.0.0"
+            }
+        },
+        "p-locate": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+            "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+            "dev": true,
+            "requires": {
+                "p-limit": "^2.0.0"
+            }
+        },
+        "p-try": {
+            "version": "2.2.0",
+            "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+            "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+            "dev": true
+        },
         "parse-semver": {
             "version": "1.1.1",
             "resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz",
@@ -859,12 +1055,24 @@
                 "@types/node": "*"
             }
         },
+        "path-exists": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+            "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+            "dev": true
+        },
         "path-is-absolute": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
             "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
             "dev": true
         },
+        "path-key": {
+            "version": "2.0.1",
+            "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+            "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
+            "dev": true
+        },
         "path-parse": {
             "version": "1.0.6",
             "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
@@ -877,41 +1085,21 @@
             "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=",
             "dev": true
         },
-        "performance-now": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
-            "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
-            "dev": true
-        },
         "prettier": {
             "version": "1.18.2",
             "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.18.2.tgz",
             "integrity": "sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw==",
             "dev": true
         },
-        "psl": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/psl/-/psl-1.2.0.tgz",
-            "integrity": "sha512-GEn74ZffufCmkDDLNcl3uuyF/aSD6exEyh1v/ZSdAomB82t6G9hzJVRx0jBmLDW+VfZqks3aScmMw9DszwUalA==",
-            "dev": true
-        },
-        "punycode": {
-            "version": "2.1.1",
-            "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
-            "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
-            "dev": true
-        },
-        "qs": {
-            "version": "6.5.2",
-            "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
-            "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
-            "dev": true
-        },
-        "querystringify": {
-            "version": "2.1.1",
-            "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz",
-            "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==",
-            "dev": true
+        "pump": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+            "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+            "dev": true,
+            "requires": {
+                "end-of-stream": "^1.1.0",
+                "once": "^1.3.1"
+            }
         },
         "read": {
             "version": "1.0.7",
@@ -942,38 +1130,16 @@
                 "resolve": "^1.1.6"
             }
         },
-        "request": {
-            "version": "2.88.0",
-            "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
-            "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
-            "dev": true,
-            "requires": {
-                "aws-sign2": "~0.7.0",
-                "aws4": "^1.8.0",
-                "caseless": "~0.12.0",
-                "combined-stream": "~1.0.6",
-                "extend": "~3.0.2",
-                "forever-agent": "~0.6.1",
-                "form-data": "~2.3.2",
-                "har-validator": "~5.1.0",
-                "http-signature": "~1.2.0",
-                "is-typedarray": "~1.0.0",
-                "isstream": "~0.1.2",
-                "json-stringify-safe": "~5.0.1",
-                "mime-types": "~2.1.19",
-                "oauth-sign": "~0.9.0",
-                "performance-now": "^2.1.0",
-                "qs": "~6.5.2",
-                "safe-buffer": "^5.1.2",
-                "tough-cookie": "~2.4.3",
-                "tunnel-agent": "^0.6.0",
-                "uuid": "^3.3.2"
-            }
-        },
-        "requires-port": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
-            "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
+        "require-directory": {
+            "version": "2.1.1",
+            "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+            "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
+            "dev": true
+        },
+        "require-main-filename": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+            "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
             "dev": true
         },
         "resolve": {
@@ -985,18 +1151,21 @@
                 "path-parse": "^1.0.6"
             }
         },
+        "rimraf": {
+            "version": "2.7.1",
+            "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+            "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+            "dev": true,
+            "requires": {
+                "glob": "^7.1.3"
+            }
+        },
         "safe-buffer": {
             "version": "5.1.2",
             "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
             "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
             "dev": true
         },
-        "safer-buffer": {
-            "version": "2.1.2",
-            "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
-            "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
-            "dev": true
-        },
         "seedrandom": {
             "version": "3.0.1",
             "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.1.tgz",
@@ -1007,6 +1176,27 @@
             "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
             "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA=="
         },
+        "set-blocking": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+            "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
+            "dev": true
+        },
+        "shebang-command": {
+            "version": "1.2.0",
+            "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+            "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+            "dev": true,
+            "requires": {
+                "shebang-regex": "^1.0.0"
+            }
+        },
+        "shebang-regex": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+            "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
+            "dev": true
+        },
         "shelljs": {
             "version": "0.8.3",
             "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.3.tgz",
@@ -1037,43 +1227,26 @@
                 }
             }
         },
-        "source-map": {
-            "version": "0.6.1",
-            "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-            "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+        "signal-exit": {
+            "version": "3.0.2",
+            "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
+            "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
             "dev": true
         },
-        "source-map-support": {
-            "version": "0.5.12",
-            "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz",
-            "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==",
-            "dev": true,
-            "requires": {
-                "buffer-from": "^1.0.0",
-                "source-map": "^0.6.0"
-            }
-        },
         "sprintf-js": {
             "version": "1.0.3",
             "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
             "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
             "dev": true
         },
-        "sshpk": {
-            "version": "1.16.1",
-            "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
-            "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
+        "string-width": {
+            "version": "2.1.1",
+            "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+            "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
             "dev": true,
             "requires": {
-                "asn1": "~0.2.3",
-                "assert-plus": "^1.0.0",
-                "bcrypt-pbkdf": "^1.0.0",
-                "dashdash": "^1.12.0",
-                "ecc-jsbn": "~0.1.1",
-                "getpass": "^0.1.1",
-                "jsbn": "~0.1.0",
-                "safer-buffer": "^2.0.2",
-                "tweetnacl": "~0.14.0"
+                "is-fullwidth-code-point": "^2.0.0",
+                "strip-ansi": "^4.0.0"
             }
         },
         "string_decoder": {
@@ -1085,6 +1258,27 @@
                 "safe-buffer": "~5.1.0"
             }
         },
+        "strip-ansi": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+            "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+            "dev": true,
+            "requires": {
+                "ansi-regex": "^3.0.0"
+            }
+        },
+        "strip-eof": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
+            "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
+            "dev": true
+        },
+        "strip-json-comments": {
+            "version": "2.0.1",
+            "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+            "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
+            "dev": true
+        },
         "supports-color": {
             "version": "5.5.0",
             "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
@@ -1103,24 +1297,6 @@
                 "os-tmpdir": "~1.0.1"
             }
         },
-        "tough-cookie": {
-            "version": "2.4.3",
-            "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
-            "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
-            "dev": true,
-            "requires": {
-                "psl": "^1.1.24",
-                "punycode": "^1.4.1"
-            },
-            "dependencies": {
-                "punycode": {
-                    "version": "1.4.1",
-                    "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
-                    "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
-                    "dev": true
-                }
-            }
-        },
         "tslib": {
             "version": "1.10.0",
             "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
@@ -1169,21 +1345,6 @@
             "integrity": "sha1-LTeFoVjBdMmhbcLARuxfxfF0IhM=",
             "dev": true
         },
-        "tunnel-agent": {
-            "version": "0.6.0",
-            "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
-            "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
-            "dev": true,
-            "requires": {
-                "safe-buffer": "^5.0.1"
-            }
-        },
-        "tweetnacl": {
-            "version": "0.14.5",
-            "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
-            "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
-            "dev": true
-        },
         "typed-rest-client": {
             "version": "1.2.0",
             "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.2.0.tgz",
@@ -1212,54 +1373,18 @@
             "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=",
             "dev": true
         },
-        "uri-js": {
-            "version": "4.2.2",
-            "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
-            "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
-            "dev": true,
-            "requires": {
-                "punycode": "^2.1.0"
-            }
-        },
         "url-join": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/url-join/-/url-join-1.1.0.tgz",
             "integrity": "sha1-dBxsL0WWxIMNZxhGCSDQySIC3Hg=",
             "dev": true
         },
-        "url-parse": {
-            "version": "1.4.7",
-            "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz",
-            "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==",
-            "dev": true,
-            "requires": {
-                "querystringify": "^2.1.1",
-                "requires-port": "^1.0.0"
-            }
-        },
         "util-deprecate": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
             "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
             "dev": true
         },
-        "uuid": {
-            "version": "3.3.2",
-            "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
-            "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==",
-            "dev": true
-        },
-        "verror": {
-            "version": "1.10.0",
-            "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
-            "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
-            "dev": true,
-            "requires": {
-                "assert-plus": "^1.0.0",
-                "core-util-is": "1.0.2",
-                "extsprintf": "^1.2.0"
-            }
-        },
         "vsce": {
             "version": "1.66.0",
             "resolved": "https://registry.npmjs.org/vsce/-/vsce-1.66.0.tgz",
@@ -1288,21 +1413,6 @@
                 "yazl": "^2.2.2"
             }
         },
-        "vscode": {
-            "version": "1.1.35",
-            "resolved": "https://registry.npmjs.org/vscode/-/vscode-1.1.35.tgz",
-            "integrity": "sha512-xPnxzQU40LOS2yPyzWW+WKpTV6qA3z16TcgpZ9O38UWLA157Zz4GxUx5H7Gd07pxzw0GqvusbF4D+5GBgNxvEQ==",
-            "dev": true,
-            "requires": {
-                "glob": "^7.1.2",
-                "mocha": "^5.2.0",
-                "request": "^2.88.0",
-                "semver": "^5.4.1",
-                "source-map-support": "^0.5.0",
-                "url-parse": "^1.4.4",
-                "vscode-test": "^0.4.1"
-            }
-        },
         "vscode-jsonrpc": {
             "version": "4.1.0-next.2",
             "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-4.1.0-next.2.tgz",
@@ -1332,13 +1442,85 @@
             "integrity": "sha512-2JkrMWWUi2rlVLSo9OFR2PIGUzdiowEM8NgNYiwLKnXTjpwpjjIrJbNNxDik7Rv4oo9KtikcFQZKXbrKilL/MQ=="
         },
         "vscode-test": {
-            "version": "0.4.3",
-            "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-0.4.3.tgz",
-            "integrity": "sha512-EkMGqBSefZH2MgW65nY05rdRSko15uvzq4VAPM5jVmwYuFQKE7eikKXNJDRxL+OITXHB6pI+a3XqqD32Y3KC5w==",
+            "version": "1.2.0",
+            "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-1.2.0.tgz",
+            "integrity": "sha512-aowqgc8gZe0eflzVUXsBjBrlsJ8eC35kfgfSEeHu9PKA1vQKm/3rVK43TlbxGue8hKtZBElNAJ5QuYklR/vLJA==",
             "dev": true,
             "requires": {
                 "http-proxy-agent": "^2.1.0",
-                "https-proxy-agent": "^2.2.1"
+                "https-proxy-agent": "^2.2.1",
+                "rimraf": "^2.6.3"
+            }
+        },
+        "which": {
+            "version": "1.3.1",
+            "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+            "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+            "dev": true,
+            "requires": {
+                "isexe": "^2.0.0"
+            }
+        },
+        "which-module": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
+            "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
+            "dev": true
+        },
+        "wide-align": {
+            "version": "1.1.3",
+            "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
+            "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
+            "dev": true,
+            "requires": {
+                "string-width": "^1.0.2 || 2"
+            }
+        },
+        "wrap-ansi": {
+            "version": "2.1.0",
+            "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
+            "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
+            "dev": true,
+            "requires": {
+                "string-width": "^1.0.1",
+                "strip-ansi": "^3.0.1"
+            },
+            "dependencies": {
+                "ansi-regex": {
+                    "version": "2.1.1",
+                    "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+                    "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+                    "dev": true
+                },
+                "is-fullwidth-code-point": {
+                    "version": "1.0.0",
+                    "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+                    "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+                    "dev": true,
+                    "requires": {
+                        "number-is-nan": "^1.0.0"
+                    }
+                },
+                "string-width": {
+                    "version": "1.0.2",
+                    "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+                    "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+                    "dev": true,
+                    "requires": {
+                        "code-point-at": "^1.0.0",
+                        "is-fullwidth-code-point": "^1.0.0",
+                        "strip-ansi": "^3.0.0"
+                    }
+                },
+                "strip-ansi": {
+                    "version": "3.0.1",
+                    "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+                    "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+                    "dev": true,
+                    "requires": {
+                        "ansi-regex": "^2.0.0"
+                    }
+                }
             }
         },
         "wrappy": {
@@ -1347,6 +1529,124 @@
             "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
             "dev": true
         },
+        "y18n": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
+            "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
+            "dev": true
+        },
+        "yargs": {
+            "version": "13.2.2",
+            "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.2.tgz",
+            "integrity": "sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==",
+            "dev": true,
+            "requires": {
+                "cliui": "^4.0.0",
+                "find-up": "^3.0.0",
+                "get-caller-file": "^2.0.1",
+                "os-locale": "^3.1.0",
+                "require-directory": "^2.1.1",
+                "require-main-filename": "^2.0.0",
+                "set-blocking": "^2.0.0",
+                "string-width": "^3.0.0",
+                "which-module": "^2.0.0",
+                "y18n": "^4.0.0",
+                "yargs-parser": "^13.0.0"
+            },
+            "dependencies": {
+                "ansi-regex": {
+                    "version": "4.1.0",
+                    "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+                    "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+                    "dev": true
+                },
+                "string-width": {
+                    "version": "3.1.0",
+                    "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+                    "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+                    "dev": true,
+                    "requires": {
+                        "emoji-regex": "^7.0.1",
+                        "is-fullwidth-code-point": "^2.0.0",
+                        "strip-ansi": "^5.1.0"
+                    }
+                },
+                "strip-ansi": {
+                    "version": "5.2.0",
+                    "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+                    "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+                    "dev": true,
+                    "requires": {
+                        "ansi-regex": "^4.1.0"
+                    }
+                }
+            }
+        },
+        "yargs-parser": {
+            "version": "13.0.0",
+            "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz",
+            "integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==",
+            "dev": true,
+            "requires": {
+                "camelcase": "^5.0.0",
+                "decamelize": "^1.2.0"
+            }
+        },
+        "yargs-unparser": {
+            "version": "1.5.0",
+            "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.5.0.tgz",
+            "integrity": "sha512-HK25qidFTCVuj/D1VfNiEndpLIeJN78aqgR23nL3y4N0U/91cOAzqfHlF8n2BvoNDcZmJKin3ddNSvOxSr8flw==",
+            "dev": true,
+            "requires": {
+                "flat": "^4.1.0",
+                "lodash": "^4.17.11",
+                "yargs": "^12.0.5"
+            },
+            "dependencies": {
+                "get-caller-file": {
+                    "version": "1.0.3",
+                    "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
+                    "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==",
+                    "dev": true
+                },
+                "require-main-filename": {
+                    "version": "1.0.1",
+                    "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
+                    "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=",
+                    "dev": true
+                },
+                "yargs": {
+                    "version": "12.0.5",
+                    "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz",
+                    "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==",
+                    "dev": true,
+                    "requires": {
+                        "cliui": "^4.0.0",
+                        "decamelize": "^1.2.0",
+                        "find-up": "^3.0.0",
+                        "get-caller-file": "^1.0.1",
+                        "os-locale": "^3.0.0",
+                        "require-directory": "^2.1.1",
+                        "require-main-filename": "^1.0.1",
+                        "set-blocking": "^2.0.0",
+                        "string-width": "^2.0.0",
+                        "which-module": "^2.0.0",
+                        "y18n": "^3.2.1 || ^4.0.0",
+                        "yargs-parser": "^11.1.1"
+                    }
+                },
+                "yargs-parser": {
+                    "version": "11.1.1",
+                    "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz",
+                    "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==",
+                    "dev": true,
+                    "requires": {
+                        "camelcase": "^5.0.0",
+                        "decamelize": "^1.2.0"
+                    }
+                }
+            }
+        },
         "yauzl": {
             "version": "2.10.0",
             "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
diff --git a/editors/code/package.json b/editors/code/package.json
index 95ec6cff6f..e2bc72f325 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -13,18 +13,17 @@
         "Other"
     ],
     "engines": {
-        "vscode": "^1.33.0"
+        "vscode": "^1.36.0"
     },
     "scripts": {
         "vscode:prepublish": "npm run compile",
         "package": "vsce package",
         "compile": "tsc -p ./ && shx cp src/utils/terminateProcess.sh out/utils/terminateProcess.sh",
         "watch": "tsc -watch -p ./",
-        "postinstall": "node ./node_modules/vscode/bin/install",
         "fix": "prettier **/*.{json,ts} --write && tslint --project . --fix",
         "lint": "tslint --project .",
-        "test": "node node_modules/vscode/bin/test",
         "prettier": "prettier **/*.{json,ts}",
+        "test": "node ./out/test/runTest.js",
         "travis": "npm run compile && npm run test && npm run lint && npm run prettier -- --write && git diff --exit-code"
     },
     "prettier": {
@@ -39,13 +38,17 @@
         "@types/mocha": "^5.2.7",
         "@types/node": "^10.14.13",
         "@types/seedrandom": "^2.4.28",
+        "@types/glob": "^7.1.1",
+        "@types/vscode": "^1.36.0",
+        "glob": "^7.1.4",
+        "mocha": "^6.2.0",
         "prettier": "^1.18.2",
         "shx": "^0.3.1",
         "tslint": "^5.18.0",
         "tslint-config-prettier": "^1.18.0",
         "typescript": "^3.5.3",
         "vsce": "^1.66.0",
-        "vscode": "^1.1.35"
+        "vscode-test": "^1.2.0"
     },
     "activationEvents": [
         "onLanguage:rust",
diff --git a/editors/code/src/utils/diagnostics/rust.ts b/editors/code/src/utils/diagnostics/rust.ts
index bfb494a3a5..1fb1f7b6dc 100644
--- a/editors/code/src/utils/diagnostics/rust.ts
+++ b/editors/code/src/utils/diagnostics/rust.ts
@@ -64,7 +64,7 @@ function mapLevelToSeverity(s: string): vscode.DiagnosticSeverity {
  * Converts a Rust span to a VsCode location
  */
 function mapSpanToLocation(span: RustDiagnosticSpan): vscode.Location {
-    const fileName = path.join(vscode.workspace.rootPath!, span.file_name);
+    const fileName = path.join(vscode.workspace.rootPath || '', span.file_name);
     const fileUri = vscode.Uri.file(fileName);
 
     const range = new vscode.Range(


Test patch:
diff --git a/crates/ra_mbe/src/tests.rs b/crates/ra_mbe/src/tests.rs
index 1dbf229970..192e9007d6 100644
--- a/crates/ra_mbe/src/tests.rs
+++ b/crates/ra_mbe/src/tests.rs
@@ -419,9 +419,9 @@ MACRO_ITEMS@[0; 40)
     STRUCT_KW@[0; 6) "struct"
     NAME@[6; 9)
       IDENT@[6; 9) "Foo"
-    RECORD_FIELD_DEF_LIST@[9; 20)
+    NAMED_FIELD_DEF_LIST@[9; 20)
       L_CURLY@[9; 10) "{"
-      RECORD_FIELD_DEF@[10; 19)
+      NAMED_FIELD_DEF@[10; 19)
         NAME@[10; 15)
           IDENT@[10; 15) "field"
         COLON@[15; 16) ":"
@@ -435,9 +435,9 @@ MACRO_ITEMS@[0; 40)
     STRUCT_KW@[20; 26) "struct"
     NAME@[26; 29)
       IDENT@[26; 29) "Bar"
-    RECORD_FIELD_DEF_LIST@[29; 40)
+    NAMED_FIELD_DEF_LIST@[29; 40)
       L_CURLY@[29; 30) "{"
-      RECORD_FIELD_DEF@[30; 39)
+      NAMED_FIELD_DEF@[30; 39)
         NAME@[30; 35)
           IDENT@[30; 35) "field"
         COLON@[35; 36) ":"
diff --git a/crates/ra_syntax/test_data/parser/err/0000_struct_field_missing_comma.txt b/crates/ra_syntax/test_data/parser/err/0000_struct_field_missing_comma.txt
index dc143945ad..0dbbfe8534 100644
--- a/crates/ra_syntax/test_data/parser/err/0000_struct_field_missing_comma.txt
+++ b/crates/ra_syntax/test_data/parser/err/0000_struct_field_missing_comma.txt
@@ -5,10 +5,10 @@ SOURCE_FILE@[0; 34)
     NAME@[7; 8)
       IDENT@[7; 8) "S"
     WHITESPACE@[8; 9) " "
-    RECORD_FIELD_DEF_LIST@[9; 34)
+    NAMED_FIELD_DEF_LIST@[9; 34)
       L_CURLY@[9; 10) "{"
       WHITESPACE@[10; 15) "\n    "
-      RECORD_FIELD_DEF@[15; 21)
+      NAMED_FIELD_DEF@[15; 21)
         NAME@[15; 16)
           IDENT@[15; 16) "a"
         COLON@[16; 17) ":"
@@ -19,7 +19,7 @@ SOURCE_FILE@[0; 34)
               NAME_REF@[18; 21)
                 IDENT@[18; 21) "u32"
       WHITESPACE@[21; 26) "\n    "
-      RECORD_FIELD_DEF@[26; 32)
+      NAMED_FIELD_DEF@[26; 32)
         NAME@[26; 27)
           IDENT@[26; 27) "b"
         COLON@[27; 28) ":"
diff --git a/crates/ra_syntax/test_data/parser/err/0001_item_recovery_in_file.txt b/crates/ra_syntax/test_data/parser/err/0001_item_recovery_in_file.txt
index 181bcdb9ec..7cfb54ef87 100644
--- a/crates/ra_syntax/test_data/parser/err/0001_item_recovery_in_file.txt
+++ b/crates/ra_syntax/test_data/parser/err/0001_item_recovery_in_file.txt
@@ -11,7 +11,7 @@ SOURCE_FILE@[0; 21)
     NAME@[17; 18)
       IDENT@[17; 18) "S"
     WHITESPACE@[18; 19) " "
-    RECORD_FIELD_DEF_LIST@[19; 21)
+    NAMED_FIELD_DEF_LIST@[19; 21)
       L_CURLY@[19; 20) "{"
       R_CURLY@[20; 21) "}"
 error 0: expected an item
diff --git a/crates/ra_syntax/test_data/parser/err/0003_C++_semicolon.txt b/crates/ra_syntax/test_data/parser/err/0003_C++_semicolon.txt
index 58d005902b..8578260378 100644
--- a/crates/ra_syntax/test_data/parser/err/0003_C++_semicolon.txt
+++ b/crates/ra_syntax/test_data/parser/err/0003_C++_semicolon.txt
@@ -5,10 +5,10 @@ SOURCE_FILE@[0; 40)
     NAME@[7; 8)
       IDENT@[7; 8) "S"
     WHITESPACE@[8; 9) " "
-    RECORD_FIELD_DEF_LIST@[9; 39)
+    NAMED_FIELD_DEF_LIST@[9; 39)
       L_CURLY@[9; 10) "{"
       WHITESPACE@[10; 15) "\n    "
-      RECORD_FIELD_DEF@[15; 21)
+      NAMED_FIELD_DEF@[15; 21)
         NAME@[15; 16)
           IDENT@[15; 16) "a"
         COLON@[16; 17) ":"
@@ -20,7 +20,7 @@ SOURCE_FILE@[0; 40)
                 IDENT@[18; 21) "i32"
       COMMA@[21; 22) ","
       WHITESPACE@[22; 27) "\n    "
-      RECORD_FIELD_DEF@[27; 36)
+      NAMED_FIELD_DEF@[27; 36)
         NAME@[27; 28)
           IDENT@[27; 28) "b"
         COLON@[28; 29) ":"
diff --git a/crates/ra_syntax/test_data/parser/err/0006_named_field_recovery.txt b/crates/ra_syntax/test_data/parser/err/0006_named_field_recovery.txt
index 5f5198b31e..6143e68f13 100644
--- a/crates/ra_syntax/test_data/parser/err/0006_named_field_recovery.txt
+++ b/crates/ra_syntax/test_data/parser/err/0006_named_field_recovery.txt
@@ -5,10 +5,10 @@ SOURCE_FILE@[0; 74)
     NAME@[7; 8)
       IDENT@[7; 8) "S"
     WHITESPACE@[8; 9) " "
-    RECORD_FIELD_DEF_LIST@[9; 73)
+    NAMED_FIELD_DEF_LIST@[9; 73)
       L_CURLY@[9; 10) "{"
       WHITESPACE@[10; 15) "\n    "
-      RECORD_FIELD_DEF@[15; 21)
+      NAMED_FIELD_DEF@[15; 21)
         NAME@[15; 16)
           IDENT@[15; 16) "f"
         COLON@[16; 17) ":"
@@ -35,7 +35,7 @@ SOURCE_FILE@[0; 74)
       ERROR@[42; 43)
         STAR@[42; 43) "*"
       WHITESPACE@[43; 48) "\n    "
-      RECORD_FIELD_DEF@[48; 58)
+      NAMED_FIELD_DEF@[48; 58)
         VISIBILITY@[48; 51)
           PUB_KW@[48; 51) "pub"
         WHITESPACE@[51; 52) " "
@@ -50,7 +50,7 @@ SOURCE_FILE@[0; 74)
                 IDENT@[55; 58) "u32"
       COMMA@[58; 59) ","
       WHITESPACE@[59; 64) "\n    "
-      RECORD_FIELD_DEF@[64; 70)
+      NAMED_FIELD_DEF@[64; 70)
         NAME@[64; 65)
           IDENT@[64; 65) "z"
         COLON@[65; 66) ":"
diff --git a/crates/ra_syntax/test_data/parser/err/0013_invalid_type.txt b/crates/ra_syntax/test_data/parser/err/0013_invalid_type.txt
index 4907bac6da..bef286b372 100644
--- a/crates/ra_syntax/test_data/parser/err/0013_invalid_type.txt
+++ b/crates/ra_syntax/test_data/parser/err/0013_invalid_type.txt
@@ -7,10 +7,10 @@ SOURCE_FILE@[0; 86)
     WHITESPACE@[10; 11) " "
     NAME@[11; 16)
       IDENT@[11; 16) "Cache"
-    TUPLE_FIELD_DEF_LIST@[16; 72)
+    POS_FIELD_DEF_LIST@[16; 72)
       L_PAREN@[16; 17) "("
       WHITESPACE@[17; 22) "\n    "
-      TUPLE_FIELD_DEF@[22; 68)
+      POS_FIELD_DEF@[22; 68)
         PATH_TYPE@[22; 68)
           PATH@[22; 68)
             PATH_SEGMENT@[22; 68)
@@ -47,7 +47,7 @@ SOURCE_FILE@[0; 86)
                                       ERROR@[67; 68)
                                         AT@[67; 68) "@"
       WHITESPACE@[68; 69) " "
-      TUPLE_FIELD_DEF@[69; 72)
+      POS_FIELD_DEF@[69; 72)
         PATH_TYPE@[69; 72)
           PATH@[69; 72)
             PATH_SEGMENT@[69; 72)
diff --git a/crates/ra_syntax/test_data/parser/err/0018_incomplete_fn.txt b/crates/ra_syntax/test_data/parser/err/0018_incomplete_fn.txt
index 52eb7d5e22..51def2d8fc 100644
--- a/crates/ra_syntax/test_data/parser/err/0018_incomplete_fn.txt
+++ b/crates/ra_syntax/test_data/parser/err/0018_incomplete_fn.txt
@@ -75,16 +75,16 @@ SOURCE_FILE@[0; 183)
               IDENT@[106; 110) "push"
             ARG_LIST@[110; 155)
               L_PAREN@[110; 111) "("
-              RECORD_LIT@[111; 154)
+              STRUCT_LIT@[111; 154)
                 PATH@[111; 120)
                   PATH_SEGMENT@[111; 120)
                     NAME_REF@[111; 120)
                       IDENT@[111; 120) "ScopeData"
                 WHITESPACE@[120; 121) " "
-                RECORD_FIELD_LIST@[121; 154)
+                NAMED_FIELD_LIST@[121; 154)
                   L_CURLY@[121; 122) "{"
                   WHITESPACE@[122; 123) " "
-                  RECORD_FIELD@[123; 135)
+                  NAMED_FIELD@[123; 135)
                     NAME_REF@[123; 129)
                       IDENT@[123; 129) "parent"
                     COLON@[129; 130) ":"
@@ -96,7 +96,7 @@ SOURCE_FILE@[0; 183)
                             IDENT@[131; 135) "None"
                   COMMA@[135; 136) ","
                   WHITESPACE@[136; 137) " "
-                  RECORD_FIELD@[137; 152)
+                  NAMED_FIELD@[137; 152)
                     NAME_REF@[137; 144)
                       IDENT@[137; 144) "entries"
                     COLON@[144; 145) ":"
diff --git a/crates/ra_syntax/test_data/parser/err/0025_nope.txt b/crates/ra_syntax/test_data/parser/err/0025_nope.txt
index 7b228a8ed9..0a3952dc96 100644
--- a/crates/ra_syntax/test_data/parser/err/0025_nope.txt
+++ b/crates/ra_syntax/test_data/parser/err/0025_nope.txt
@@ -28,9 +28,9 @@ SOURCE_FILE@[0; 575)
           ENUM_VARIANT@[50; 62)
             NAME@[50; 54)
               IDENT@[50; 54) "Var2"
-            TUPLE_FIELD_DEF_LIST@[54; 62)
+            POS_FIELD_DEF_LIST@[54; 62)
               L_PAREN@[54; 55) "("
-              TUPLE_FIELD_DEF@[55; 61)
+              POS_FIELD_DEF@[55; 61)
                 PATH_TYPE@[55; 61)
                   PATH@[55; 61)
                     PATH_SEGMENT@[55; 61)
@@ -43,10 +43,10 @@ SOURCE_FILE@[0; 575)
             NAME@[72; 76)
               IDENT@[72; 76) "Var3"
             WHITESPACE@[76; 77) " "
-            RECORD_FIELD_DEF_LIST@[77; 145)
+            NAMED_FIELD_DEF_LIST@[77; 145)
               L_CURLY@[77; 78) "{"
               WHITESPACE@[78; 91) "\n            "
-              RECORD_FIELD_DEF@[91; 95)
+              NAMED_FIELD_DEF@[91; 95)
                 NAME@[91; 94)
                   IDENT@[91; 94) "abc"
                 COLON@[94; 95) ":"
@@ -108,10 +108,10 @@ SOURCE_FILE@[0; 575)
             NAME@[250; 259)
               IDENT@[250; 259) "StillFine"
             WHITESPACE@[259; 260) " "
-            RECORD_FIELD_DEF_LIST@[260; 293)
+            NAMED_FIELD_DEF_LIST@[260; 293)
               L_CURLY@[260; 261) "{"
               WHITESPACE@[261; 274) "\n            "
-              RECORD_FIELD_DEF@[274; 282)
+              NAMED_FIELD_DEF@[274; 282)
                 NAME@[274; 277)
                   IDENT@[274; 277) "def"
                 COLON@[277; 278) ":"
@@ -147,9 +147,9 @@ SOURCE_FILE@[0; 575)
                 ENUM_VARIANT@[363; 372)
                   NAME@[363; 367)
                     IDENT@[363; 367) "Nope"
-                  TUPLE_FIELD_DEF_LIST@[367; 372)
+                  POS_FIELD_DEF_LIST@[367; 372)
                     L_PAREN@[367; 368) "("
-                    TUPLE_FIELD_DEF@[368; 371)
+                    POS_FIELD_DEF@[368; 371)
                       PATH_TYPE@[368; 371)
                         PATH@[368; 371)
                           PATH_SEGMENT@[368; 371)
diff --git a/crates/ra_syntax/test_data/parser/err/0034_bad_box_pattern.rs b/crates/ra_syntax/test_data/parser/err/0034_bad_box_pattern.rs
deleted file mode 100644
index d3fa2e468c..0000000000
--- a/crates/ra_syntax/test_data/parser/err/0034_bad_box_pattern.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-fn main() {
-    let ref box i = ();
-    let mut box i = ();
-    let ref mut box i = ();
-}
-
diff --git a/crates/ra_syntax/test_data/parser/err/0034_bad_box_pattern.txt b/crates/ra_syntax/test_data/parser/err/0034_bad_box_pattern.txt
deleted file mode 100644
index 0cdca4b555..0000000000
--- a/crates/ra_syntax/test_data/parser/err/0034_bad_box_pattern.txt
+++ /dev/null
@@ -1,95 +0,0 @@
-SOURCE_FILE@[0; 91)
-  FN_DEF@[0; 89)
-    FN_KW@[0; 2) "fn"
-    WHITESPACE@[2; 3) " "
-    NAME@[3; 7)
-      IDENT@[3; 7) "main"
-    PARAM_LIST@[7; 9)
-      L_PAREN@[7; 8) "("
-      R_PAREN@[8; 9) ")"
-    WHITESPACE@[9; 10) " "
-    BLOCK@[10; 89)
-      L_CURLY@[10; 11) "{"
-      WHITESPACE@[11; 16) "\n    "
-      LET_STMT@[16; 27)
-        LET_KW@[16; 19) "let"
-        WHITESPACE@[19; 20) " "
-        BIND_PAT@[20; 27)
-          REF_KW@[20; 23) "ref"
-          WHITESPACE@[23; 24) " "
-          ERROR@[24; 27)
-            BOX_KW@[24; 27) "box"
-      WHITESPACE@[27; 28) " "
-      EXPR_STMT@[28; 35)
-        BIN_EXPR@[28; 34)
-          PATH_EXPR@[28; 29)
-            PATH@[28; 29)
-              PATH_SEGMENT@[28; 29)
-                NAME_REF@[28; 29)
-                  IDENT@[28; 29) "i"
-          WHITESPACE@[29; 30) " "
-          EQ@[30; 31) "="
-          WHITESPACE@[31; 32) " "
-          TUPLE_EXPR@[32; 34)
-            L_PAREN@[32; 33) "("
-            R_PAREN@[33; 34) ")"
-        SEMI@[34; 35) ";"
-      WHITESPACE@[35; 40) "\n    "
-      LET_STMT@[40; 51)
-        LET_KW@[40; 43) "let"
-        WHITESPACE@[43; 44) " "
-        BIND_PAT@[44; 51)
-          MUT_KW@[44; 47) "mut"
-          WHITESPACE@[47; 48) " "
-          ERROR@[48; 51)
-            BOX_KW@[48; 51) "box"
-      WHITESPACE@[51; 52) " "
-      EXPR_STMT@[52; 59)
-        BIN_EXPR@[52; 58)
-          PATH_EXPR@[52; 53)
-            PATH@[52; 53)
-              PATH_SEGMENT@[52; 53)
-                NAME_REF@[52; 53)
-                  IDENT@[52; 53) "i"
-          WHITESPACE@[53; 54) " "
-          EQ@[54; 55) "="
-          WHITESPACE@[55; 56) " "
-          TUPLE_EXPR@[56; 58)
-            L_PAREN@[56; 57) "("
-            R_PAREN@[57; 58) ")"
-        SEMI@[58; 59) ";"
-      WHITESPACE@[59; 64) "\n    "
-      LET_STMT@[64; 79)
-        LET_KW@[64; 67) "let"
-        WHITESPACE@[67; 68) " "
-        BIND_PAT@[68; 79)
-          REF_KW@[68; 71) "ref"
-          WHITESPACE@[71; 72) " "
-          MUT_KW@[72; 75) "mut"
-          WHITESPACE@[75; 76) " "
-          ERROR@[76; 79)
-            BOX_KW@[76; 79) "box"
-      WHITESPACE@[79; 80) " "
-      EXPR_STMT@[80; 87)
-        BIN_EXPR@[80; 86)
-          PATH_EXPR@[80; 81)
-            PATH@[80; 81)
-              PATH_SEGMENT@[80; 81)
-                NAME_REF@[80; 81)
-                  IDENT@[80; 81) "i"
-          WHITESPACE@[81; 82) " "
-          EQ@[82; 83) "="
-          WHITESPACE@[83; 84) " "
-          TUPLE_EXPR@[84; 86)
-            L_PAREN@[84; 85) "("
-            R_PAREN@[85; 86) ")"
-        SEMI@[86; 87) ";"
-      WHITESPACE@[87; 88) "\n"
-      R_CURLY@[88; 89) "}"
-  WHITESPACE@[89; 91) "\n\n"
-error 24: expected a name
-error 27: expected SEMI
-error 48: expected a name
-error 51: expected SEMI
-error 76: expected a name
-error 79: expected SEMI
diff --git a/crates/ra_syntax/test_data/parser/fuzz-failures/0000.rs b/crates/ra_syntax/test_data/parser/fuzz-failures/0000.rs
index 0e6e0ccc3f..e0437d1632 100644
--- a/crates/ra_syntax/test_data/parser/fuzz-failures/0000.rs
+++ b/crates/ra_syntax/test_data/parser/fuzz-failures/0000.rs
@@ -86,7 +86,7 @@ fn find_reparsable_node(node: SyntaxNodeRef, range: TextRange) -> Option<(Syntax
     fn reparser(node: SyntaxNodeRef) -> Option<fn(&mut Parser)> {
         let res = match node.kind() {
             BLOCK => grammar::block,
-            RECORD_FIELD_DEF_LIST => grammar::record_field_def_list,
+            NAMED_FIELD_DEF_LIST => grammar::named_field_def_list,
             _ => return None,
         };
         Some(res)
@@ -138,7 +138,7 @@ fn find_reparsable_node(node: SyntaxNodeRef, range: TextRange) -> Option<(Syntax
         let res = match node.kind() {
      ;
     let end = u32::from(range.end()) as usize;
-    text.replaT => grammar::record_field_def_list,
+    text.replaT => grammar::named_field_def_list,
             _ => return None,
         };
         Some(res)
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0008_path_part.txt b/crates/ra_syntax/test_data/parser/inline/ok/0008_path_part.txt
index 4108762e52..0c6be485ef 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0008_path_part.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0008_path_part.txt
@@ -52,13 +52,13 @@ SOURCE_FILE@[0; 103)
       LET_STMT@[58; 78)
         LET_KW@[58; 61) "let"
         WHITESPACE@[61; 62) " "
-        RECORD_PAT@[62; 72)
+        STRUCT_PAT@[62; 72)
           PATH@[62; 65)
             PATH_SEGMENT@[62; 65)
               NAME_REF@[62; 65)
                 IDENT@[62; 65) "Bar"
           WHITESPACE@[65; 66) " "
-          RECORD_FIELD_PAT_LIST@[66; 72)
+          FIELD_PAT_LIST@[66; 72)
             L_CURLY@[66; 67) "{"
             WHITESPACE@[67; 68) " "
             DOTDOT@[68; 70) ".."
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0040_crate_keyword_vis.txt b/crates/ra_syntax/test_data/parser/inline/ok/0040_crate_keyword_vis.txt
index 882e4a9aec..fb8246174a 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0040_crate_keyword_vis.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0040_crate_keyword_vis.txt
@@ -22,10 +22,10 @@ SOURCE_FILE@[0; 71)
     NAME@[27; 28)
       IDENT@[27; 28) "S"
     WHITESPACE@[28; 29) " "
-    RECORD_FIELD_DEF_LIST@[29; 49)
+    NAMED_FIELD_DEF_LIST@[29; 49)
       L_CURLY@[29; 30) "{"
       WHITESPACE@[30; 31) " "
-      RECORD_FIELD_DEF@[31; 47)
+      NAMED_FIELD_DEF@[31; 47)
         VISIBILITY@[31; 36)
           CRATE_KW@[31; 36) "crate"
         WHITESPACE@[36; 37) " "
@@ -46,9 +46,9 @@ SOURCE_FILE@[0; 71)
     WHITESPACE@[56; 57) " "
     NAME@[57; 58)
       IDENT@[57; 58) "T"
-    TUPLE_FIELD_DEF_LIST@[58; 69)
+    POS_FIELD_DEF_LIST@[58; 69)
       L_PAREN@[58; 59) "("
-      TUPLE_FIELD_DEF@[59; 68)
+      POS_FIELD_DEF@[59; 68)
         VISIBILITY@[59; 64)
           CRATE_KW@[59; 64) "crate"
         WHITESPACE@[64; 65) " "
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0054_record_field_attrs.rs b/crates/ra_syntax/test_data/parser/inline/ok/0054_field_attrs.rs
similarity index 100%
rename from crates/ra_syntax/test_data/parser/inline/ok/0054_record_field_attrs.rs
rename to crates/ra_syntax/test_data/parser/inline/ok/0054_field_attrs.rs
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0054_record_field_attrs.txt b/crates/ra_syntax/test_data/parser/inline/ok/0054_field_attrs.txt
similarity index 94%
rename from crates/ra_syntax/test_data/parser/inline/ok/0054_record_field_attrs.txt
rename to crates/ra_syntax/test_data/parser/inline/ok/0054_field_attrs.txt
index 56aeba7681..f214d1d47b 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0054_record_field_attrs.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0054_field_attrs.txt
@@ -5,10 +5,10 @@ SOURCE_FILE@[0; 64)
     NAME@[7; 8)
       IDENT@[7; 8) "S"
     WHITESPACE@[8; 9) " "
-    RECORD_FIELD_DEF_LIST@[9; 63)
+    NAMED_FIELD_DEF_LIST@[9; 63)
       L_CURLY@[9; 10) "{"
       WHITESPACE@[10; 15) "\n    "
-      RECORD_FIELD_DEF@[15; 60)
+      NAMED_FIELD_DEF@[15; 60)
         ATTR@[15; 43)
           POUND@[15; 16) "#"
           TOKEN_TREE@[16; 43)
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0061_record_lit.rs b/crates/ra_syntax/test_data/parser/inline/ok/0061_struct_lit.rs
similarity index 100%
rename from crates/ra_syntax/test_data/parser/inline/ok/0061_record_lit.rs
rename to crates/ra_syntax/test_data/parser/inline/ok/0061_struct_lit.rs
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0061_record_lit.txt b/crates/ra_syntax/test_data/parser/inline/ok/0061_struct_lit.txt
similarity index 88%
rename from crates/ra_syntax/test_data/parser/inline/ok/0061_record_lit.txt
rename to crates/ra_syntax/test_data/parser/inline/ok/0061_struct_lit.txt
index 1c915ea0c1..d06594cae2 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0061_record_lit.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0061_struct_lit.txt
@@ -12,33 +12,33 @@ SOURCE_FILE@[0; 112)
       L_CURLY@[9; 10) "{"
       WHITESPACE@[10; 15) "\n    "
       EXPR_STMT@[15; 20)
-        RECORD_LIT@[15; 19)
+        STRUCT_LIT@[15; 19)
           PATH@[15; 16)
             PATH_SEGMENT@[15; 16)
               NAME_REF@[15; 16)
                 IDENT@[15; 16) "S"
           WHITESPACE@[16; 17) " "
-          RECORD_FIELD_LIST@[17; 19)
+          NAMED_FIELD_LIST@[17; 19)
             L_CURLY@[17; 18) "{"
             R_CURLY@[18; 19) "}"
         SEMI@[19; 20) ";"
       WHITESPACE@[20; 25) "\n    "
       EXPR_STMT@[25; 41)
-        RECORD_LIT@[25; 40)
+        STRUCT_LIT@[25; 40)
           PATH@[25; 26)
             PATH_SEGMENT@[25; 26)
               NAME_REF@[25; 26)
                 IDENT@[25; 26) "S"
           WHITESPACE@[26; 27) " "
-          RECORD_FIELD_LIST@[27; 40)
+          NAMED_FIELD_LIST@[27; 40)
             L_CURLY@[27; 28) "{"
             WHITESPACE@[28; 29) " "
-            RECORD_FIELD@[29; 30)
+            NAMED_FIELD@[29; 30)
               NAME_REF@[29; 30)
                 IDENT@[29; 30) "x"
             COMMA@[30; 31) ","
             WHITESPACE@[31; 32) " "
-            RECORD_FIELD@[32; 37)
+            NAMED_FIELD@[32; 37)
               NAME_REF@[32; 33)
                 IDENT@[32; 33) "y"
               COLON@[33; 34) ":"
@@ -51,21 +51,21 @@ SOURCE_FILE@[0; 112)
         SEMI@[40; 41) ";"
       WHITESPACE@[41; 46) "\n    "
       EXPR_STMT@[46; 83)
-        RECORD_LIT@[46; 82)
+        STRUCT_LIT@[46; 82)
           PATH@[46; 47)
             PATH_SEGMENT@[46; 47)
               NAME_REF@[46; 47)
                 IDENT@[46; 47) "S"
           WHITESPACE@[47; 48) " "
-          RECORD_FIELD_LIST@[48; 82)
+          NAMED_FIELD_LIST@[48; 82)
             L_CURLY@[48; 49) "{"
             WHITESPACE@[49; 50) " "
-            RECORD_FIELD@[50; 51)
+            NAMED_FIELD@[50; 51)
               NAME_REF@[50; 51)
                 IDENT@[50; 51) "x"
             COMMA@[51; 52) ","
             WHITESPACE@[52; 53) " "
-            RECORD_FIELD@[53; 58)
+            NAMED_FIELD@[53; 58)
               NAME_REF@[53; 54)
                 IDENT@[53; 54) "y"
               COLON@[54; 55) ":"
@@ -94,16 +94,16 @@ SOURCE_FILE@[0; 112)
         SEMI@[82; 83) ";"
       WHITESPACE@[83; 88) "\n    "
       EXPR_STMT@[88; 109)
-        RECORD_LIT@[88; 108)
+        STRUCT_LIT@[88; 108)
           PATH@[88; 99)
             PATH_SEGMENT@[88; 99)
               NAME_REF@[88; 99)
                 IDENT@[88; 99) "TupleStruct"
           WHITESPACE@[99; 100) " "
-          RECORD_FIELD_LIST@[100; 108)
+          NAMED_FIELD_LIST@[100; 108)
             L_CURLY@[100; 101) "{"
             WHITESPACE@[101; 102) " "
-            RECORD_FIELD@[102; 106)
+            NAMED_FIELD@[102; 106)
               NAME_REF@[102; 103)
                 INT_NUMBER@[102; 103) "0"
               COLON@[103; 104) ":"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.rs b/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.rs
index 9e009e24f4..2d476278d1 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.rs
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.rs
@@ -5,5 +5,7 @@ fn foo() {
         X | Y if Z => (),
         | X | Y if Z => (),
         | X => (),
+        box X => (),
+        Some(box X) => (),
     };
 }
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.txt b/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.txt
index c2f256ac39..28d501459d 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.txt
@@ -1,5 +1,5 @@
-SOURCE_FILE@[0; 167)
-  FN_DEF@[0; 166)
+SOURCE_FILE@[0; 215)
+  FN_DEF@[0; 214)
     FN_KW@[0; 2) "fn"
     WHITESPACE@[2; 3) " "
     NAME@[3; 6)
@@ -8,18 +8,18 @@ SOURCE_FILE@[0; 167)
       L_PAREN@[6; 7) "("
       R_PAREN@[7; 8) ")"
     WHITESPACE@[8; 9) " "
-    BLOCK@[9; 166)
+    BLOCK@[9; 214)
       L_CURLY@[9; 10) "{"
       WHITESPACE@[10; 15) "\n    "
-      EXPR_STMT@[15; 164)
-        MATCH_EXPR@[15; 163)
+      EXPR_STMT@[15; 212)
+        MATCH_EXPR@[15; 211)
           MATCH_KW@[15; 20) "match"
           WHITESPACE@[20; 21) " "
           TUPLE_EXPR@[21; 23)
             L_PAREN@[21; 22) "("
             R_PAREN@[22; 23) ")"
           WHITESPACE@[23; 24) " "
-          MATCH_ARM_LIST@[24; 163)
+          MATCH_ARM_LIST@[24; 211)
             L_CURLY@[24; 25) "{"
             WHITESPACE@[25; 34) "\n        "
             MATCH_ARM@[34; 41)
@@ -49,14 +49,14 @@ SOURCE_FILE@[0; 167)
                   WHITESPACE@[60; 61) " "
                   R_ANGLE@[61; 62) ">"
                   WHITESPACE@[62; 63) " "
-                  RECORD_LIT@[63; 77)
+                  STRUCT_LIT@[63; 77)
                     PATH@[63; 67)
                       PATH_SEGMENT@[63; 67)
                         NAME_REF@[63; 67)
                           IDENT@[63; 67) "Test"
-                    RECORD_FIELD_LIST@[67; 77)
+                    NAMED_FIELD_LIST@[67; 77)
                       L_CURLY@[67; 68) "{"
-                      RECORD_FIELD@[68; 76)
+                      NAMED_FIELD@[68; 76)
                         NAME_REF@[68; 73)
                           IDENT@[68; 73) "field"
                         COLON@[73; 74) ":"
@@ -141,9 +141,44 @@ SOURCE_FILE@[0; 167)
                 L_PAREN@[154; 155) "("
                 R_PAREN@[155; 156) ")"
             COMMA@[156; 157) ","
-            WHITESPACE@[157; 162) "\n    "
-            R_CURLY@[162; 163) "}"
-        SEMI@[163; 164) ";"
-      WHITESPACE@[164; 165) "\n"
-      R_CURLY@[165; 166) "}"
-  WHITESPACE@[166; 167) "\n"
+            WHITESPACE@[157; 166) "\n        "
+            MATCH_ARM@[166; 177)
+              BIND_PAT@[166; 171)
+                BOX_KW@[166; 169) "box"
+                WHITESPACE@[169; 170) " "
+                NAME@[170; 171)
+                  IDENT@[170; 171) "X"
+              WHITESPACE@[171; 172) " "
+              FAT_ARROW@[172; 174) "=>"
+              WHITESPACE@[174; 175) " "
+              TUPLE_EXPR@[175; 177)
+                L_PAREN@[175; 176) "("
+                R_PAREN@[176; 177) ")"
+            COMMA@[177; 178) ","
+            WHITESPACE@[178; 187) "\n        "
+            MATCH_ARM@[187; 204)
+              TUPLE_STRUCT_PAT@[187; 198)
+                PATH@[187; 191)
+                  PATH_SEGMENT@[187; 191)
+                    NAME_REF@[187; 191)
+                      IDENT@[187; 191) "Some"
+                L_PAREN@[191; 192) "("
+                BIND_PAT@[192; 197)
+                  BOX_KW@[192; 195) "box"
+                  WHITESPACE@[195; 196) " "
+                  NAME@[196; 197)
+                    IDENT@[196; 197) "X"
+                R_PAREN@[197; 198) ")"
+              WHITESPACE@[198; 199) " "
+              FAT_ARROW@[199; 201) "=>"
+              WHITESPACE@[201; 202) " "
+              TUPLE_EXPR@[202; 204)
+                L_PAREN@[202; 203) "("
+                R_PAREN@[203; 204) ")"
+            COMMA@[204; 205) ","
+            WHITESPACE@[205; 210) "\n    "
+            R_CURLY@[210; 211) "}"
+        SEMI@[211; 212) ";"
+      WHITESPACE@[212; 213) "\n"
+      R_CURLY@[213; 214) "}"
+  WHITESPACE@[214; 215) "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0068_union_items.txt b/crates/ra_syntax/test_data/parser/inline/ok/0068_union_items.txt
index f9ace02ee0..4b653317b8 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0068_union_items.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0068_union_items.txt
@@ -5,7 +5,7 @@ SOURCE_FILE@[0; 51)
     NAME@[6; 9)
       IDENT@[6; 9) "Foo"
     WHITESPACE@[9; 10) " "
-    RECORD_FIELD_DEF_LIST@[10; 12)
+    NAMED_FIELD_DEF_LIST@[10; 12)
       L_CURLY@[10; 11) "{"
       R_CURLY@[11; 12) "}"
   WHITESPACE@[12; 13) "\n"
@@ -15,10 +15,10 @@ SOURCE_FILE@[0; 51)
     NAME@[19; 22)
       IDENT@[19; 22) "Foo"
     WHITESPACE@[22; 23) " "
-    RECORD_FIELD_DEF_LIST@[23; 50)
+    NAMED_FIELD_DEF_LIST@[23; 50)
       L_CURLY@[23; 24) "{"
       WHITESPACE@[24; 29) "\n    "
-      RECORD_FIELD_DEF@[29; 35)
+      NAMED_FIELD_DEF@[29; 35)
         NAME@[29; 30)
           IDENT@[29; 30) "a"
         COLON@[30; 31) ":"
@@ -30,7 +30,7 @@ SOURCE_FILE@[0; 51)
                 IDENT@[32; 35) "i32"
       COMMA@[35; 36) ","
       WHITESPACE@[36; 41) "\n    "
-      RECORD_FIELD_DEF@[41; 47)
+      NAMED_FIELD_DEF@[41; 47)
         NAME@[41; 42)
           IDENT@[41; 42) "b"
         COLON@[42; 43) ":"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0083_struct_items.txt b/crates/ra_syntax/test_data/parser/inline/ok/0083_struct_items.txt
index e909f2b785..62d93512b2 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0083_struct_items.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0083_struct_items.txt
@@ -12,7 +12,7 @@ SOURCE_FILE@[0; 106)
     NAME@[19; 22)
       IDENT@[19; 22) "Foo"
     WHITESPACE@[22; 23) " "
-    RECORD_FIELD_DEF_LIST@[23; 25)
+    NAMED_FIELD_DEF_LIST@[23; 25)
       L_CURLY@[23; 24) "{"
       R_CURLY@[24; 25) "}"
   WHITESPACE@[25; 26) "\n"
@@ -21,7 +21,7 @@ SOURCE_FILE@[0; 106)
     WHITESPACE@[32; 33) " "
     NAME@[33; 36)
       IDENT@[33; 36) "Foo"
-    TUPLE_FIELD_DEF_LIST@[36; 38)
+    POS_FIELD_DEF_LIST@[36; 38)
       L_PAREN@[36; 37) "("
       R_PAREN@[37; 38) ")"
     SEMI@[38; 39) ";"
@@ -31,9 +31,9 @@ SOURCE_FILE@[0; 106)
     WHITESPACE@[46; 47) " "
     NAME@[47; 50)
       IDENT@[47; 50) "Foo"
-    TUPLE_FIELD_DEF_LIST@[50; 65)
+    POS_FIELD_DEF_LIST@[50; 65)
       L_PAREN@[50; 51) "("
-      TUPLE_FIELD_DEF@[51; 57)
+      POS_FIELD_DEF@[51; 57)
         PATH_TYPE@[51; 57)
           PATH@[51; 57)
             PATH_SEGMENT@[51; 57)
@@ -41,7 +41,7 @@ SOURCE_FILE@[0; 106)
                 IDENT@[51; 57) "String"
       COMMA@[57; 58) ","
       WHITESPACE@[58; 59) " "
-      TUPLE_FIELD_DEF@[59; 64)
+      POS_FIELD_DEF@[59; 64)
         PATH_TYPE@[59; 64)
           PATH@[59; 64)
             PATH_SEGMENT@[59; 64)
@@ -56,10 +56,10 @@ SOURCE_FILE@[0; 106)
     NAME@[74; 77)
       IDENT@[74; 77) "Foo"
     WHITESPACE@[77; 78) " "
-    RECORD_FIELD_DEF_LIST@[78; 105)
+    NAMED_FIELD_DEF_LIST@[78; 105)
       L_CURLY@[78; 79) "{"
       WHITESPACE@[79; 84) "\n    "
-      RECORD_FIELD_DEF@[84; 90)
+      NAMED_FIELD_DEF@[84; 90)
         NAME@[84; 85)
           IDENT@[84; 85) "a"
         COLON@[85; 86) ":"
@@ -71,7 +71,7 @@ SOURCE_FILE@[0; 106)
                 IDENT@[87; 90) "i32"
       COMMA@[90; 91) ","
       WHITESPACE@[91; 96) "\n    "
-      RECORD_FIELD_DEF@[96; 102)
+      NAMED_FIELD_DEF@[96; 102)
         NAME@[96; 97)
           IDENT@[96; 97) "b"
         COLON@[97; 98) ":"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0102_record_field_pat_list.rs b/crates/ra_syntax/test_data/parser/inline/ok/0102_field_pat_list.rs
similarity index 100%
rename from crates/ra_syntax/test_data/parser/inline/ok/0102_record_field_pat_list.rs
rename to crates/ra_syntax/test_data/parser/inline/ok/0102_field_pat_list.rs
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0102_record_field_pat_list.txt b/crates/ra_syntax/test_data/parser/inline/ok/0102_field_pat_list.txt
similarity index 91%
rename from crates/ra_syntax/test_data/parser/inline/ok/0102_record_field_pat_list.txt
rename to crates/ra_syntax/test_data/parser/inline/ok/0102_field_pat_list.txt
index 22db72c129..a2af4fc601 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0102_record_field_pat_list.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0102_field_pat_list.txt
@@ -14,13 +14,13 @@ SOURCE_FILE@[0; 119)
       LET_STMT@[15; 29)
         LET_KW@[15; 18) "let"
         WHITESPACE@[18; 19) " "
-        RECORD_PAT@[19; 23)
+        STRUCT_PAT@[19; 23)
           PATH@[19; 20)
             PATH_SEGMENT@[19; 20)
               NAME_REF@[19; 20)
                 IDENT@[19; 20) "S"
           WHITESPACE@[20; 21) " "
-          RECORD_FIELD_PAT_LIST@[21; 23)
+          FIELD_PAT_LIST@[21; 23)
             L_CURLY@[21; 22) "{"
             R_CURLY@[22; 23) "}"
         WHITESPACE@[23; 24) " "
@@ -34,13 +34,13 @@ SOURCE_FILE@[0; 119)
       LET_STMT@[34; 62)
         LET_KW@[34; 37) "let"
         WHITESPACE@[37; 38) " "
-        RECORD_PAT@[38; 56)
+        STRUCT_PAT@[38; 56)
           PATH@[38; 39)
             PATH_SEGMENT@[38; 39)
               NAME_REF@[38; 39)
                 IDENT@[38; 39) "S"
           WHITESPACE@[39; 40) " "
-          RECORD_FIELD_PAT_LIST@[40; 56)
+          FIELD_PAT_LIST@[40; 56)
             L_CURLY@[40; 41) "{"
             WHITESPACE@[41; 42) " "
             BIND_PAT@[42; 43)
@@ -68,16 +68,16 @@ SOURCE_FILE@[0; 119)
       LET_STMT@[67; 90)
         LET_KW@[67; 70) "let"
         WHITESPACE@[70; 71) " "
-        RECORD_PAT@[71; 84)
+        STRUCT_PAT@[71; 84)
           PATH@[71; 72)
             PATH_SEGMENT@[71; 72)
               NAME_REF@[71; 72)
                 IDENT@[71; 72) "S"
           WHITESPACE@[72; 73) " "
-          RECORD_FIELD_PAT_LIST@[73; 84)
+          FIELD_PAT_LIST@[73; 84)
             L_CURLY@[73; 74) "{"
             WHITESPACE@[74; 75) " "
-            RECORD_FIELD_PAT@[75; 79)
+            FIELD_PAT@[75; 79)
               NAME@[75; 76)
                 IDENT@[75; 76) "h"
               COLON@[76; 77) ":"
@@ -99,16 +99,16 @@ SOURCE_FILE@[0; 119)
       LET_STMT@[95; 116)
         LET_KW@[95; 98) "let"
         WHITESPACE@[98; 99) " "
-        RECORD_PAT@[99; 110)
+        STRUCT_PAT@[99; 110)
           PATH@[99; 100)
             PATH_SEGMENT@[99; 100)
               NAME_REF@[99; 100)
                 IDENT@[99; 100) "S"
           WHITESPACE@[100; 101) " "
-          RECORD_FIELD_PAT_LIST@[101; 110)
+          FIELD_PAT_LIST@[101; 110)
             L_CURLY@[101; 102) "{"
             WHITESPACE@[102; 103) " "
-            RECORD_FIELD_PAT@[103; 107)
+            FIELD_PAT@[103; 107)
               NAME@[103; 104)
                 IDENT@[103; 104) "h"
               COLON@[104; 105) ":"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0112_bind_pat.rs b/crates/ra_syntax/test_data/parser/inline/ok/0112_bind_pat.rs
index 820a9e72ce..5a93469af5 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0112_bind_pat.rs
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0112_bind_pat.rs
@@ -5,4 +5,5 @@ fn main() {
     let ref mut d = ();
     let e @ _ = ();
     let ref mut f @ g @ _ = ();
+    let box i = Box::new(1i32);
 }
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0112_bind_pat.txt b/crates/ra_syntax/test_data/parser/inline/ok/0112_bind_pat.txt
index ab0f88507e..189254a19a 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0112_bind_pat.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0112_bind_pat.txt
@@ -1,5 +1,5 @@
-SOURCE_FILE@[0; 146)
-  FN_DEF@[0; 145)
+SOURCE_FILE@[0; 178)
+  FN_DEF@[0; 177)
     FN_KW@[0; 2) "fn"
     WHITESPACE@[2; 3) " "
     NAME@[3; 7)
@@ -8,7 +8,7 @@ SOURCE_FILE@[0; 146)
       L_PAREN@[7; 8) "("
       R_PAREN@[8; 9) ")"
     WHITESPACE@[9; 10) " "
-    BLOCK@[10; 145)
+    BLOCK@[10; 177)
       L_CURLY@[10; 11) "{"
       WHITESPACE@[11; 16) "\n    "
       LET_STMT@[16; 27)
@@ -122,6 +122,35 @@ SOURCE_FILE@[0; 146)
           L_PAREN@[140; 141) "("
           R_PAREN@[141; 142) ")"
         SEMI@[142; 143) ";"
-      WHITESPACE@[143; 144) "\n"
-      R_CURLY@[144; 145) "}"
-  WHITESPACE@[145; 146) "\n"
+      WHITESPACE@[143; 148) "\n    "
+      LET_STMT@[148; 175)
+        LET_KW@[148; 151) "let"
+        WHITESPACE@[151; 152) " "
+        BIND_PAT@[152; 157)
+          BOX_KW@[152; 155) "box"
+          WHITESPACE@[155; 156) " "
+          NAME@[156; 157)
+            IDENT@[156; 157) "i"
+        WHITESPACE@[157; 158) " "
+        EQ@[158; 159) "="
+        WHITESPACE@[159; 160) " "
+        CALL_EXPR@[160; 174)
+          PATH_EXPR@[160; 168)
+            PATH@[160; 168)
+              PATH@[160; 163)
+                PATH_SEGMENT@[160; 163)
+                  NAME_REF@[160; 163)
+                    IDENT@[160; 163) "Box"
+              COLONCOLON@[163; 165) "::"
+              PATH_SEGMENT@[165; 168)
+                NAME_REF@[165; 168)
+                  IDENT@[165; 168) "new"
+          ARG_LIST@[168; 174)
+            L_PAREN@[168; 169) "("
+            LITERAL@[169; 173)
+              INT_NUMBER@[169; 173) "1i32"
+            R_PAREN@[173; 174) ")"
+        SEMI@[174; 175) ";"
+      WHITESPACE@[175; 176) "\n"
+      R_CURLY@[176; 177) "}"
+  WHITESPACE@[177; 178) "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0114_tuple_struct_where.txt b/crates/ra_syntax/test_data/parser/inline/ok/0114_tuple_struct_where.txt
index f5de014058..8534592b9a 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0114_tuple_struct_where.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0114_tuple_struct_where.txt
@@ -10,9 +10,9 @@ SOURCE_FILE@[0; 53)
         NAME@[12; 13)
           IDENT@[12; 13) "T"
       R_ANGLE@[13; 14) ">"
-    TUPLE_FIELD_DEF_LIST@[14; 17)
+    POS_FIELD_DEF_LIST@[14; 17)
       L_PAREN@[14; 15) "("
-      TUPLE_FIELD_DEF@[15; 16)
+      POS_FIELD_DEF@[15; 16)
         PATH_TYPE@[15; 16)
           PATH@[15; 16)
             PATH_SEGMENT@[15; 16)
@@ -51,9 +51,9 @@ SOURCE_FILE@[0; 53)
         NAME@[46; 47)
           IDENT@[46; 47) "T"
       R_ANGLE@[47; 48) ">"
-    TUPLE_FIELD_DEF_LIST@[48; 51)
+    POS_FIELD_DEF_LIST@[48; 51)
       L_PAREN@[48; 49) "("
-      TUPLE_FIELD_DEF@[49; 50)
+      POS_FIELD_DEF@[49; 50)
         PATH_TYPE@[49; 50)
           PATH@[49; 50)
             PATH_SEGMENT@[49; 50)
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0115_tuple_field_attrs.rs b/crates/ra_syntax/test_data/parser/inline/ok/0115_pos_field_attrs.rs
similarity index 100%
rename from crates/ra_syntax/test_data/parser/inline/ok/0115_tuple_field_attrs.rs
rename to crates/ra_syntax/test_data/parser/inline/ok/0115_pos_field_attrs.rs
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0115_tuple_field_attrs.txt b/crates/ra_syntax/test_data/parser/inline/ok/0115_pos_field_attrs.txt
similarity index 94%
rename from crates/ra_syntax/test_data/parser/inline/ok/0115_tuple_field_attrs.txt
rename to crates/ra_syntax/test_data/parser/inline/ok/0115_pos_field_attrs.txt
index cb6d9f76d0..6dd3a9b93b 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0115_tuple_field_attrs.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0115_pos_field_attrs.txt
@@ -5,10 +5,10 @@ SOURCE_FILE@[0; 60)
     NAME@[7; 8)
       IDENT@[7; 8) "S"
     WHITESPACE@[8; 9) " "
-    TUPLE_FIELD_DEF_LIST@[9; 58)
+    POS_FIELD_DEF_LIST@[9; 58)
       L_PAREN@[9; 10) "("
       WHITESPACE@[10; 15) "\n    "
-      TUPLE_FIELD_DEF@[15; 55)
+      POS_FIELD_DEF@[15; 55)
         ATTR@[15; 43)
           POUND@[15; 16) "#"
           TOKEN_TREE@[16; 43)
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0125_record_literal_field_with_attr.rs b/crates/ra_syntax/test_data/parser/inline/ok/0125_struct_literal_field_with_attr.rs
similarity index 100%
rename from crates/ra_syntax/test_data/parser/inline/ok/0125_record_literal_field_with_attr.rs
rename to crates/ra_syntax/test_data/parser/inline/ok/0125_struct_literal_field_with_attr.rs
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0125_record_literal_field_with_attr.txt b/crates/ra_syntax/test_data/parser/inline/ok/0125_struct_literal_field_with_attr.txt
similarity index 93%
rename from crates/ra_syntax/test_data/parser/inline/ok/0125_record_literal_field_with_attr.txt
rename to crates/ra_syntax/test_data/parser/inline/ok/0125_struct_literal_field_with_attr.txt
index 8fdf3756f4..f9c5ec1246 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0125_record_literal_field_with_attr.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0125_struct_literal_field_with_attr.txt
@@ -11,16 +11,16 @@ SOURCE_FILE@[0; 46)
     BLOCK@[10; 45)
       L_CURLY@[10; 11) "{"
       WHITESPACE@[11; 16) "\n    "
-      RECORD_LIT@[16; 43)
+      STRUCT_LIT@[16; 43)
         PATH@[16; 17)
           PATH_SEGMENT@[16; 17)
             NAME_REF@[16; 17)
               IDENT@[16; 17) "S"
         WHITESPACE@[17; 18) " "
-        RECORD_FIELD_LIST@[18; 43)
+        NAMED_FIELD_LIST@[18; 43)
           L_CURLY@[18; 19) "{"
           WHITESPACE@[19; 20) " "
-          RECORD_FIELD@[20; 41)
+          NAMED_FIELD@[20; 41)
             ATTR@[20; 32)
               POUND@[20; 21) "#"
               TOKEN_TREE@[21; 32)
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0134_nocontentexpr_after_item.txt b/crates/ra_syntax/test_data/parser/inline/ok/0134_nocontentexpr_after_item.txt
index 64cbf4632a..50d3b5defe 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0134_nocontentexpr_after_item.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0134_nocontentexpr_after_item.txt
@@ -53,7 +53,7 @@ SOURCE_FILE@[0; 111)
         NAME@[103; 104)
           IDENT@[103; 104) "S"
         WHITESPACE@[104; 105) " "
-        RECORD_FIELD_DEF_LIST@[105; 107)
+        NAMED_FIELD_DEF_LIST@[105; 107)
           L_CURLY@[105; 106) "{"
           R_CURLY@[106; 107) "}"
       SEMI@[107; 108) ";"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0138_expression_after_block.txt b/crates/ra_syntax/test_data/parser/inline/ok/0138_expression_after_block.txt
index c4db9da40a..08128f3654 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0138_expression_after_block.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0138_expression_after_block.txt
@@ -22,14 +22,14 @@ SOURCE_FILE@[0; 52)
         WHITESPACE@[23; 24) " "
         EQ@[24; 25) "="
         WHITESPACE@[25; 26) " "
-        RECORD_LIT@[26; 33)
+        STRUCT_LIT@[26; 33)
           PATH@[26; 27)
             PATH_SEGMENT@[26; 27)
               NAME_REF@[26; 27)
                 IDENT@[26; 27) "F"
-          RECORD_FIELD_LIST@[27; 33)
+          NAMED_FIELD_LIST@[27; 33)
             L_CURLY@[27; 28) "{"
-            RECORD_FIELD@[28; 32)
+            NAMED_FIELD@[28; 32)
               NAME_REF@[28; 29)
                 IDENT@[28; 29) "x"
               COLON@[29; 30) ":"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0143_box_pat.rs b/crates/ra_syntax/test_data/parser/inline/ok/0143_box_pat.rs
deleted file mode 100644
index 9d458aa1e6..0000000000
--- a/crates/ra_syntax/test_data/parser/inline/ok/0143_box_pat.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-fn main() {
-    let box i = ();
-    let box Outer { box i, j: box Inner(box &x) } = ();
-    let box ref mut i = ();
-}
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0143_box_pat.txt b/crates/ra_syntax/test_data/parser/inline/ok/0143_box_pat.txt
deleted file mode 100644
index f0db58143c..0000000000
--- a/crates/ra_syntax/test_data/parser/inline/ok/0143_box_pat.txt
+++ /dev/null
@@ -1,109 +0,0 @@
-SOURCE_FILE@[0; 118)
-  FN_DEF@[0; 117)
-    FN_KW@[0; 2) "fn"
-    WHITESPACE@[2; 3) " "
-    NAME@[3; 7)
-      IDENT@[3; 7) "main"
-    PARAM_LIST@[7; 9)
-      L_PAREN@[7; 8) "("
-      R_PAREN@[8; 9) ")"
-    WHITESPACE@[9; 10) " "
-    BLOCK@[10; 117)
-      L_CURLY@[10; 11) "{"
-      WHITESPACE@[11; 16) "\n    "
-      LET_STMT@[16; 31)
-        LET_KW@[16; 19) "let"
-        WHITESPACE@[19; 20) " "
-        BOX_PAT@[20; 25)
-          BOX_KW@[20; 23) "box"
-          WHITESPACE@[23; 24) " "
-          BIND_PAT@[24; 25)
-            NAME@[24; 25)
-              IDENT@[24; 25) "i"
-        WHITESPACE@[25; 26) " "
-        EQ@[26; 27) "="
-        WHITESPACE@[27; 28) " "
-        TUPLE_EXPR@[28; 30)
-          L_PAREN@[28; 29) "("
-          R_PAREN@[29; 30) ")"
-        SEMI@[30; 31) ";"
-      WHITESPACE@[31; 36) "\n    "
-      LET_STMT@[36; 87)
-        LET_KW@[36; 39) "let"
-        WHITESPACE@[39; 40) " "
-        BOX_PAT@[40; 81)
-          BOX_KW@[40; 43) "box"
-          WHITESPACE@[43; 44) " "
-          RECORD_PAT@[44; 81)
-            PATH@[44; 49)
-              PATH_SEGMENT@[44; 49)
-                NAME_REF@[44; 49)
-                  IDENT@[44; 49) "Outer"
-            WHITESPACE@[49; 50) " "
-            RECORD_FIELD_PAT_LIST@[50; 81)
-              L_CURLY@[50; 51) "{"
-              WHITESPACE@[51; 52) " "
-              BOX_PAT@[52; 57)
-                BOX_KW@[52; 55) "box"
-                WHITESPACE@[55; 56) " "
-                BIND_PAT@[56; 57)
-                  NAME@[56; 57)
-                    IDENT@[56; 57) "i"
-              COMMA@[57; 58) ","
-              WHITESPACE@[58; 59) " "
-              RECORD_FIELD_PAT@[59; 79)
-                NAME@[59; 60)
-                  IDENT@[59; 60) "j"
-                COLON@[60; 61) ":"
-                WHITESPACE@[61; 62) " "
-                BOX_PAT@[62; 79)
-                  BOX_KW@[62; 65) "box"
-                  WHITESPACE@[65; 66) " "
-                  TUPLE_STRUCT_PAT@[66; 79)
-                    PATH@[66; 71)
-                      PATH_SEGMENT@[66; 71)
-                        NAME_REF@[66; 71)
-                          IDENT@[66; 71) "Inner"
-                    L_PAREN@[71; 72) "("
-                    BOX_PAT@[72; 78)
-                      BOX_KW@[72; 75) "box"
-                      WHITESPACE@[75; 76) " "
-                      REF_PAT@[76; 78)
-                        AMP@[76; 77) "&"
-                        BIND_PAT@[77; 78)
-                          NAME@[77; 78)
-                            IDENT@[77; 78) "x"
-                    R_PAREN@[78; 79) ")"
-              WHITESPACE@[79; 80) " "
-              R_CURLY@[80; 81) "}"
-        WHITESPACE@[81; 82) " "
-        EQ@[82; 83) "="
-        WHITESPACE@[83; 84) " "
-        TUPLE_EXPR@[84; 86)
-          L_PAREN@[84; 85) "("
-          R_PAREN@[85; 86) ")"
-        SEMI@[86; 87) ";"
-      WHITESPACE@[87; 92) "\n    "
-      LET_STMT@[92; 115)
-        LET_KW@[92; 95) "let"
-        WHITESPACE@[95; 96) " "
-        BOX_PAT@[96; 109)
-          BOX_KW@[96; 99) "box"
-          WHITESPACE@[99; 100) " "
-          BIND_PAT@[100; 109)
-            REF_KW@[100; 103) "ref"
-            WHITESPACE@[103; 104) " "
-            MUT_KW@[104; 107) "mut"
-            WHITESPACE@[107; 108) " "
-            NAME@[108; 109)
-              IDENT@[108; 109) "i"
-        WHITESPACE@[109; 110) " "
-        EQ@[110; 111) "="
-        WHITESPACE@[111; 112) " "
-        TUPLE_EXPR@[112; 114)
-          L_PAREN@[112; 113) "("
-          R_PAREN@[113; 114) ")"
-        SEMI@[114; 115) ";"
-      WHITESPACE@[115; 116) "\n"
-      R_CURLY@[116; 117) "}"
-  WHITESPACE@[117; 118) "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0001_struct_item.txt b/crates/ra_syntax/test_data/parser/ok/0001_struct_item.txt
index fdc2d67689..c6653cf25e 100644
--- a/crates/ra_syntax/test_data/parser/ok/0001_struct_item.txt
+++ b/crates/ra_syntax/test_data/parser/ok/0001_struct_item.txt
@@ -20,10 +20,10 @@ SOURCE_FILE@[0; 32)
                     IDENT@[12; 16) "Copy"
       R_ANGLE@[16; 17) ">"
     WHITESPACE@[17; 18) " "
-    RECORD_FIELD_DEF_LIST@[18; 31)
+    NAMED_FIELD_DEF_LIST@[18; 31)
       L_CURLY@[18; 19) "{"
       WHITESPACE@[19; 24) "\n    "
-      RECORD_FIELD_DEF@[24; 28)
+      NAMED_FIELD_DEF@[24; 28)
         NAME@[24; 25)
           IDENT@[24; 25) "f"
         COLON@[25; 26) ":"
diff --git a/crates/ra_syntax/test_data/parser/ok/0002_struct_item_field.txt b/crates/ra_syntax/test_data/parser/ok/0002_struct_item_field.txt
index ef34702fd0..d0565ea836 100644
--- a/crates/ra_syntax/test_data/parser/ok/0002_struct_item_field.txt
+++ b/crates/ra_syntax/test_data/parser/ok/0002_struct_item_field.txt
@@ -5,10 +5,10 @@ SOURCE_FILE@[0; 25)
     NAME@[7; 8)
       IDENT@[7; 8) "S"
     WHITESPACE@[8; 9) " "
-    RECORD_FIELD_DEF_LIST@[9; 25)
+    NAMED_FIELD_DEF_LIST@[9; 25)
       L_CURLY@[9; 10) "{"
       WHITESPACE@[10; 15) "\n    "
-      RECORD_FIELD_DEF@[15; 23)
+      NAMED_FIELD_DEF@[15; 23)
         NAME@[15; 18)
           IDENT@[15; 18) "foo"
         COLON@[18; 19) ":"
diff --git a/crates/ra_syntax/test_data/parser/ok/0008_mod_item.txt b/crates/ra_syntax/test_data/parser/ok/0008_mod_item.txt
index 5c16d0be67..9152d6eb67 100644
--- a/crates/ra_syntax/test_data/parser/ok/0008_mod_item.txt
+++ b/crates/ra_syntax/test_data/parser/ok/0008_mod_item.txt
@@ -46,7 +46,7 @@ SOURCE_FILE@[0; 118)
         NAME@[59; 60)
           IDENT@[59; 60) "S"
         WHITESPACE@[60; 61) " "
-        RECORD_FIELD_DEF_LIST@[61; 63)
+        NAMED_FIELD_DEF_LIST@[61; 63)
           L_CURLY@[61; 62) "{"
           R_CURLY@[62; 63) "}"
       WHITESPACE@[63; 64) "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0016_struct_flavors.txt b/crates/ra_syntax/test_data/parser/ok/0016_struct_flavors.txt
index 3fbd14d7b7..ac44093e82 100644
--- a/crates/ra_syntax/test_data/parser/ok/0016_struct_flavors.txt
+++ b/crates/ra_syntax/test_data/parser/ok/0016_struct_flavors.txt
@@ -12,7 +12,7 @@ SOURCE_FILE@[0; 97)
     NAME@[17; 18)
       IDENT@[17; 18) "B"
     WHITESPACE@[18; 19) " "
-    RECORD_FIELD_DEF_LIST@[19; 21)
+    NAMED_FIELD_DEF_LIST@[19; 21)
       L_CURLY@[19; 20) "{"
       R_CURLY@[20; 21) "}"
   WHITESPACE@[21; 22) "\n"
@@ -21,7 +21,7 @@ SOURCE_FILE@[0; 97)
     WHITESPACE@[28; 29) " "
     NAME@[29; 30)
       IDENT@[29; 30) "C"
-    TUPLE_FIELD_DEF_LIST@[30; 32)
+    POS_FIELD_DEF_LIST@[30; 32)
       L_PAREN@[30; 31) "("
       R_PAREN@[31; 32) ")"
     SEMI@[32; 33) ";"
@@ -32,10 +32,10 @@ SOURCE_FILE@[0; 97)
     NAME@[42; 43)
       IDENT@[42; 43) "D"
     WHITESPACE@[43; 44) " "
-    RECORD_FIELD_DEF_LIST@[44; 74)
+    NAMED_FIELD_DEF_LIST@[44; 74)
       L_CURLY@[44; 45) "{"
       WHITESPACE@[45; 50) "\n    "
-      RECORD_FIELD_DEF@[50; 56)
+      NAMED_FIELD_DEF@[50; 56)
         NAME@[50; 51)
           IDENT@[50; 51) "a"
         COLON@[51; 52) ":"
@@ -47,7 +47,7 @@ SOURCE_FILE@[0; 97)
                 IDENT@[53; 56) "u32"
       COMMA@[56; 57) ","
       WHITESPACE@[57; 62) "\n    "
-      RECORD_FIELD_DEF@[62; 72)
+      NAMED_FIELD_DEF@[62; 72)
         VISIBILITY@[62; 65)
           PUB_KW@[62; 65) "pub"
         WHITESPACE@[65; 66) " "
@@ -68,9 +68,9 @@ SOURCE_FILE@[0; 97)
     WHITESPACE@[82; 83) " "
     NAME@[83; 84)
       IDENT@[83; 84) "E"
-    TUPLE_FIELD_DEF_LIST@[84; 95)
+    POS_FIELD_DEF_LIST@[84; 95)
       L_PAREN@[84; 85) "("
-      TUPLE_FIELD_DEF@[85; 90)
+      POS_FIELD_DEF@[85; 90)
         VISIBILITY@[85; 88)
           PUB_KW@[85; 88) "pub"
         WHITESPACE@[88; 89) " "
@@ -81,7 +81,7 @@ SOURCE_FILE@[0; 97)
                 IDENT@[89; 90) "x"
       COMMA@[90; 91) ","
       WHITESPACE@[91; 92) " "
-      TUPLE_FIELD_DEF@[92; 93)
+      POS_FIELD_DEF@[92; 93)
         PATH_TYPE@[92; 93)
           PATH@[92; 93)
             PATH_SEGMENT@[92; 93)
diff --git a/crates/ra_syntax/test_data/parser/ok/0018_struct_type_params.txt b/crates/ra_syntax/test_data/parser/ok/0018_struct_type_params.txt
index 1e4e58dd3f..3f06f20f93 100644
--- a/crates/ra_syntax/test_data/parser/ok/0018_struct_type_params.txt
+++ b/crates/ra_syntax/test_data/parser/ok/0018_struct_type_params.txt
@@ -23,9 +23,9 @@ SOURCE_FILE@[0; 290)
         NAME@[24; 25)
           IDENT@[24; 25) "T"
       R_ANGLE@[25; 26) ">"
-    TUPLE_FIELD_DEF_LIST@[26; 31)
+    POS_FIELD_DEF_LIST@[26; 31)
       L_PAREN@[26; 27) "("
-      TUPLE_FIELD_DEF@[27; 30)
+      POS_FIELD_DEF@[27; 30)
         PATH_TYPE@[27; 30)
           PATH@[27; 30)
             PATH_SEGMENT@[27; 30)
@@ -46,10 +46,10 @@ SOURCE_FILE@[0; 290)
           IDENT@[43; 44) "T"
       R_ANGLE@[44; 45) ">"
     WHITESPACE@[45; 46) " "
-    RECORD_FIELD_DEF_LIST@[46; 56)
+    NAMED_FIELD_DEF_LIST@[46; 56)
       L_CURLY@[46; 47) "{"
       WHITESPACE@[47; 48) " "
-      RECORD_FIELD_DEF@[48; 54)
+      NAMED_FIELD_DEF@[48; 54)
         NAME@[48; 49)
           IDENT@[48; 49) "u"
         COLON@[49; 50) ":"
diff --git a/crates/ra_syntax/test_data/parser/ok/0019_enums.txt b/crates/ra_syntax/test_data/parser/ok/0019_enums.txt
index 9d4a47a51b..37753a7d00 100644
--- a/crates/ra_syntax/test_data/parser/ok/0019_enums.txt
+++ b/crates/ra_syntax/test_data/parser/ok/0019_enums.txt
@@ -86,10 +86,10 @@ SOURCE_FILE@[0; 182)
         NAME@[101; 102)
           IDENT@[101; 102) "C"
         WHITESPACE@[102; 103) " "
-        RECORD_FIELD_DEF_LIST@[103; 146)
+        NAMED_FIELD_DEF_LIST@[103; 146)
           L_CURLY@[103; 104) "{"
           WHITESPACE@[104; 113) "\n        "
-          RECORD_FIELD_DEF@[113; 119)
+          NAMED_FIELD_DEF@[113; 119)
             NAME@[113; 114)
               IDENT@[113; 114) "a"
             COLON@[114; 115) ":"
@@ -101,7 +101,7 @@ SOURCE_FILE@[0; 182)
                     IDENT@[116; 119) "u32"
           COMMA@[119; 120) ","
           WHITESPACE@[120; 129) "\n        "
-          RECORD_FIELD_DEF@[129; 139)
+          NAMED_FIELD_DEF@[129; 139)
             VISIBILITY@[129; 132)
               PUB_KW@[129; 132) "pub"
             WHITESPACE@[132; 133) " "
@@ -123,7 +123,7 @@ SOURCE_FILE@[0; 182)
         NAME@[152; 153)
           IDENT@[152; 153) "F"
         WHITESPACE@[153; 154) " "
-        RECORD_FIELD_DEF_LIST@[154; 156)
+        NAMED_FIELD_DEF_LIST@[154; 156)
           L_CURLY@[154; 155) "{"
           R_CURLY@[155; 156) "}"
       COMMA@[156; 157) ","
@@ -131,9 +131,9 @@ SOURCE_FILE@[0; 182)
       ENUM_VARIANT@[162; 169)
         NAME@[162; 163)
           IDENT@[162; 163) "D"
-        TUPLE_FIELD_DEF_LIST@[163; 169)
+        POS_FIELD_DEF_LIST@[163; 169)
           L_PAREN@[163; 164) "("
-          TUPLE_FIELD_DEF@[164; 167)
+          POS_FIELD_DEF@[164; 167)
             PATH_TYPE@[164; 167)
               PATH@[164; 167)
                 PATH_SEGMENT@[164; 167)
@@ -146,7 +146,7 @@ SOURCE_FILE@[0; 182)
       ENUM_VARIANT@[175; 178)
         NAME@[175; 176)
           IDENT@[175; 176) "E"
-        TUPLE_FIELD_DEF_LIST@[176; 178)
+        POS_FIELD_DEF_LIST@[176; 178)
           L_PAREN@[176; 177) "("
           R_PAREN@[177; 178) ")"
       COMMA@[178; 179) ","
diff --git a/crates/ra_syntax/test_data/parser/ok/0035_weird_exprs.txt b/crates/ra_syntax/test_data/parser/ok/0035_weird_exprs.txt
index c13ebfe37b..c89b591e93 100644
--- a/crates/ra_syntax/test_data/parser/ok/0035_weird_exprs.txt
+++ b/crates/ra_syntax/test_data/parser/ok/0035_weird_exprs.txt
@@ -1564,10 +1564,10 @@ SOURCE_FILE@[0; 3813)
             LIFETIME@[2863; 2869) "\'union"
           R_ANGLE@[2869; 2870) ">"
         WHITESPACE@[2870; 2871) " "
-        RECORD_FIELD_DEF_LIST@[2871; 2904)
+        NAMED_FIELD_DEF_LIST@[2871; 2904)
           L_CURLY@[2871; 2872) "{"
           WHITESPACE@[2872; 2873) " "
-          RECORD_FIELD_DEF@[2873; 2901)
+          NAMED_FIELD_DEF@[2873; 2901)
             NAME@[2873; 2878)
               IDENT@[2873; 2878) "union"
             COLON@[2878; 2879) ":"
diff --git a/crates/ra_syntax/test_data/parser/ok/0040_raw_struct_item_field.txt b/crates/ra_syntax/test_data/parser/ok/0040_raw_struct_item_field.txt
index 05f2c656f5..3c717555d4 100644
--- a/crates/ra_syntax/test_data/parser/ok/0040_raw_struct_item_field.txt
+++ b/crates/ra_syntax/test_data/parser/ok/0040_raw_struct_item_field.txt
@@ -5,10 +5,10 @@ SOURCE_FILE@[0; 27)
     NAME@[7; 8)
       IDENT@[7; 8) "S"
     WHITESPACE@[8; 9) " "
-    RECORD_FIELD_DEF_LIST@[9; 27)
+    NAMED_FIELD_DEF_LIST@[9; 27)
       L_CURLY@[9; 10) "{"
       WHITESPACE@[10; 15) "\n    "
-      RECORD_FIELD_DEF@[15; 25)
+      NAMED_FIELD_DEF@[15; 25)
         NAME@[15; 20)
           IDENT@[15; 20) "r#foo"
         COLON@[20; 21) ":"
diff --git a/crates/ra_syntax/test_data/parser/ok/0043_complex_assignment.txt b/crates/ra_syntax/test_data/parser/ok/0043_complex_assignment.txt
index 1f2456afac..ef47521bf7 100644
--- a/crates/ra_syntax/test_data/parser/ok/0043_complex_assignment.txt
+++ b/crates/ra_syntax/test_data/parser/ok/0043_complex_assignment.txt
@@ -7,10 +7,10 @@ SOURCE_FILE@[0; 160)
     NAME@[69; 73)
       IDENT@[69; 73) "Repr"
     WHITESPACE@[73; 74) " "
-    RECORD_FIELD_DEF_LIST@[74; 90)
+    NAMED_FIELD_DEF_LIST@[74; 90)
       L_CURLY@[74; 75) "{"
       WHITESPACE@[75; 76) " "
-      RECORD_FIELD_DEF@[76; 88)
+      NAMED_FIELD_DEF@[76; 88)
         NAME@[76; 79)
           IDENT@[76; 79) "raw"
         COLON@[79; 80) ":"
@@ -46,16 +46,16 @@ SOURCE_FILE@[0; 160)
         BIN_EXPR@[107; 135)
           INDEX_EXPR@[107; 131)
             FIELD_EXPR@[107; 128)
-              RECORD_LIT@[107; 124)
+              STRUCT_LIT@[107; 124)
                 PATH@[107; 111)
                   PATH_SEGMENT@[107; 111)
                     NAME_REF@[107; 111)
                       IDENT@[107; 111) "Repr"
                 WHITESPACE@[111; 112) " "
-                RECORD_FIELD_LIST@[112; 124)
+                NAMED_FIELD_LIST@[112; 124)
                   L_CURLY@[112; 113) "{"
                   WHITESPACE@[113; 114) " "
-                  RECORD_FIELD@[114; 122)
+                  NAMED_FIELD@[114; 122)
                     NAME_REF@[114; 117)
                       IDENT@[114; 117) "raw"
                     COLON@[117; 118) ":"
@@ -83,14 +83,14 @@ SOURCE_FILE@[0; 160)
       WHITESPACE@[136; 141) "\n    "
       EXPR_STMT@[141; 157)
         CALL_EXPR@[141; 156)
-          RECORD_LIT@[141; 154)
+          STRUCT_LIT@[141; 154)
             PATH@[141; 145)
               PATH_SEGMENT@[141; 145)
                 NAME_REF@[141; 145)
                   IDENT@[141; 145) "Repr"
-            RECORD_FIELD_LIST@[145; 154)
+            NAMED_FIELD_LIST@[145; 154)
               L_CURLY@[145; 146) "{"
-              RECORD_FIELD@[146; 153)
+              NAMED_FIELD@[146; 153)
                 NAME_REF@[146; 149)
                   IDENT@[146; 149) "raw"
                 COLON@[149; 150) ":"
diff --git a/crates/ra_syntax/test_data/parser/ok/0047_minus_in_inner_pattern.txt b/crates/ra_syntax/test_data/parser/ok/0047_minus_in_inner_pattern.txt
index 136e2aae1a..917b50ddf5 100644
--- a/crates/ra_syntax/test_data/parser/ok/0047_minus_in_inner_pattern.txt
+++ b/crates/ra_syntax/test_data/parser/ok/0047_minus_in_inner_pattern.txt
@@ -268,9 +268,9 @@ SOURCE_FILE@[0; 395)
       ENUM_VARIANT@[356; 365)
         NAME@[356; 357)
           IDENT@[356; 357) "B"
-        TUPLE_FIELD_DEF_LIST@[357; 365)
+        POS_FIELD_DEF_LIST@[357; 365)
           L_PAREN@[357; 358) "("
-          TUPLE_FIELD_DEF@[358; 360)
+          POS_FIELD_DEF@[358; 360)
             PATH_TYPE@[358; 360)
               PATH@[358; 360)
                 PATH_SEGMENT@[358; 360)
@@ -278,7 +278,7 @@ SOURCE_FILE@[0; 395)
                     IDENT@[358; 360) "i8"
           COMMA@[360; 361) ","
           WHITESPACE@[361; 362) " "
-          TUPLE_FIELD_DEF@[362; 364)
+          POS_FIELD_DEF@[362; 364)
             PATH_TYPE@[362; 364)
               PATH@[362; 364)
                 PATH_SEGMENT@[362; 364)
diff --git a/editors/code/src/test/index.ts b/editors/code/src/test/index.ts
deleted file mode 100644
index 6e565c254a..0000000000
--- a/editors/code/src/test/index.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-//
-// PLEASE DO NOT MODIFY / DELETE UNLESS YOU KNOW WHAT YOU ARE DOING
-//
-// This file is providing the test runner to use when running extension tests.
-// By default the test runner in use is Mocha based.
-//
-// You can provide your own test runner if you want to override it by exporting
-// a function run(testRoot: string, clb: (error:Error) => void) that the extension
-// host can call to run the tests. The test runner is expected to use console.log
-// to report the results back to the caller. When the tests are finished, return
-// a possible error to the callback or null if none.
-
-import * as testRunner from 'vscode/lib/testrunner';
-
-// You can directly control Mocha options by uncommenting the following lines
-// See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info
-testRunner.configure({
-    ui: 'bdd', // the TDD UI is being used in extension.test.ts (suite, test, etc.)
-    useColors: true // colored output from test results
-});
-
-module.exports = testRunner;
diff --git a/editors/code/src/test/runTest.ts b/editors/code/src/test/runTest.ts
new file mode 100644
index 0000000000..d880d47df7
--- /dev/null
+++ b/editors/code/src/test/runTest.ts
@@ -0,0 +1,22 @@
+import * as path from 'path';
+
+import { runTests } from 'vscode-test';
+
+async function main() {
+    try {
+        // The folder containing the Extension Manifest package.json
+        // Passed to `--extensionDevelopmentPath`
+        const extensionDevelopmentPath = path.resolve(__dirname, '../../');
+
+        // The path to the extension test runner script
+        // Passed to --extensionTestsPath
+        const extensionTestsPath = path.resolve(__dirname, './utils/index');
+
+        // Download VS Code, unzip it and run the integration test
+        await runTests({ extensionDevelopmentPath, extensionTestsPath });
+    } catch (err) {
+        process.exit(1);
+    }
+}
+
+main();
diff --git a/editors/code/src/test/utils/index.ts b/editors/code/src/test/utils/index.ts
new file mode 100644
index 0000000000..16715a286c
--- /dev/null
+++ b/editors/code/src/test/utils/index.ts
@@ -0,0 +1,49 @@
+//
+// PLEASE DO NOT MODIFY / DELETE UNLESS YOU KNOW WHAT YOU ARE DOING
+//
+// This file is providing the test runner to use when running extension tests.
+// By default the test runner in use is Mocha based.
+//
+// You can provide your own test runner if you want to override it by exporting
+// a function run(testRoot: string, clb: (error:Error) => void) that the extension
+// host can call to run the tests. The test runner is expected to use console.log
+// to report the results back to the caller. When the tests are finished, return
+// a possible error to the callback or null if none.
+
+import * as glob from 'glob';
+import * as Mocha from 'mocha';
+import * as path from 'path';
+
+export function run(): Promise<void> {
+    // Create the mocha test
+    const mocha = new Mocha({
+        ui: 'bdd'
+    });
+    mocha.useColors(true);
+
+    const testsRoot = __dirname;
+
+    return new Promise((c, e) => {
+        glob('**/**.test.js', { cwd: testsRoot }, (err, files) => {
+            if (err) {
+                return e(err);
+            }
+
+            // Add files to the test suite
+            files.forEach(f => mocha.addFile(path.resolve(testsRoot, f)));
+
+            try {
+                // Run the mocha test
+                mocha.run(failures => {
+                    if (failures > 0) {
+                        e(new Error(`${failures} tests failed.`));
+                    } else {
+                        c();
+                    }
+                });
+            } catch (err) {
+                e(err);
+            }
+        });
+    });
+}