diff options
59 files changed, 2405 insertions, 1390 deletions
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 307096ef3..d5c93f69b 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml | |||
@@ -109,12 +109,7 @@ jobs: | |||
109 | node-version: 12.x | 109 | node-version: 12.x |
110 | 110 | ||
111 | - name: Dist | 111 | - name: Dist |
112 | if: github.ref == 'refs/heads/release' | 112 | run: cargo xtask dist --client-patch-version $GITHUB_RUN_NUMBER |
113 | run: cargo xtask dist --client 0.2.$GITHUB_RUN_NUMBER | ||
114 | |||
115 | - name: Dist | ||
116 | if: github.ref != 'refs/heads/release' | ||
117 | run: cargo xtask dist --nightly --client 0.3.$GITHUB_RUN_NUMBER-nightly | ||
118 | 113 | ||
119 | - name: Run analysis-stats on rust-analyzer | 114 | - name: Run analysis-stats on rust-analyzer |
120 | run: target/${{ env.RA_TARGET }}/release/rust-analyzer analysis-stats . | 115 | run: target/${{ env.RA_TARGET }}/release/rust-analyzer analysis-stats . |
@@ -266,7 +261,7 @@ jobs: | |||
266 | with: | 261 | with: |
267 | node-version: 12.x | 262 | node-version: 12.x |
268 | 263 | ||
269 | - run: echo "TAG=$(date --iso --utc)" >> $GITHUB_ENV | 264 | - run: echo "TAG=$(date --iso -u)" >> $GITHUB_ENV |
270 | if: github.ref == 'refs/heads/release' | 265 | if: github.ref == 'refs/heads/release' |
271 | - run: echo "TAG=nightly" >> $GITHUB_ENV | 266 | - run: echo "TAG=nightly" >> $GITHUB_ENV |
272 | if: github.ref != 'refs/heads/release' | 267 | if: github.ref != 'refs/heads/release' |
diff --git a/Cargo.lock b/Cargo.lock index 98141f5cd..ba6862e98 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -841,9 +841,9 @@ dependencies = [ | |||
841 | 841 | ||
842 | [[package]] | 842 | [[package]] |
843 | name = "lsp-server" | 843 | name = "lsp-server" |
844 | version = "0.5.0" | 844 | version = "0.5.1" |
845 | source = "registry+https://github.com/rust-lang/crates.io-index" | 845 | source = "registry+https://github.com/rust-lang/crates.io-index" |
846 | checksum = "69b18dfe0e4a380b872aa79d8e0ee6c3d7a9682466e84b83ad807c88b3545f79" | 846 | checksum = "6825d7042d5ca1825a366c40c9446928ec7b30e2be97243a13b164aee6583992" |
847 | dependencies = [ | 847 | dependencies = [ |
848 | "crossbeam-channel", | 848 | "crossbeam-channel", |
849 | "log", | 849 | "log", |
@@ -1175,6 +1175,7 @@ dependencies = [ | |||
1175 | "log", | 1175 | "log", |
1176 | "memmap", | 1176 | "memmap", |
1177 | "object", | 1177 | "object", |
1178 | "profile", | ||
1178 | "serde", | 1179 | "serde", |
1179 | "serde_json", | 1180 | "serde_json", |
1180 | "snap", | 1181 | "snap", |
@@ -1302,9 +1303,9 @@ dependencies = [ | |||
1302 | 1303 | ||
1303 | [[package]] | 1304 | [[package]] |
1304 | name = "regex" | 1305 | name = "regex" |
1305 | version = "1.4.5" | 1306 | version = "1.4.6" |
1306 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1307 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1307 | checksum = "957056ecddbeba1b26965114e191d2e8589ce74db242b6ea25fc4062427a5c19" | 1308 | checksum = "2a26af418b574bd56588335b3a3659a65725d4e636eb1016c2f9e3b38c7cc759" |
1308 | dependencies = [ | 1309 | dependencies = [ |
1309 | "regex-syntax", | 1310 | "regex-syntax", |
1310 | ] | 1311 | ] |
@@ -1581,9 +1582,9 @@ dependencies = [ | |||
1581 | 1582 | ||
1582 | [[package]] | 1583 | [[package]] |
1583 | name = "syn" | 1584 | name = "syn" |
1584 | version = "1.0.69" | 1585 | version = "1.0.70" |
1585 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1586 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1586 | checksum = "48fe99c6bd8b1cc636890bcc071842de909d902c81ac7dab53ba33c421ab8ffb" | 1587 | checksum = "b9505f307c872bab8eb46f77ae357c8eba1fdacead58ee5a850116b1d7f82883" |
1587 | dependencies = [ | 1588 | dependencies = [ |
1588 | "proc-macro2", | 1589 | "proc-macro2", |
1589 | "quote", | 1590 | "quote", |
diff --git a/crates/base_db/src/input.rs b/crates/base_db/src/input.rs index 07628935f..0ef77ef5d 100644 --- a/crates/base_db/src/input.rs +++ b/crates/base_db/src/input.rs | |||
@@ -239,6 +239,7 @@ impl CrateGraph { | |||
239 | name: CrateName, | 239 | name: CrateName, |
240 | to: CrateId, | 240 | to: CrateId, |
241 | ) -> Result<(), CyclicDependenciesError> { | 241 | ) -> Result<(), CyclicDependenciesError> { |
242 | let _p = profile::span("add_dep"); | ||
242 | if self.dfs_find(from, to, &mut FxHashSet::default()) { | 243 | if self.dfs_find(from, to, &mut FxHashSet::default()) { |
243 | return Err(CyclicDependenciesError { | 244 | return Err(CyclicDependenciesError { |
244 | from: (from, self[from].display_name.clone()), | 245 | from: (from, self[from].display_name.clone()), |
diff --git a/crates/ide/src/display/navigation_target.rs b/crates/ide/src/display/navigation_target.rs index 364be260c..2079c22a3 100644 --- a/crates/ide/src/display/navigation_target.rs +++ b/crates/ide/src/display/navigation_target.rs | |||
@@ -20,7 +20,7 @@ use syntax::{ | |||
20 | 20 | ||
21 | use crate::FileSymbol; | 21 | use crate::FileSymbol; |
22 | 22 | ||
23 | /// `NavigationTarget` represents and element in the editor's UI which you can | 23 | /// `NavigationTarget` represents an element in the editor's UI which you can |
24 | /// click on to navigate to a particular piece of code. | 24 | /// click on to navigate to a particular piece of code. |
25 | /// | 25 | /// |
26 | /// Typically, a `NavigationTarget` corresponds to some element in the source | 26 | /// Typically, a `NavigationTarget` corresponds to some element in the source |
@@ -35,12 +35,10 @@ pub struct NavigationTarget { | |||
35 | /// Clients should use this range to answer "is the cursor inside the | 35 | /// Clients should use this range to answer "is the cursor inside the |
36 | /// element?" question. | 36 | /// element?" question. |
37 | pub full_range: TextRange, | 37 | pub full_range: TextRange, |
38 | /// A "most interesting" range withing the `full_range`. | 38 | /// A "most interesting" range within the `full_range`. |
39 | /// | 39 | /// |
40 | /// Typically, `full_range` is the whole syntax node, including doc | 40 | /// Typically, `full_range` is the whole syntax node, including doc |
41 | /// comments, and `focus_range` is the range of the identifier. "Most | 41 | /// comments, and `focus_range` is the range of the identifier. |
42 | /// interesting" range within the full range, typically the range of | ||
43 | /// identifier. | ||
44 | /// | 42 | /// |
45 | /// Clients should place the cursor on this range when navigating to this target. | 43 | /// Clients should place the cursor on this range when navigating to this target. |
46 | pub focus_range: Option<TextRange>, | 44 | pub focus_range: Option<TextRange>, |
diff --git a/crates/ide/src/references/rename.rs b/crates/ide/src/references/rename.rs index 2408a0181..175e7a31d 100644 --- a/crates/ide/src/references/rename.rs +++ b/crates/ide/src/references/rename.rs | |||
@@ -50,6 +50,17 @@ pub(crate) fn prepare_rename( | |||
50 | let sema = Semantics::new(db); | 50 | let sema = Semantics::new(db); |
51 | let source_file = sema.parse(position.file_id); | 51 | let source_file = sema.parse(position.file_id); |
52 | let syntax = source_file.syntax(); | 52 | let syntax = source_file.syntax(); |
53 | |||
54 | let def = find_definition(&sema, syntax, position)?; | ||
55 | match def { | ||
56 | Definition::SelfType(_) => bail!("Cannot rename `Self`"), | ||
57 | Definition::ModuleDef(ModuleDef::BuiltinType(_)) => bail!("Cannot rename builtin type"), | ||
58 | _ => {} | ||
59 | }; | ||
60 | let nav = | ||
61 | def.try_to_nav(sema.db).ok_or_else(|| format_err!("No references found at position"))?; | ||
62 | nav.focus_range.ok_or_else(|| format_err!("No identifier available to rename"))?; | ||
63 | |||
53 | let name_like = sema | 64 | let name_like = sema |
54 | .find_node_at_offset_with_descend(&syntax, position.offset) | 65 | .find_node_at_offset_with_descend(&syntax, position.offset) |
55 | .ok_or_else(|| format_err!("No references found at position"))?; | 66 | .ok_or_else(|| format_err!("No references found at position"))?; |
@@ -507,7 +518,8 @@ fn source_edit_from_def( | |||
507 | def.try_to_nav(sema.db).ok_or_else(|| format_err!("No references found at position"))?; | 518 | def.try_to_nav(sema.db).ok_or_else(|| format_err!("No references found at position"))?; |
508 | 519 | ||
509 | let mut replacement_text = String::new(); | 520 | let mut replacement_text = String::new(); |
510 | let mut repl_range = nav.focus_or_full_range(); | 521 | let mut repl_range = |
522 | nav.focus_range.ok_or_else(|| format_err!("No identifier available to rename"))?; | ||
511 | if let Definition::Local(local) = def { | 523 | if let Definition::Local(local) = def { |
512 | if let Either::Left(pat) = local.source(sema.db).value { | 524 | if let Either::Left(pat) = local.source(sema.db).value { |
513 | if matches!( | 525 | if matches!( |
@@ -626,6 +638,49 @@ foo!(Foo$0);", | |||
626 | } | 638 | } |
627 | 639 | ||
628 | #[test] | 640 | #[test] |
641 | fn test_prepare_rename_tuple_field() { | ||
642 | check_prepare( | ||
643 | r#" | ||
644 | struct Foo(i32); | ||
645 | |||
646 | fn baz() { | ||
647 | let mut x = Foo(4); | ||
648 | x.0$0 = 5; | ||
649 | } | ||
650 | "#, | ||
651 | expect![[r#"No identifier available to rename"#]], | ||
652 | ); | ||
653 | } | ||
654 | |||
655 | #[test] | ||
656 | fn test_prepare_rename_builtin() { | ||
657 | check_prepare( | ||
658 | r#" | ||
659 | fn foo() { | ||
660 | let x: i32$0 = 0; | ||
661 | } | ||
662 | "#, | ||
663 | expect![[r#"Cannot rename builtin type"#]], | ||
664 | ); | ||
665 | } | ||
666 | |||
667 | #[test] | ||
668 | fn test_prepare_rename_self() { | ||
669 | check_prepare( | ||
670 | r#" | ||
671 | struct Foo {} | ||
672 | |||
673 | impl Foo { | ||
674 | fn foo(self) -> Self$0 { | ||
675 | self | ||
676 | } | ||
677 | } | ||
678 | "#, | ||
679 | expect![[r#"Cannot rename `Self`"#]], | ||
680 | ); | ||
681 | } | ||
682 | |||
683 | #[test] | ||
629 | fn test_rename_to_underscore() { | 684 | fn test_rename_to_underscore() { |
630 | check("_", r#"fn main() { let i$0 = 1; }"#, r#"fn main() { let _ = 1; }"#); | 685 | check("_", r#"fn main() { let i$0 = 1; }"#, r#"fn main() { let _ = 1; }"#); |
631 | } | 686 | } |
@@ -1787,4 +1842,50 @@ fn foo() { | |||
1787 | "#, | 1842 | "#, |
1788 | ) | 1843 | ) |
1789 | } | 1844 | } |
1845 | |||
1846 | #[test] | ||
1847 | fn test_rename_tuple_field() { | ||
1848 | check( | ||
1849 | "foo", | ||
1850 | r#" | ||
1851 | struct Foo(i32); | ||
1852 | |||
1853 | fn baz() { | ||
1854 | let mut x = Foo(4); | ||
1855 | x.0$0 = 5; | ||
1856 | } | ||
1857 | "#, | ||
1858 | "error: No identifier available to rename", | ||
1859 | ); | ||
1860 | } | ||
1861 | |||
1862 | #[test] | ||
1863 | fn test_rename_builtin() { | ||
1864 | check( | ||
1865 | "foo", | ||
1866 | r#" | ||
1867 | fn foo() { | ||
1868 | let x: i32$0 = 0; | ||
1869 | } | ||
1870 | "#, | ||
1871 | "error: Cannot rename builtin type", | ||
1872 | ); | ||
1873 | } | ||
1874 | |||
1875 | #[test] | ||
1876 | fn test_rename_self() { | ||
1877 | check( | ||
1878 | "foo", | ||
1879 | r#" | ||
1880 | struct Foo {} | ||
1881 | |||
1882 | impl Foo { | ||
1883 | fn foo(self) -> Self$0 { | ||
1884 | self | ||
1885 | } | ||
1886 | } | ||
1887 | "#, | ||
1888 | "error: Cannot rename `Self`", | ||
1889 | ); | ||
1890 | } | ||
1790 | } | 1891 | } |
diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs index 18552459b..b586dcc17 100644 --- a/crates/ide/src/syntax_highlighting/highlight.rs +++ b/crates/ide/src/syntax_highlighting/highlight.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | //! Computes color for a single element. | 1 | //! Computes color for a single element. |
2 | 2 | ||
3 | use hir::{AsAssocItem, AssocItemContainer, Semantics, VariantDef}; | 3 | use hir::{AsAssocItem, Semantics}; |
4 | use ide_db::{ | 4 | use ide_db::{ |
5 | defs::{Definition, NameClass, NameRefClass}, | 5 | defs::{Definition, NameClass, NameRefClass}, |
6 | RootDatabase, SymbolKind, | 6 | RootDatabase, SymbolKind, |
@@ -45,28 +45,26 @@ pub(super) fn element( | |||
45 | }; | 45 | }; |
46 | 46 | ||
47 | match name_kind { | 47 | match name_kind { |
48 | Some(NameClass::ExternCrate(_)) => HlTag::Symbol(SymbolKind::Module).into(), | 48 | Some(NameClass::ExternCrate(_)) => SymbolKind::Module.into(), |
49 | Some(NameClass::Definition(def)) => highlight_def(db, def) | HlMod::Definition, | 49 | Some(NameClass::Definition(def)) => highlight_def(db, def) | HlMod::Definition, |
50 | Some(NameClass::ConstReference(def)) => highlight_def(db, def), | 50 | Some(NameClass::ConstReference(def)) => highlight_def(db, def), |
51 | Some(NameClass::PatFieldShorthand { field_ref, .. }) => { | 51 | Some(NameClass::PatFieldShorthand { field_ref, .. }) => { |
52 | let mut h = HlTag::Symbol(SymbolKind::Field).into(); | 52 | let mut h = HlTag::Symbol(SymbolKind::Field).into(); |
53 | if let Definition::Field(field) = field_ref { | 53 | if let Definition::Field(field) = field_ref { |
54 | if let VariantDef::Union(_) = field.parent_def(db) { | 54 | if let hir::VariantDef::Union(_) = field.parent_def(db) { |
55 | h |= HlMod::Unsafe; | 55 | h |= HlMod::Unsafe; |
56 | } | 56 | } |
57 | } | 57 | } |
58 | |||
59 | h | 58 | h |
60 | } | 59 | } |
61 | None => highlight_name_by_syntax(name) | HlMod::Definition, | 60 | None => highlight_name_by_syntax(name) | HlMod::Definition, |
62 | } | 61 | } |
63 | } | 62 | } |
64 | |||
65 | // Highlight references like the definitions they resolve to | 63 | // Highlight references like the definitions they resolve to |
66 | NAME_REF if element.ancestors().any(|it| it.kind() == ATTR) => { | 64 | NAME_REF if element.ancestors().any(|it| it.kind() == ATTR) => { |
67 | // even though we track whether we are in an attribute or not we still need this special case | 65 | // even though we track whether we are in an attribute or not we still need this special case |
68 | // as otherwise we would emit unresolved references for name refs inside attributes | 66 | // as otherwise we would emit unresolved references for name refs inside attributes |
69 | Highlight::from(HlTag::Symbol(SymbolKind::Function)) | 67 | SymbolKind::Function.into() |
70 | } | 68 | } |
71 | NAME_REF => { | 69 | NAME_REF => { |
72 | let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap(); | 70 | let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap(); |
@@ -74,7 +72,7 @@ pub(super) fn element( | |||
74 | let is_self = name_ref.self_token().is_some(); | 72 | let is_self = name_ref.self_token().is_some(); |
75 | let h = match NameRefClass::classify(sema, &name_ref) { | 73 | let h = match NameRefClass::classify(sema, &name_ref) { |
76 | Some(name_kind) => match name_kind { | 74 | Some(name_kind) => match name_kind { |
77 | NameRefClass::ExternCrate(_) => HlTag::Symbol(SymbolKind::Module).into(), | 75 | NameRefClass::ExternCrate(_) => SymbolKind::Module.into(), |
78 | NameRefClass::Definition(def) => { | 76 | NameRefClass::Definition(def) => { |
79 | if let Definition::Local(local) = &def { | 77 | if let Definition::Local(local) = &def { |
80 | if let Some(name) = local.name(db) { | 78 | if let Some(name) = local.name(db) { |
@@ -95,7 +93,7 @@ pub(super) fn element( | |||
95 | if let Some(parent) = name_ref.syntax().parent() { | 93 | if let Some(parent) = name_ref.syntax().parent() { |
96 | if matches!(parent.kind(), FIELD_EXPR | RECORD_PAT_FIELD) { | 94 | if matches!(parent.kind(), FIELD_EXPR | RECORD_PAT_FIELD) { |
97 | if let Definition::Field(field) = def { | 95 | if let Definition::Field(field) = def { |
98 | if let VariantDef::Union(_) = field.parent_def(db) { | 96 | if let hir::VariantDef::Union(_) = field.parent_def(db) { |
99 | h |= HlMod::Unsafe; | 97 | h |= HlMod::Unsafe; |
100 | } | 98 | } |
101 | } | 99 | } |
@@ -104,9 +102,7 @@ pub(super) fn element( | |||
104 | 102 | ||
105 | h | 103 | h |
106 | } | 104 | } |
107 | NameRefClass::FieldShorthand { .. } => { | 105 | NameRefClass::FieldShorthand { .. } => SymbolKind::Field.into(), |
108 | HlTag::Symbol(SymbolKind::Field).into() | ||
109 | } | ||
110 | }, | 106 | }, |
111 | None if syntactic_name_ref_highlighting => { | 107 | None if syntactic_name_ref_highlighting => { |
112 | highlight_name_ref_by_syntax(name_ref, sema) | 108 | highlight_name_ref_by_syntax(name_ref, sema) |
@@ -114,7 +110,7 @@ pub(super) fn element( | |||
114 | None => HlTag::UnresolvedReference.into(), | 110 | None => HlTag::UnresolvedReference.into(), |
115 | }; | 111 | }; |
116 | if h.tag == HlTag::Symbol(SymbolKind::Module) && is_self { | 112 | if h.tag == HlTag::Symbol(SymbolKind::Module) && is_self { |
117 | HlTag::Symbol(SymbolKind::SelfParam).into() | 113 | SymbolKind::SelfParam.into() |
118 | } else { | 114 | } else { |
119 | h | 115 | h |
120 | } | 116 | } |
@@ -135,7 +131,7 @@ pub(super) fn element( | |||
135 | INT_NUMBER | FLOAT_NUMBER => HlTag::NumericLiteral.into(), | 131 | INT_NUMBER | FLOAT_NUMBER => HlTag::NumericLiteral.into(), |
136 | BYTE => HlTag::ByteLiteral.into(), | 132 | BYTE => HlTag::ByteLiteral.into(), |
137 | CHAR => HlTag::CharLiteral.into(), | 133 | CHAR => HlTag::CharLiteral.into(), |
138 | QUESTION => Highlight::new(HlTag::Operator(HlOperator::Other)) | HlMod::ControlFlow, | 134 | QUESTION => HlTag::Operator(HlOperator::Other) | HlMod::ControlFlow, |
139 | LIFETIME => { | 135 | LIFETIME => { |
140 | let lifetime = element.into_node().and_then(ast::Lifetime::cast).unwrap(); | 136 | let lifetime = element.into_node().and_then(ast::Lifetime::cast).unwrap(); |
141 | 137 | ||
@@ -143,44 +139,31 @@ pub(super) fn element( | |||
143 | Some(NameClass::Definition(def)) => highlight_def(db, def) | HlMod::Definition, | 139 | Some(NameClass::Definition(def)) => highlight_def(db, def) | HlMod::Definition, |
144 | None => match NameRefClass::classify_lifetime(sema, &lifetime) { | 140 | None => match NameRefClass::classify_lifetime(sema, &lifetime) { |
145 | Some(NameRefClass::Definition(def)) => highlight_def(db, def), | 141 | Some(NameRefClass::Definition(def)) => highlight_def(db, def), |
146 | _ => Highlight::new(HlTag::Symbol(SymbolKind::LifetimeParam)), | 142 | _ => SymbolKind::LifetimeParam.into(), |
147 | }, | 143 | }, |
148 | _ => Highlight::new(HlTag::Symbol(SymbolKind::LifetimeParam)) | HlMod::Definition, | 144 | _ => Highlight::from(SymbolKind::LifetimeParam) | HlMod::Definition, |
149 | } | 145 | } |
150 | } | 146 | } |
151 | p if p.is_punct() => match p { | 147 | p if p.is_punct() => match p { |
152 | T![&] if element.parent().and_then(ast::BinExpr::cast).is_some() => { | 148 | T![&] if parent_matches::<ast::BinExpr>(&element) => HlOperator::Bitwise.into(), |
153 | HlTag::Operator(HlOperator::Bitwise).into() | ||
154 | } | ||
155 | T![&] => { | 149 | T![&] => { |
156 | let h = HlTag::Operator(HlOperator::Other).into(); | 150 | let h = HlTag::Operator(HlOperator::Other).into(); |
157 | let is_unsafe = element | 151 | let is_unsafe = element |
158 | .parent() | 152 | .parent() |
159 | .and_then(ast::RefExpr::cast) | 153 | .and_then(ast::RefExpr::cast) |
160 | .map(|ref_expr| sema.is_unsafe_ref_expr(&ref_expr)) | 154 | .map_or(false, |ref_expr| sema.is_unsafe_ref_expr(&ref_expr)); |
161 | .unwrap_or(false); | ||
162 | if is_unsafe { | 155 | if is_unsafe { |
163 | h | HlMod::Unsafe | 156 | h | HlMod::Unsafe |
164 | } else { | 157 | } else { |
165 | h | 158 | h |
166 | } | 159 | } |
167 | } | 160 | } |
168 | T![::] | T![->] | T![=>] | T![..] | T![=] | T![@] | T![.] => { | 161 | T![::] | T![->] | T![=>] | T![..] | T![=] | T![@] | T![.] => HlOperator::Other.into(), |
169 | HlTag::Operator(HlOperator::Other).into() | 162 | T![!] if parent_matches::<ast::MacroCall>(&element) => SymbolKind::Macro.into(), |
170 | } | 163 | T![!] if parent_matches::<ast::NeverType>(&element) => HlTag::BuiltinType.into(), |
171 | T![!] if element.parent().and_then(ast::MacroCall::cast).is_some() => { | 164 | T![!] if parent_matches::<ast::PrefixExpr>(&element) => HlOperator::Logical.into(), |
172 | HlTag::Symbol(SymbolKind::Macro).into() | 165 | T![*] if parent_matches::<ast::PtrType>(&element) => HlTag::Keyword.into(), |
173 | } | 166 | T![*] if parent_matches::<ast::PrefixExpr>(&element) => { |
174 | T![!] if element.parent().and_then(ast::NeverType::cast).is_some() => { | ||
175 | HlTag::BuiltinType.into() | ||
176 | } | ||
177 | T![!] if element.parent().and_then(ast::PrefixExpr::cast).is_some() => { | ||
178 | HlTag::Operator(HlOperator::Logical).into() | ||
179 | } | ||
180 | T![*] if element.parent().and_then(ast::PtrType::cast).is_some() => { | ||
181 | HlTag::Keyword.into() | ||
182 | } | ||
183 | T![*] if element.parent().and_then(ast::PrefixExpr::cast).is_some() => { | ||
184 | let prefix_expr = element.parent().and_then(ast::PrefixExpr::cast)?; | 167 | let prefix_expr = element.parent().and_then(ast::PrefixExpr::cast)?; |
185 | 168 | ||
186 | let expr = prefix_expr.expr()?; | 169 | let expr = prefix_expr.expr()?; |
@@ -188,12 +171,12 @@ pub(super) fn element( | |||
188 | if ty.is_raw_ptr() { | 171 | if ty.is_raw_ptr() { |
189 | HlTag::Operator(HlOperator::Other) | HlMod::Unsafe | 172 | HlTag::Operator(HlOperator::Other) | HlMod::Unsafe |
190 | } else if let Some(ast::PrefixOp::Deref) = prefix_expr.op_kind() { | 173 | } else if let Some(ast::PrefixOp::Deref) = prefix_expr.op_kind() { |
191 | HlTag::Operator(HlOperator::Other).into() | 174 | HlOperator::Other.into() |
192 | } else { | 175 | } else { |
193 | HlTag::Punctuation(HlPunct::Other).into() | 176 | HlPunct::Other.into() |
194 | } | 177 | } |
195 | } | 178 | } |
196 | T![-] if element.parent().and_then(ast::PrefixExpr::cast).is_some() => { | 179 | T![-] if parent_matches::<ast::PrefixExpr>(&element) => { |
197 | let prefix_expr = element.parent().and_then(ast::PrefixExpr::cast)?; | 180 | let prefix_expr = element.parent().and_then(ast::PrefixExpr::cast)?; |
198 | 181 | ||
199 | let expr = prefix_expr.expr()?; | 182 | let expr = prefix_expr.expr()?; |
@@ -203,41 +186,31 @@ pub(super) fn element( | |||
203 | } | 186 | } |
204 | .into() | 187 | .into() |
205 | } | 188 | } |
206 | _ if element.parent().and_then(ast::PrefixExpr::cast).is_some() => { | 189 | _ if parent_matches::<ast::PrefixExpr>(&element) => HlOperator::Other.into(), |
207 | HlTag::Operator(HlOperator::Other).into() | ||
208 | } | ||
209 | T![+] | T![-] | T![*] | T![/] | T![+=] | T![-=] | T![*=] | T![/=] | 190 | T![+] | T![-] | T![*] | T![/] | T![+=] | T![-=] | T![*=] | T![/=] |
210 | if element.parent().and_then(ast::BinExpr::cast).is_some() => | 191 | if parent_matches::<ast::BinExpr>(&element) => |
211 | { | 192 | { |
212 | HlTag::Operator(HlOperator::Arithmetic).into() | 193 | HlOperator::Arithmetic.into() |
213 | } | 194 | } |
214 | T![|] | T![&] | T![!] | T![^] | T![|=] | T![&=] | T![^=] | 195 | T![|] | T![&] | T![!] | T![^] | T![|=] | T![&=] | T![^=] |
215 | if element.parent().and_then(ast::BinExpr::cast).is_some() => | 196 | if parent_matches::<ast::BinExpr>(&element) => |
216 | { | 197 | { |
217 | HlTag::Operator(HlOperator::Bitwise).into() | 198 | HlOperator::Bitwise.into() |
218 | } | 199 | } |
219 | T![&&] | T![||] if element.parent().and_then(ast::BinExpr::cast).is_some() => { | 200 | T![&&] | T![||] if parent_matches::<ast::BinExpr>(&element) => { |
220 | HlTag::Operator(HlOperator::Logical).into() | 201 | HlOperator::Logical.into() |
221 | } | 202 | } |
222 | T![>] | T![<] | T![==] | T![>=] | T![<=] | T![!=] | 203 | T![>] | T![<] | T![==] | T![>=] | T![<=] | T![!=] |
223 | if element.parent().and_then(ast::BinExpr::cast).is_some() => | 204 | if parent_matches::<ast::BinExpr>(&element) => |
224 | { | 205 | { |
225 | HlTag::Operator(HlOperator::Comparison).into() | 206 | HlOperator::Comparison.into() |
226 | } | ||
227 | _ if element.parent().and_then(ast::BinExpr::cast).is_some() => { | ||
228 | HlTag::Operator(HlOperator::Other).into() | ||
229 | } | ||
230 | _ if element.parent().and_then(ast::RangeExpr::cast).is_some() => { | ||
231 | HlTag::Operator(HlOperator::Other).into() | ||
232 | } | 207 | } |
233 | _ if element.parent().and_then(ast::RangePat::cast).is_some() => { | 208 | _ if parent_matches::<ast::BinExpr>(&element) => HlOperator::Other.into(), |
234 | HlTag::Operator(HlOperator::Other).into() | 209 | _ if parent_matches::<ast::RangeExpr>(&element) => HlOperator::Other.into(), |
235 | } | 210 | _ if parent_matches::<ast::RangePat>(&element) => HlOperator::Other.into(), |
236 | _ if element.parent().and_then(ast::RestPat::cast).is_some() => { | 211 | _ if parent_matches::<ast::RestPat>(&element) => HlOperator::Other.into(), |
237 | HlTag::Operator(HlOperator::Other).into() | 212 | _ if parent_matches::<ast::Attr>(&element) => HlTag::Attribute.into(), |
238 | } | 213 | kind => match kind { |
239 | _ if element.parent().and_then(ast::Attr::cast).is_some() => HlTag::Attribute.into(), | ||
240 | kind => HlTag::Punctuation(match kind { | ||
241 | T!['['] | T![']'] => HlPunct::Bracket, | 214 | T!['['] | T![']'] => HlPunct::Bracket, |
242 | T!['{'] | T!['}'] => HlPunct::Brace, | 215 | T!['{'] | T!['}'] => HlPunct::Brace, |
243 | T!['('] | T![')'] => HlPunct::Parenthesis, | 216 | T!['('] | T![')'] => HlPunct::Parenthesis, |
@@ -247,22 +220,24 @@ pub(super) fn element( | |||
247 | T![;] => HlPunct::Semi, | 220 | T![;] => HlPunct::Semi, |
248 | T![.] => HlPunct::Dot, | 221 | T![.] => HlPunct::Dot, |
249 | _ => HlPunct::Other, | 222 | _ => HlPunct::Other, |
250 | }) | 223 | } |
251 | .into(), | 224 | .into(), |
252 | }, | 225 | }, |
253 | 226 | ||
254 | k if k.is_keyword() => { | 227 | k if k.is_keyword() => { |
255 | let h = Highlight::new(HlTag::Keyword); | 228 | let h = Highlight::new(HlTag::Keyword); |
256 | match k { | 229 | match k { |
257 | T![break] | 230 | T![await] |
231 | | T![break] | ||
258 | | T![continue] | 232 | | T![continue] |
259 | | T![else] | 233 | | T![else] |
260 | | T![if] | 234 | | T![if] |
235 | | T![in] | ||
261 | | T![loop] | 236 | | T![loop] |
262 | | T![match] | 237 | | T![match] |
263 | | T![return] | 238 | | T![return] |
264 | | T![while] | 239 | | T![while] |
265 | | T![in] => h | HlMod::ControlFlow, | 240 | | T![yield] => h | HlMod::ControlFlow, |
266 | T![for] if !is_child_of_impl(&element) => h | HlMod::ControlFlow, | 241 | T![for] if !is_child_of_impl(&element) => h | HlMod::ControlFlow, |
267 | T![unsafe] => h | HlMod::Unsafe, | 242 | T![unsafe] => h | HlMod::Unsafe, |
268 | T![true] | T![false] => HlTag::BoolLiteral.into(), | 243 | T![true] | T![false] => HlTag::BoolLiteral.into(), |
@@ -301,7 +276,6 @@ pub(super) fn element( | |||
301 | hash((name, shadow_count)) | 276 | hash((name, shadow_count)) |
302 | } | 277 | } |
303 | } | 278 | } |
304 | |||
305 | fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight { | 279 | fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight { |
306 | match def { | 280 | match def { |
307 | Definition::Macro(_) => HlTag::Symbol(SymbolKind::Macro), | 281 | Definition::Macro(_) => HlTag::Symbol(SymbolKind::Macro), |
@@ -312,17 +286,22 @@ fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight { | |||
312 | let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Function)); | 286 | let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Function)); |
313 | if let Some(item) = func.as_assoc_item(db) { | 287 | if let Some(item) = func.as_assoc_item(db) { |
314 | h |= HlMod::Associated; | 288 | h |= HlMod::Associated; |
315 | if func.self_param(db).is_none() { | 289 | match func.self_param(db) { |
316 | h |= HlMod::Static | 290 | Some(sp) => { |
291 | if let hir::Access::Exclusive = sp.access(db) { | ||
292 | h |= HlMod::Mutable; | ||
293 | } | ||
294 | } | ||
295 | None => h |= HlMod::Static, | ||
317 | } | 296 | } |
318 | 297 | ||
319 | match item.container(db) { | 298 | match item.container(db) { |
320 | AssocItemContainer::Impl(i) => { | 299 | hir::AssocItemContainer::Impl(i) => { |
321 | if i.trait_(db).is_some() { | 300 | if i.trait_(db).is_some() { |
322 | h |= HlMod::Trait; | 301 | h |= HlMod::Trait; |
323 | } | 302 | } |
324 | } | 303 | } |
325 | AssocItemContainer::Trait(_t) => { | 304 | hir::AssocItemContainer::Trait(_t) => { |
326 | h |= HlMod::Trait; | 305 | h |= HlMod::Trait; |
327 | } | 306 | } |
328 | } | 307 | } |
@@ -342,12 +321,12 @@ fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight { | |||
342 | if let Some(item) = konst.as_assoc_item(db) { | 321 | if let Some(item) = konst.as_assoc_item(db) { |
343 | h |= HlMod::Associated; | 322 | h |= HlMod::Associated; |
344 | match item.container(db) { | 323 | match item.container(db) { |
345 | AssocItemContainer::Impl(i) => { | 324 | hir::AssocItemContainer::Impl(i) => { |
346 | if i.trait_(db).is_some() { | 325 | if i.trait_(db).is_some() { |
347 | h |= HlMod::Trait; | 326 | h |= HlMod::Trait; |
348 | } | 327 | } |
349 | } | 328 | } |
350 | AssocItemContainer::Trait(_t) => { | 329 | hir::AssocItemContainer::Trait(_t) => { |
351 | h |= HlMod::Trait; | 330 | h |= HlMod::Trait; |
352 | } | 331 | } |
353 | } | 332 | } |
@@ -361,12 +340,12 @@ fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight { | |||
361 | if let Some(item) = type_.as_assoc_item(db) { | 340 | if let Some(item) = type_.as_assoc_item(db) { |
362 | h |= HlMod::Associated; | 341 | h |= HlMod::Associated; |
363 | match item.container(db) { | 342 | match item.container(db) { |
364 | AssocItemContainer::Impl(i) => { | 343 | hir::AssocItemContainer::Impl(i) => { |
365 | if i.trait_(db).is_some() { | 344 | if i.trait_(db).is_some() { |
366 | h |= HlMod::Trait; | 345 | h |= HlMod::Trait; |
367 | } | 346 | } |
368 | } | 347 | } |
369 | AssocItemContainer::Trait(_t) => { | 348 | hir::AssocItemContainer::Trait(_t) => { |
370 | h |= HlMod::Trait; | 349 | h |= HlMod::Trait; |
371 | } | 350 | } |
372 | } | 351 | } |
@@ -425,7 +404,7 @@ fn highlight_method_call( | |||
425 | method_call: &ast::MethodCallExpr, | 404 | method_call: &ast::MethodCallExpr, |
426 | ) -> Option<Highlight> { | 405 | ) -> Option<Highlight> { |
427 | let func = sema.resolve_method_call(&method_call)?; | 406 | let func = sema.resolve_method_call(&method_call)?; |
428 | let mut h = HlTag::Symbol(SymbolKind::Function).into(); | 407 | let mut h = SymbolKind::Function.into(); |
429 | h |= HlMod::Associated; | 408 | h |= HlMod::Associated; |
430 | if func.is_unsafe(sema.db) || sema.is_unsafe_method_call(&method_call) { | 409 | if func.is_unsafe(sema.db) || sema.is_unsafe_method_call(&method_call) { |
431 | h |= HlMod::Unsafe; | 410 | h |= HlMod::Unsafe; |
@@ -461,20 +440,20 @@ fn highlight_name_by_syntax(name: ast::Name) -> Highlight { | |||
461 | }; | 440 | }; |
462 | 441 | ||
463 | let tag = match parent.kind() { | 442 | let tag = match parent.kind() { |
464 | STRUCT => HlTag::Symbol(SymbolKind::Struct), | 443 | STRUCT => SymbolKind::Struct, |
465 | ENUM => HlTag::Symbol(SymbolKind::Enum), | 444 | ENUM => SymbolKind::Enum, |
466 | VARIANT => HlTag::Symbol(SymbolKind::Variant), | 445 | VARIANT => SymbolKind::Variant, |
467 | UNION => HlTag::Symbol(SymbolKind::Union), | 446 | UNION => SymbolKind::Union, |
468 | TRAIT => HlTag::Symbol(SymbolKind::Trait), | 447 | TRAIT => SymbolKind::Trait, |
469 | TYPE_ALIAS => HlTag::Symbol(SymbolKind::TypeAlias), | 448 | TYPE_ALIAS => SymbolKind::TypeAlias, |
470 | TYPE_PARAM => HlTag::Symbol(SymbolKind::TypeParam), | 449 | TYPE_PARAM => SymbolKind::TypeParam, |
471 | RECORD_FIELD => HlTag::Symbol(SymbolKind::Field), | 450 | RECORD_FIELD => SymbolKind::Field, |
472 | MODULE => HlTag::Symbol(SymbolKind::Module), | 451 | MODULE => SymbolKind::Module, |
473 | FN => HlTag::Symbol(SymbolKind::Function), | 452 | FN => SymbolKind::Function, |
474 | CONST => HlTag::Symbol(SymbolKind::Const), | 453 | CONST => SymbolKind::Const, |
475 | STATIC => HlTag::Symbol(SymbolKind::Static), | 454 | STATIC => SymbolKind::Static, |
476 | IDENT_PAT => HlTag::Symbol(SymbolKind::Local), | 455 | IDENT_PAT => SymbolKind::Local, |
477 | _ => default, | 456 | _ => return default.into(), |
478 | }; | 457 | }; |
479 | 458 | ||
480 | tag.into() | 459 | tag.into() |
@@ -492,20 +471,15 @@ fn highlight_name_ref_by_syntax(name: ast::NameRef, sema: &Semantics<RootDatabas | |||
492 | METHOD_CALL_EXPR => { | 471 | METHOD_CALL_EXPR => { |
493 | return ast::MethodCallExpr::cast(parent) | 472 | return ast::MethodCallExpr::cast(parent) |
494 | .and_then(|it| highlight_method_call(sema, &it)) | 473 | .and_then(|it| highlight_method_call(sema, &it)) |
495 | .unwrap_or_else(|| HlTag::Symbol(SymbolKind::Function).into()); | 474 | .unwrap_or_else(|| SymbolKind::Function.into()); |
496 | } | 475 | } |
497 | FIELD_EXPR => { | 476 | FIELD_EXPR => { |
498 | let h = HlTag::Symbol(SymbolKind::Field); | 477 | let h = HlTag::Symbol(SymbolKind::Field); |
499 | let is_union = ast::FieldExpr::cast(parent) | 478 | let is_union = ast::FieldExpr::cast(parent) |
500 | .and_then(|field_expr| { | 479 | .and_then(|field_expr| sema.resolve_field(&field_expr)) |
501 | let field = sema.resolve_field(&field_expr)?; | 480 | .map_or(false, |field| { |
502 | Some(if let VariantDef::Union(_) = field.parent_def(sema.db) { | 481 | matches!(field.parent_def(sema.db), hir::VariantDef::Union(_)) |
503 | true | 482 | }); |
504 | } else { | ||
505 | false | ||
506 | }) | ||
507 | }) | ||
508 | .unwrap_or(false); | ||
509 | if is_union { | 483 | if is_union { |
510 | h | HlMod::Unsafe | 484 | h | HlMod::Unsafe |
511 | } else { | 485 | } else { |
@@ -522,9 +496,9 @@ fn highlight_name_ref_by_syntax(name: ast::NameRef, sema: &Semantics<RootDatabas | |||
522 | _ => { | 496 | _ => { |
523 | // within path, decide whether it is module or adt by checking for uppercase name | 497 | // within path, decide whether it is module or adt by checking for uppercase name |
524 | return if name.text().chars().next().unwrap_or_default().is_uppercase() { | 498 | return if name.text().chars().next().unwrap_or_default().is_uppercase() { |
525 | HlTag::Symbol(SymbolKind::Struct) | 499 | SymbolKind::Struct |
526 | } else { | 500 | } else { |
527 | HlTag::Symbol(SymbolKind::Module) | 501 | SymbolKind::Module |
528 | } | 502 | } |
529 | .into(); | 503 | .into(); |
530 | } | 504 | } |
@@ -535,11 +509,11 @@ fn highlight_name_ref_by_syntax(name: ast::NameRef, sema: &Semantics<RootDatabas | |||
535 | }; | 509 | }; |
536 | 510 | ||
537 | match parent.kind() { | 511 | match parent.kind() { |
538 | CALL_EXPR => HlTag::Symbol(SymbolKind::Function).into(), | 512 | CALL_EXPR => SymbolKind::Function.into(), |
539 | _ => if name.text().chars().next().unwrap_or_default().is_uppercase() { | 513 | _ => if name.text().chars().next().unwrap_or_default().is_uppercase() { |
540 | HlTag::Symbol(SymbolKind::Struct) | 514 | SymbolKind::Struct |
541 | } else { | 515 | } else { |
542 | HlTag::Symbol(SymbolKind::Const) | 516 | SymbolKind::Const |
543 | } | 517 | } |
544 | .into(), | 518 | .into(), |
545 | } | 519 | } |
@@ -574,6 +548,11 @@ fn parents_match(mut node: NodeOrToken<SyntaxNode, SyntaxToken>, mut kinds: &[Sy | |||
574 | kinds.len() == 0 | 548 | kinds.len() == 0 |
575 | } | 549 | } |
576 | 550 | ||
551 | #[inline] | ||
552 | fn parent_matches<N: AstNode>(element: &SyntaxElement) -> bool { | ||
553 | element.parent().map_or(false, |it| N::can_cast(it.kind())) | ||
554 | } | ||
555 | |||
577 | fn is_child_of_impl(element: &SyntaxElement) -> bool { | 556 | fn is_child_of_impl(element: &SyntaxElement) -> bool { |
578 | match element.parent() { | 557 | match element.parent() { |
579 | Some(e) => e.kind() == IMPL, | 558 | Some(e) => e.kind() == IMPL, |
diff --git a/crates/ide/src/syntax_highlighting/tags.rs b/crates/ide/src/syntax_highlighting/tags.rs index e58392d67..a304b3250 100644 --- a/crates/ide/src/syntax_highlighting/tags.rs +++ b/crates/ide/src/syntax_highlighting/tags.rs | |||
@@ -40,28 +40,33 @@ pub enum HlTag { | |||
40 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] | 40 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] |
41 | #[repr(u8)] | 41 | #[repr(u8)] |
42 | pub enum HlMod { | 42 | pub enum HlMod { |
43 | /// Used for items in traits and impls. | ||
44 | Associated = 0, | ||
43 | /// Used to differentiate individual elements within attributes. | 45 | /// Used to differentiate individual elements within attributes. |
44 | Attribute = 0, | 46 | Attribute, |
47 | /// Callable item or value. | ||
48 | Callable, | ||
49 | /// Value that is being consumed in a function call | ||
50 | Consuming, | ||
45 | /// Used with keywords like `if` and `break`. | 51 | /// Used with keywords like `if` and `break`. |
46 | ControlFlow, | 52 | ControlFlow, |
47 | /// `foo` in `fn foo(x: i32)` is a definition, `foo` in `foo(90 + 2)` is | 53 | /// `foo` in `fn foo(x: i32)` is a definition, `foo` in `foo(90 + 2)` is |
48 | /// not. | 54 | /// not. |
49 | Definition, | 55 | Definition, |
56 | /// Doc-strings like this one. | ||
50 | Documentation, | 57 | Documentation, |
58 | /// Highlighting injection like rust code in doc strings or ra_fixture. | ||
51 | Injected, | 59 | Injected, |
52 | Mutable, | ||
53 | Consuming, | ||
54 | Callable, | ||
55 | /// Used for associated functions | ||
56 | Static, | ||
57 | /// Used for items in impls&traits. | ||
58 | Associated, | ||
59 | /// Used for intra doc links in doc injection. | 60 | /// Used for intra doc links in doc injection. |
60 | IntraDocLink, | 61 | IntraDocLink, |
62 | /// Mutable binding. | ||
63 | Mutable, | ||
64 | /// Used for associated functions. | ||
65 | Static, | ||
61 | /// Used for items in traits and trait impls. | 66 | /// Used for items in traits and trait impls. |
62 | Trait, | 67 | Trait, |
63 | 68 | // Keep this last! | |
64 | /// Keep this last! | 69 | /// Used for unsafe functions, mutable statics, union accesses and unsafe operations. |
65 | Unsafe, | 70 | Unsafe, |
66 | } | 71 | } |
67 | 72 | ||
@@ -169,17 +174,17 @@ impl fmt::Display for HlTag { | |||
169 | 174 | ||
170 | impl HlMod { | 175 | impl HlMod { |
171 | const ALL: &'static [HlMod; HlMod::Unsafe as u8 as usize + 1] = &[ | 176 | const ALL: &'static [HlMod; HlMod::Unsafe as u8 as usize + 1] = &[ |
177 | HlMod::Associated, | ||
172 | HlMod::Attribute, | 178 | HlMod::Attribute, |
179 | HlMod::Callable, | ||
180 | HlMod::Consuming, | ||
173 | HlMod::ControlFlow, | 181 | HlMod::ControlFlow, |
174 | HlMod::Definition, | 182 | HlMod::Definition, |
175 | HlMod::Documentation, | 183 | HlMod::Documentation, |
176 | HlMod::IntraDocLink, | ||
177 | HlMod::Injected, | 184 | HlMod::Injected, |
185 | HlMod::IntraDocLink, | ||
178 | HlMod::Mutable, | 186 | HlMod::Mutable, |
179 | HlMod::Consuming, | ||
180 | HlMod::Callable, | ||
181 | HlMod::Static, | 187 | HlMod::Static, |
182 | HlMod::Associated, | ||
183 | HlMod::Trait, | 188 | HlMod::Trait, |
184 | HlMod::Unsafe, | 189 | HlMod::Unsafe, |
185 | ]; | 190 | ]; |
@@ -229,6 +234,24 @@ impl From<HlTag> for Highlight { | |||
229 | } | 234 | } |
230 | } | 235 | } |
231 | 236 | ||
237 | impl From<HlOperator> for Highlight { | ||
238 | fn from(op: HlOperator) -> Highlight { | ||
239 | Highlight::new(HlTag::Operator(op)) | ||
240 | } | ||
241 | } | ||
242 | |||
243 | impl From<HlPunct> for Highlight { | ||
244 | fn from(punct: HlPunct) -> Highlight { | ||
245 | Highlight::new(HlTag::Punctuation(punct)) | ||
246 | } | ||
247 | } | ||
248 | |||
249 | impl From<SymbolKind> for Highlight { | ||
250 | fn from(sym: SymbolKind) -> Highlight { | ||
251 | Highlight::new(HlTag::Symbol(sym)) | ||
252 | } | ||
253 | } | ||
254 | |||
232 | impl Highlight { | 255 | impl Highlight { |
233 | pub(crate) fn new(tag: HlTag) -> Highlight { | 256 | pub(crate) fn new(tag: HlTag) -> Highlight { |
234 | Highlight { tag, mods: HlMods::default() } | 257 | Highlight { tag, mods: HlMods::default() } |
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html b/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html index 8cde3906c..a0ea1db34 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html | |||
@@ -42,17 +42,17 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
42 | <span class="keyword">struct</span> <span class="struct declaration">foo</span> <span class="brace">{</span><span class="brace">}</span> | 42 | <span class="keyword">struct</span> <span class="struct declaration">foo</span> <span class="brace">{</span><span class="brace">}</span> |
43 | 43 | ||
44 | <span class="keyword">impl</span> <span class="struct">foo</span> <span class="brace">{</span> | 44 | <span class="keyword">impl</span> <span class="struct">foo</span> <span class="brace">{</span> |
45 | <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration static associated">is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> | 45 | <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function associated declaration static">is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> |
46 | <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration associated">is_not_static</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> | 46 | <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function associated declaration">is_not_static</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> |
47 | <span class="brace">}</span> | 47 | <span class="brace">}</span> |
48 | 48 | ||
49 | <span class="keyword">trait</span> <span class="trait declaration">t</span> <span class="brace">{</span> | 49 | <span class="keyword">trait</span> <span class="trait declaration">t</span> <span class="brace">{</span> |
50 | <span class="keyword">fn</span> <span class="function declaration static associated trait">t_is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> | 50 | <span class="keyword">fn</span> <span class="function associated declaration static trait">t_is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> |
51 | <span class="keyword">fn</span> <span class="function declaration associated trait">t_is_not_static</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> | 51 | <span class="keyword">fn</span> <span class="function associated declaration trait">t_is_not_static</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> |
52 | <span class="brace">}</span> | 52 | <span class="brace">}</span> |
53 | 53 | ||
54 | <span class="keyword">impl</span> <span class="trait">t</span> <span class="keyword">for</span> <span class="struct">foo</span> <span class="brace">{</span> | 54 | <span class="keyword">impl</span> <span class="trait">t</span> <span class="keyword">for</span> <span class="struct">foo</span> <span class="brace">{</span> |
55 | <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration static associated trait">is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> | 55 | <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function associated declaration static trait">is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> |
56 | <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration associated trait">is_not_static</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> | 56 | <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function associated declaration trait">is_not_static</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> |
57 | <span class="brace">}</span> | 57 | <span class="brace">}</span> |
58 | </code></pre> \ No newline at end of file | 58 | </code></pre> \ No newline at end of file |
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html b/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html index 6ee6d85fb..638f42c2f 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html | |||
@@ -50,7 +50,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
50 | <span class="comment">// KILLER WHALE</span> | 50 | <span class="comment">// KILLER WHALE</span> |
51 | <span class="comment documentation">/// </span><span class="string_literal injected"> Ishmael."</span><span class="semicolon injected">;</span> | 51 | <span class="comment documentation">/// </span><span class="string_literal injected"> Ishmael."</span><span class="semicolon injected">;</span> |
52 | <span class="comment documentation">/// ```</span> | 52 | <span class="comment documentation">/// ```</span> |
53 | <span class="keyword">pub</span> <span class="keyword">const</span> <span class="constant declaration associated">bar</span><span class="colon">:</span> <span class="builtin_type">bool</span> <span class="operator">=</span> <span class="bool_literal">true</span><span class="semicolon">;</span> | 53 | <span class="keyword">pub</span> <span class="keyword">const</span> <span class="constant associated declaration">bar</span><span class="colon">:</span> <span class="builtin_type">bool</span> <span class="operator">=</span> <span class="bool_literal">true</span><span class="semicolon">;</span> |
54 | 54 | ||
55 | <span class="comment documentation">/// Constructs a new `Foo`.</span> | 55 | <span class="comment documentation">/// Constructs a new `Foo`.</span> |
56 | <span class="comment documentation">///</span> | 56 | <span class="comment documentation">///</span> |
@@ -60,7 +60,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
60 | <span class="comment documentation">/// #</span><span class="none injected"> </span><span class="attribute attribute injected">#</span><span class="attribute attribute injected">!</span><span class="attribute attribute injected">[</span><span class="function attribute injected">allow</span><span class="parenthesis attribute injected">(</span><span class="attribute attribute injected">unused_mut</span><span class="parenthesis attribute injected">)</span><span class="attribute attribute injected">]</span> | 60 | <span class="comment documentation">/// #</span><span class="none injected"> </span><span class="attribute attribute injected">#</span><span class="attribute attribute injected">!</span><span class="attribute attribute injected">[</span><span class="function attribute injected">allow</span><span class="parenthesis attribute injected">(</span><span class="attribute attribute injected">unused_mut</span><span class="parenthesis attribute injected">)</span><span class="attribute attribute injected">]</span> |
61 | <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="none injected"> </span><span class="keyword injected">mut</span><span class="none injected"> </span><span class="variable declaration injected mutable">foo</span><span class="colon injected">:</span><span class="none injected"> </span><span class="struct injected">Foo</span><span class="none injected"> </span><span class="operator injected">=</span><span class="none injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="function injected">new</span><span class="parenthesis injected">(</span><span class="parenthesis injected">)</span><span class="semicolon injected">;</span> | 61 | <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="none injected"> </span><span class="keyword injected">mut</span><span class="none injected"> </span><span class="variable declaration injected mutable">foo</span><span class="colon injected">:</span><span class="none injected"> </span><span class="struct injected">Foo</span><span class="none injected"> </span><span class="operator injected">=</span><span class="none injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="function injected">new</span><span class="parenthesis injected">(</span><span class="parenthesis injected">)</span><span class="semicolon injected">;</span> |
62 | <span class="comment documentation">/// ```</span> | 62 | <span class="comment documentation">/// ```</span> |
63 | <span class="keyword">pub</span> <span class="keyword">const</span> <span class="keyword">fn</span> <span class="function declaration static associated">new</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="struct">Foo</span> <span class="brace">{</span> | 63 | <span class="keyword">pub</span> <span class="keyword">const</span> <span class="keyword">fn</span> <span class="function associated declaration static">new</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="struct">Foo</span> <span class="brace">{</span> |
64 | <span class="struct">Foo</span> <span class="brace">{</span> <span class="field">bar</span><span class="colon">:</span> <span class="bool_literal">true</span> <span class="brace">}</span> | 64 | <span class="struct">Foo</span> <span class="brace">{</span> <span class="field">bar</span><span class="colon">:</span> <span class="bool_literal">true</span> <span class="brace">}</span> |
65 | <span class="brace">}</span> | 65 | <span class="brace">}</span> |
66 | 66 | ||
@@ -94,15 +94,15 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
94 | <span class="comment documentation">/// ```sh</span> | 94 | <span class="comment documentation">/// ```sh</span> |
95 | <span class="comment documentation">/// echo 1</span> | 95 | <span class="comment documentation">/// echo 1</span> |
96 | <span class="comment documentation">/// ```</span> | 96 | <span class="comment documentation">/// ```</span> |
97 | <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration associated">foo</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="builtin_type">bool</span> <span class="brace">{</span> | 97 | <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function associated declaration">foo</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="builtin_type">bool</span> <span class="brace">{</span> |
98 | <span class="bool_literal">true</span> | 98 | <span class="bool_literal">true</span> |
99 | <span class="brace">}</span> | 99 | <span class="brace">}</span> |
100 | <span class="brace">}</span> | 100 | <span class="brace">}</span> |
101 | 101 | ||
102 | <span class="comment documentation">/// </span><span class="struct documentation intra_doc_link injected">[`Foo`](Foo)</span><span class="comment documentation"> is a struct</span> | 102 | <span class="comment documentation">/// </span><span class="struct documentation injected intra_doc_link">[`Foo`](Foo)</span><span class="comment documentation"> is a struct</span> |
103 | <span class="comment documentation">/// This function is > </span><span class="function documentation intra_doc_link injected">[`all_the_links`](all_the_links)</span><span class="comment documentation"> <</span> | 103 | <span class="comment documentation">/// This function is > </span><span class="function documentation injected intra_doc_link">[`all_the_links`](all_the_links)</span><span class="comment documentation"> <</span> |
104 | <span class="comment documentation">/// [`noop`](noop) is a macro below</span> | 104 | <span class="comment documentation">/// [`noop`](noop) is a macro below</span> |
105 | <span class="comment documentation">/// </span><span class="struct documentation intra_doc_link injected">[`Item`]</span><span class="comment documentation"> is a struct in the module </span><span class="module documentation intra_doc_link injected">[`module`]</span> | 105 | <span class="comment documentation">/// </span><span class="struct documentation injected intra_doc_link">[`Item`]</span><span class="comment documentation"> is a struct in the module </span><span class="module documentation injected intra_doc_link">[`module`]</span> |
106 | <span class="comment documentation">///</span> | 106 | <span class="comment documentation">///</span> |
107 | <span class="comment documentation">/// [`Item`]: module::Item</span> | 107 | <span class="comment documentation">/// [`Item`]: module::Item</span> |
108 | <span class="comment documentation">/// [mix_and_match]: ThisShouldntResolve</span> | 108 | <span class="comment documentation">/// [mix_and_match]: ThisShouldntResolve</span> |
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html b/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html index 7c6694a27..6202a03ce 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html | |||
@@ -42,7 +42,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
42 | <span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> | 42 | <span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> |
43 | <span class="function">fixture</span><span class="parenthesis">(</span><span class="string_literal">r#"</span> | 43 | <span class="function">fixture</span><span class="parenthesis">(</span><span class="string_literal">r#"</span> |
44 | <span class="keyword">trait</span> <span class="trait declaration">Foo</span> <span class="brace">{</span> | 44 | <span class="keyword">trait</span> <span class="trait declaration">Foo</span> <span class="brace">{</span> |
45 | <span class="keyword">fn</span> <span class="function declaration static associated trait">foo</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> | 45 | <span class="keyword">fn</span> <span class="function associated declaration static trait">foo</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> |
46 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"2 + 2 = {}"</span><span class="comma">,</span> <span class="numeric_literal">4</span><span class="parenthesis">)</span><span class="semicolon">;</span> | 46 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"2 + 2 = {}"</span><span class="comma">,</span> <span class="numeric_literal">4</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
47 | <span class="brace">}</span> | 47 | <span class="brace">}</span> |
48 | <span class="brace">}</span><span class="string_literal">"#</span> | 48 | <span class="brace">}</span><span class="string_literal">"#</span> |
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html b/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html index 72910421d..68165bdbf 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html | |||
@@ -47,7 +47,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
47 | <span class="keyword">struct</span> <span class="struct declaration">HasUnsafeFn</span><span class="semicolon">;</span> | 47 | <span class="keyword">struct</span> <span class="struct declaration">HasUnsafeFn</span><span class="semicolon">;</span> |
48 | 48 | ||
49 | <span class="keyword">impl</span> <span class="struct">HasUnsafeFn</span> <span class="brace">{</span> | 49 | <span class="keyword">impl</span> <span class="struct">HasUnsafeFn</span> <span class="brace">{</span> |
50 | <span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="function declaration associated unsafe">unsafe_method</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> | 50 | <span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="function associated declaration unsafe">unsafe_method</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> |
51 | <span class="brace">}</span> | 51 | <span class="brace">}</span> |
52 | 52 | ||
53 | <span class="keyword">struct</span> <span class="struct declaration">TypeForStaticMut</span> <span class="brace">{</span> | 53 | <span class="keyword">struct</span> <span class="struct declaration">TypeForStaticMut</span> <span class="brace">{</span> |
@@ -62,11 +62,11 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
62 | <span class="brace">}</span> | 62 | <span class="brace">}</span> |
63 | 63 | ||
64 | <span class="keyword">trait</span> <span class="trait declaration">DoTheAutoref</span> <span class="brace">{</span> | 64 | <span class="keyword">trait</span> <span class="trait declaration">DoTheAutoref</span> <span class="brace">{</span> |
65 | <span class="keyword">fn</span> <span class="function declaration associated trait">calls_autoref</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span><span class="semicolon">;</span> | 65 | <span class="keyword">fn</span> <span class="function associated declaration trait">calls_autoref</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
66 | <span class="brace">}</span> | 66 | <span class="brace">}</span> |
67 | 67 | ||
68 | <span class="keyword">impl</span> <span class="trait">DoTheAutoref</span> <span class="keyword">for</span> <span class="builtin_type">u16</span> <span class="brace">{</span> | 68 | <span class="keyword">impl</span> <span class="trait">DoTheAutoref</span> <span class="keyword">for</span> <span class="builtin_type">u16</span> <span class="brace">{</span> |
69 | <span class="keyword">fn</span> <span class="function declaration associated trait">calls_autoref</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> | 69 | <span class="keyword">fn</span> <span class="function associated declaration trait">calls_autoref</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> |
70 | <span class="brace">}</span> | 70 | <span class="brace">}</span> |
71 | 71 | ||
72 | <span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> | 72 | <span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> |
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlighting.html b/crates/ide/src/syntax_highlighting/test_data/highlighting.html index c43bcb691..df4192194 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlighting.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlighting.html | |||
@@ -67,25 +67,25 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
67 | <span class="brace">}</span> | 67 | <span class="brace">}</span> |
68 | 68 | ||
69 | <span class="keyword">trait</span> <span class="trait declaration">Bar</span> <span class="brace">{</span> | 69 | <span class="keyword">trait</span> <span class="trait declaration">Bar</span> <span class="brace">{</span> |
70 | <span class="keyword">fn</span> <span class="function declaration associated trait">bar</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="builtin_type">i32</span><span class="semicolon">;</span> | 70 | <span class="keyword">fn</span> <span class="function associated declaration trait">bar</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="builtin_type">i32</span><span class="semicolon">;</span> |
71 | <span class="brace">}</span> | 71 | <span class="brace">}</span> |
72 | 72 | ||
73 | <span class="keyword">impl</span> <span class="trait">Bar</span> <span class="keyword">for</span> <span class="struct">Foo</span> <span class="brace">{</span> | 73 | <span class="keyword">impl</span> <span class="trait">Bar</span> <span class="keyword">for</span> <span class="struct">Foo</span> <span class="brace">{</span> |
74 | <span class="keyword">fn</span> <span class="function declaration associated trait">bar</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="builtin_type">i32</span> <span class="brace">{</span> | 74 | <span class="keyword">fn</span> <span class="function associated declaration trait">bar</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="builtin_type">i32</span> <span class="brace">{</span> |
75 | <span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span> | 75 | <span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span> |
76 | <span class="brace">}</span> | 76 | <span class="brace">}</span> |
77 | <span class="brace">}</span> | 77 | <span class="brace">}</span> |
78 | 78 | ||
79 | <span class="keyword">impl</span> <span class="struct">Foo</span> <span class="brace">{</span> | 79 | <span class="keyword">impl</span> <span class="struct">Foo</span> <span class="brace">{</span> |
80 | <span class="keyword">fn</span> <span class="function declaration associated">baz</span><span class="parenthesis">(</span><span class="keyword">mut</span> <span class="self_keyword declaration mutable">self</span><span class="comma">,</span> <span class="value_param declaration">f</span><span class="colon">:</span> <span class="struct">Foo</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="builtin_type">i32</span> <span class="brace">{</span> | 80 | <span class="keyword">fn</span> <span class="function associated declaration">baz</span><span class="parenthesis">(</span><span class="keyword">mut</span> <span class="self_keyword declaration mutable">self</span><span class="comma">,</span> <span class="value_param declaration">f</span><span class="colon">:</span> <span class="struct">Foo</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="builtin_type">i32</span> <span class="brace">{</span> |
81 | <span class="value_param">f</span><span class="operator">.</span><span class="function consuming associated">baz</span><span class="parenthesis">(</span><span class="self_keyword mutable consuming">self</span><span class="parenthesis">)</span> | 81 | <span class="value_param">f</span><span class="operator">.</span><span class="function associated consuming">baz</span><span class="parenthesis">(</span><span class="self_keyword consuming mutable">self</span><span class="parenthesis">)</span> |
82 | <span class="brace">}</span> | 82 | <span class="brace">}</span> |
83 | 83 | ||
84 | <span class="keyword">fn</span> <span class="function declaration associated">qux</span><span class="parenthesis">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword declaration mutable">self</span><span class="parenthesis">)</span> <span class="brace">{</span> | 84 | <span class="keyword">fn</span> <span class="function associated declaration mutable">qux</span><span class="parenthesis">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword declaration mutable">self</span><span class="parenthesis">)</span> <span class="brace">{</span> |
85 | <span class="self_keyword mutable">self</span><span class="operator">.</span><span class="field">x</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="semicolon">;</span> | 85 | <span class="self_keyword mutable">self</span><span class="operator">.</span><span class="field">x</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="semicolon">;</span> |
86 | <span class="brace">}</span> | 86 | <span class="brace">}</span> |
87 | 87 | ||
88 | <span class="keyword">fn</span> <span class="function declaration associated">quop</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="builtin_type">i32</span> <span class="brace">{</span> | 88 | <span class="keyword">fn</span> <span class="function associated declaration">quop</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="builtin_type">i32</span> <span class="brace">{</span> |
89 | <span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span> | 89 | <span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span> |
90 | <span class="brace">}</span> | 90 | <span class="brace">}</span> |
91 | <span class="brace">}</span> | 91 | <span class="brace">}</span> |
@@ -96,15 +96,15 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
96 | <span class="brace">}</span> | 96 | <span class="brace">}</span> |
97 | 97 | ||
98 | <span class="keyword">impl</span> <span class="struct">FooCopy</span> <span class="brace">{</span> | 98 | <span class="keyword">impl</span> <span class="struct">FooCopy</span> <span class="brace">{</span> |
99 | <span class="keyword">fn</span> <span class="function declaration associated">baz</span><span class="parenthesis">(</span><span class="self_keyword declaration">self</span><span class="comma">,</span> <span class="value_param declaration">f</span><span class="colon">:</span> <span class="struct">FooCopy</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="builtin_type">u32</span> <span class="brace">{</span> | 99 | <span class="keyword">fn</span> <span class="function associated declaration">baz</span><span class="parenthesis">(</span><span class="self_keyword declaration">self</span><span class="comma">,</span> <span class="value_param declaration">f</span><span class="colon">:</span> <span class="struct">FooCopy</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="builtin_type">u32</span> <span class="brace">{</span> |
100 | <span class="value_param">f</span><span class="operator">.</span><span class="function associated">baz</span><span class="parenthesis">(</span><span class="self_keyword">self</span><span class="parenthesis">)</span> | 100 | <span class="value_param">f</span><span class="operator">.</span><span class="function associated">baz</span><span class="parenthesis">(</span><span class="self_keyword">self</span><span class="parenthesis">)</span> |
101 | <span class="brace">}</span> | 101 | <span class="brace">}</span> |
102 | 102 | ||
103 | <span class="keyword">fn</span> <span class="function declaration associated">qux</span><span class="parenthesis">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword declaration mutable">self</span><span class="parenthesis">)</span> <span class="brace">{</span> | 103 | <span class="keyword">fn</span> <span class="function associated declaration mutable">qux</span><span class="parenthesis">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword declaration mutable">self</span><span class="parenthesis">)</span> <span class="brace">{</span> |
104 | <span class="self_keyword mutable">self</span><span class="operator">.</span><span class="field">x</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="semicolon">;</span> | 104 | <span class="self_keyword mutable">self</span><span class="operator">.</span><span class="field">x</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="semicolon">;</span> |
105 | <span class="brace">}</span> | 105 | <span class="brace">}</span> |
106 | 106 | ||
107 | <span class="keyword">fn</span> <span class="function declaration associated">quop</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="builtin_type">u32</span> <span class="brace">{</span> | 107 | <span class="keyword">fn</span> <span class="function associated declaration">quop</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="builtin_type">u32</span> <span class="brace">{</span> |
108 | <span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span> | 108 | <span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span> |
109 | <span class="brace">}</span> | 109 | <span class="brace">}</span> |
110 | <span class="brace">}</span> | 110 | <span class="brace">}</span> |
@@ -128,7 +128,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
128 | <span class="brace">}</span> | 128 | <span class="brace">}</span> |
129 | 129 | ||
130 | <span class="keyword">use</span> <span class="module">ops</span><span class="operator">::</span><span class="trait">Fn</span><span class="semicolon">;</span> | 130 | <span class="keyword">use</span> <span class="module">ops</span><span class="operator">::</span><span class="trait">Fn</span><span class="semicolon">;</span> |
131 | <span class="keyword">fn</span> <span class="function declaration">baz</span><span class="angle"><</span><span class="type_param declaration">F</span><span class="colon">:</span> <span class="trait">Fn</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="angle">></span><span class="parenthesis">(</span><span class="value_param declaration callable">f</span><span class="colon">:</span> <span class="type_param">F</span><span class="parenthesis">)</span> <span class="brace">{</span> | 131 | <span class="keyword">fn</span> <span class="function declaration">baz</span><span class="angle"><</span><span class="type_param declaration">F</span><span class="colon">:</span> <span class="trait">Fn</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="angle">></span><span class="parenthesis">(</span><span class="value_param callable declaration">f</span><span class="colon">:</span> <span class="type_param">F</span><span class="parenthesis">)</span> <span class="brace">{</span> |
132 | <span class="value_param callable">f</span><span class="parenthesis">(</span><span class="parenthesis">)</span> | 132 | <span class="value_param callable">f</span><span class="parenthesis">(</span><span class="parenthesis">)</span> |
133 | <span class="brace">}</span> | 133 | <span class="brace">}</span> |
134 | 134 | ||
@@ -199,16 +199,16 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
199 | <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">foo</span> <span class="operator">=</span> <span class="struct">Foo</span> <span class="brace">{</span> <span class="field">x</span><span class="comma">,</span> <span class="field">y</span><span class="colon">:</span> <span class="variable mutable">x</span> <span class="brace">}</span><span class="semicolon">;</span> | 199 | <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">foo</span> <span class="operator">=</span> <span class="struct">Foo</span> <span class="brace">{</span> <span class="field">x</span><span class="comma">,</span> <span class="field">y</span><span class="colon">:</span> <span class="variable mutable">x</span> <span class="brace">}</span><span class="semicolon">;</span> |
200 | <span class="keyword">let</span> <span class="variable declaration">foo2</span> <span class="operator">=</span> <span class="struct">Foo</span> <span class="brace">{</span> <span class="field">x</span><span class="comma">,</span> <span class="field">y</span><span class="colon">:</span> <span class="variable mutable">x</span> <span class="brace">}</span><span class="semicolon">;</span> | 200 | <span class="keyword">let</span> <span class="variable declaration">foo2</span> <span class="operator">=</span> <span class="struct">Foo</span> <span class="brace">{</span> <span class="field">x</span><span class="comma">,</span> <span class="field">y</span><span class="colon">:</span> <span class="variable mutable">x</span> <span class="brace">}</span><span class="semicolon">;</span> |
201 | <span class="variable mutable">foo</span><span class="operator">.</span><span class="function associated">quop</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> | 201 | <span class="variable mutable">foo</span><span class="operator">.</span><span class="function associated">quop</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
202 | <span class="variable mutable">foo</span><span class="operator">.</span><span class="function mutable associated">qux</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> | 202 | <span class="variable mutable">foo</span><span class="operator">.</span><span class="function associated mutable">qux</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
203 | <span class="variable mutable">foo</span><span class="operator">.</span><span class="function consuming associated">baz</span><span class="parenthesis">(</span><span class="variable consuming">foo2</span><span class="parenthesis">)</span><span class="semicolon">;</span> | 203 | <span class="variable mutable">foo</span><span class="operator">.</span><span class="function associated consuming">baz</span><span class="parenthesis">(</span><span class="variable consuming">foo2</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
204 | 204 | ||
205 | <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">copy</span> <span class="operator">=</span> <span class="struct">FooCopy</span> <span class="brace">{</span> <span class="field">x</span> <span class="brace">}</span><span class="semicolon">;</span> | 205 | <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">copy</span> <span class="operator">=</span> <span class="struct">FooCopy</span> <span class="brace">{</span> <span class="field">x</span> <span class="brace">}</span><span class="semicolon">;</span> |
206 | <span class="variable mutable">copy</span><span class="operator">.</span><span class="function associated">quop</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> | 206 | <span class="variable mutable">copy</span><span class="operator">.</span><span class="function associated">quop</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
207 | <span class="variable mutable">copy</span><span class="operator">.</span><span class="function mutable associated">qux</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> | 207 | <span class="variable mutable">copy</span><span class="operator">.</span><span class="function associated mutable">qux</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
208 | <span class="variable mutable">copy</span><span class="operator">.</span><span class="function associated">baz</span><span class="parenthesis">(</span><span class="variable mutable">copy</span><span class="parenthesis">)</span><span class="semicolon">;</span> | 208 | <span class="variable mutable">copy</span><span class="operator">.</span><span class="function associated">baz</span><span class="parenthesis">(</span><span class="variable mutable">copy</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
209 | 209 | ||
210 | <span class="keyword">let</span> <span class="variable declaration callable">a</span> <span class="operator">=</span> <span class="punctuation">|</span><span class="value_param declaration">x</span><span class="punctuation">|</span> <span class="value_param">x</span><span class="semicolon">;</span> | 210 | <span class="keyword">let</span> <span class="variable callable declaration">a</span> <span class="operator">=</span> <span class="punctuation">|</span><span class="value_param declaration">x</span><span class="punctuation">|</span> <span class="value_param">x</span><span class="semicolon">;</span> |
211 | <span class="keyword">let</span> <span class="variable declaration callable">bar</span> <span class="operator">=</span> <span class="struct">Foo</span><span class="operator">::</span><span class="function associated">baz</span><span class="semicolon">;</span> | 211 | <span class="keyword">let</span> <span class="variable callable declaration">bar</span> <span class="operator">=</span> <span class="struct">Foo</span><span class="operator">::</span><span class="function associated">baz</span><span class="semicolon">;</span> |
212 | 212 | ||
213 | <span class="keyword">let</span> <span class="variable declaration">baz</span> <span class="operator">=</span> <span class="numeric_literal">-</span><span class="numeric_literal">42</span><span class="semicolon">;</span> | 213 | <span class="keyword">let</span> <span class="variable declaration">baz</span> <span class="operator">=</span> <span class="numeric_literal">-</span><span class="numeric_literal">42</span><span class="semicolon">;</span> |
214 | <span class="keyword">let</span> <span class="variable declaration">baz</span> <span class="operator">=</span> <span class="operator">-</span><span class="variable">baz</span><span class="semicolon">;</span> | 214 | <span class="keyword">let</span> <span class="variable declaration">baz</span> <span class="operator">=</span> <span class="operator">-</span><span class="variable">baz</span><span class="semicolon">;</span> |
@@ -228,7 +228,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
228 | <span class="keyword">use</span> <span class="enum">Option</span><span class="operator">::</span><span class="punctuation">*</span><span class="semicolon">;</span> | 228 | <span class="keyword">use</span> <span class="enum">Option</span><span class="operator">::</span><span class="punctuation">*</span><span class="semicolon">;</span> |
229 | 229 | ||
230 | <span class="keyword">impl</span><span class="angle"><</span><span class="type_param declaration">T</span><span class="angle">></span> <span class="enum">Option</span><span class="angle"><</span><span class="type_param">T</span><span class="angle">></span> <span class="brace">{</span> | 230 | <span class="keyword">impl</span><span class="angle"><</span><span class="type_param declaration">T</span><span class="angle">></span> <span class="enum">Option</span><span class="angle"><</span><span class="type_param">T</span><span class="angle">></span> <span class="brace">{</span> |
231 | <span class="keyword">fn</span> <span class="function declaration associated">and</span><span class="angle"><</span><span class="type_param declaration">U</span><span class="angle">></span><span class="parenthesis">(</span><span class="self_keyword declaration">self</span><span class="comma">,</span> <span class="value_param declaration">other</span><span class="colon">:</span> <span class="enum">Option</span><span class="angle"><</span><span class="type_param">U</span><span class="angle">></span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="enum">Option</span><span class="angle"><</span><span class="parenthesis">(</span><span class="type_param">T</span><span class="comma">,</span> <span class="type_param">U</span><span class="parenthesis">)</span><span class="angle">></span> <span class="brace">{</span> | 231 | <span class="keyword">fn</span> <span class="function associated declaration">and</span><span class="angle"><</span><span class="type_param declaration">U</span><span class="angle">></span><span class="parenthesis">(</span><span class="self_keyword declaration">self</span><span class="comma">,</span> <span class="value_param declaration">other</span><span class="colon">:</span> <span class="enum">Option</span><span class="angle"><</span><span class="type_param">U</span><span class="angle">></span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="enum">Option</span><span class="angle"><</span><span class="parenthesis">(</span><span class="type_param">T</span><span class="comma">,</span> <span class="type_param">U</span><span class="parenthesis">)</span><span class="angle">></span> <span class="brace">{</span> |
232 | <span class="keyword control">match</span> <span class="value_param">other</span> <span class="brace">{</span> | 232 | <span class="keyword control">match</span> <span class="value_param">other</span> <span class="brace">{</span> |
233 | <span class="enum_variant">None</span> <span class="operator">=></span> <span class="macro">unimplemented!</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="comma">,</span> | 233 | <span class="enum_variant">None</span> <span class="operator">=></span> <span class="macro">unimplemented!</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="comma">,</span> |
234 | <span class="variable declaration">Nope</span> <span class="operator">=></span> <span class="variable">Nope</span><span class="comma">,</span> | 234 | <span class="variable declaration">Nope</span> <span class="operator">=></span> <span class="variable">Nope</span><span class="comma">,</span> |
diff --git a/crates/ide_assists/src/ast_transform.rs b/crates/ide_assists/src/ast_transform.rs index 4a3ed7783..e5ae718c9 100644 --- a/crates/ide_assists/src/ast_transform.rs +++ b/crates/ide_assists/src/ast_transform.rs | |||
@@ -3,20 +3,27 @@ use hir::{HirDisplay, PathResolution, SemanticsScope}; | |||
3 | use ide_db::helpers::mod_path_to_ast; | 3 | use ide_db::helpers::mod_path_to_ast; |
4 | use rustc_hash::FxHashMap; | 4 | use rustc_hash::FxHashMap; |
5 | use syntax::{ | 5 | use syntax::{ |
6 | algo::SyntaxRewriter, | ||
7 | ast::{self, AstNode}, | 6 | ast::{self, AstNode}, |
8 | SyntaxNode, | 7 | ted, SyntaxNode, |
9 | }; | 8 | }; |
10 | 9 | ||
11 | pub fn apply<'a, N: AstNode>(transformer: &dyn AstTransform<'a>, node: N) -> N { | 10 | pub fn apply<'a, N: AstNode>(transformer: &dyn AstTransform<'a>, node: &N) { |
12 | SyntaxRewriter::from_fn(|element| match element { | 11 | let mut skip_to = None; |
13 | syntax::SyntaxElement::Node(n) => { | 12 | for event in node.syntax().preorder() { |
14 | let replacement = transformer.get_substitution(&n, transformer)?; | 13 | match event { |
15 | Some(replacement.into()) | 14 | syntax::WalkEvent::Enter(node) if skip_to.is_none() => { |
15 | skip_to = transformer.get_substitution(&node, transformer).zip(Some(node)); | ||
16 | } | ||
17 | syntax::WalkEvent::Enter(_) => (), | ||
18 | syntax::WalkEvent::Leave(node) => match &skip_to { | ||
19 | Some((replacement, skip_target)) if *skip_target == node => { | ||
20 | ted::replace(node, replacement.clone_for_update()); | ||
21 | skip_to.take(); | ||
22 | } | ||
23 | _ => (), | ||
24 | }, | ||
16 | } | 25 | } |
17 | _ => None, | 26 | } |
18 | }) | ||
19 | .rewrite_ast(&node) | ||
20 | } | 27 | } |
21 | 28 | ||
22 | /// `AstTransform` helps with applying bulk transformations to syntax nodes. | 29 | /// `AstTransform` helps with applying bulk transformations to syntax nodes. |
@@ -191,11 +198,9 @@ impl<'a> AstTransform<'a> for QualifyPaths<'a> { | |||
191 | let found_path = from.find_use_path(self.source_scope.db.upcast(), def)?; | 198 | let found_path = from.find_use_path(self.source_scope.db.upcast(), def)?; |
192 | let mut path = mod_path_to_ast(&found_path); | 199 | let mut path = mod_path_to_ast(&found_path); |
193 | 200 | ||
194 | let type_args = p | 201 | let type_args = p.segment().and_then(|s| s.generic_arg_list()); |
195 | .segment() | ||
196 | .and_then(|s| s.generic_arg_list()) | ||
197 | .map(|arg_list| apply(recur, arg_list)); | ||
198 | if let Some(type_args) = type_args { | 202 | if let Some(type_args) = type_args { |
203 | apply(recur, &type_args); | ||
199 | let last_segment = path.segment().unwrap(); | 204 | let last_segment = path.segment().unwrap(); |
200 | path = path.with_segment(last_segment.with_generic_args(type_args)) | 205 | path = path.with_segment(last_segment.with_generic_args(type_args)) |
201 | } | 206 | } |
diff --git a/crates/ide_assists/src/handlers/auto_import.rs b/crates/ide_assists/src/handlers/auto_import.rs index 49aa70f74..a454a2af3 100644 --- a/crates/ide_assists/src/handlers/auto_import.rs +++ b/crates/ide_assists/src/handlers/auto_import.rs | |||
@@ -93,7 +93,7 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> | |||
93 | 93 | ||
94 | let range = ctx.sema.original_range(&syntax_under_caret).range; | 94 | let range = ctx.sema.original_range(&syntax_under_caret).range; |
95 | let group_label = group_label(import_assets.import_candidate()); | 95 | let group_label = group_label(import_assets.import_candidate()); |
96 | let scope = ImportScope::find_insert_use_container(&syntax_under_caret, &ctx.sema)?; | 96 | let scope = ImportScope::find_insert_use_container_with_macros(&syntax_under_caret, &ctx.sema)?; |
97 | for import in proposed_imports { | 97 | for import in proposed_imports { |
98 | acc.add_group( | 98 | acc.add_group( |
99 | &group_label, | 99 | &group_label, |
@@ -101,9 +101,11 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> | |||
101 | format!("Import `{}`", import.import_path), | 101 | format!("Import `{}`", import.import_path), |
102 | range, | 102 | range, |
103 | |builder| { | 103 | |builder| { |
104 | let rewriter = | 104 | let scope = match scope.clone() { |
105 | insert_use(&scope, mod_path_to_ast(&import.import_path), ctx.config.insert_use); | 105 | ImportScope::File(it) => ImportScope::File(builder.make_ast_mut(it)), |
106 | builder.rewrite(rewriter); | 106 | ImportScope::Module(it) => ImportScope::Module(builder.make_ast_mut(it)), |
107 | }; | ||
108 | insert_use(&scope, mod_path_to_ast(&import.import_path), ctx.config.insert_use); | ||
107 | }, | 109 | }, |
108 | ); | 110 | ); |
109 | } | 111 | } |
diff --git a/crates/ide_assists/src/handlers/convert_tuple_struct_to_named_struct.rs b/crates/ide_assists/src/handlers/convert_tuple_struct_to_named_struct.rs new file mode 100644 index 000000000..b5b5ada5e --- /dev/null +++ b/crates/ide_assists/src/handlers/convert_tuple_struct_to_named_struct.rs | |||
@@ -0,0 +1,516 @@ | |||
1 | use ide_db::defs::{Definition, NameRefClass}; | ||
2 | use syntax::{ | ||
3 | ast::{self, AstNode, GenericParamsOwner, VisibilityOwner}, | ||
4 | match_ast, SyntaxNode, | ||
5 | }; | ||
6 | |||
7 | use crate::{assist_context::AssistBuilder, AssistContext, AssistId, AssistKind, Assists}; | ||
8 | |||
9 | // Assist: convert_tuple_struct_to_named_struct | ||
10 | // | ||
11 | // Converts tuple struct to struct with named fields. | ||
12 | // | ||
13 | // ``` | ||
14 | // struct Point$0(f32, f32); | ||
15 | // | ||
16 | // impl Point { | ||
17 | // pub fn new(x: f32, y: f32) -> Self { | ||
18 | // Point(x, y) | ||
19 | // } | ||
20 | // | ||
21 | // pub fn x(&self) -> f32 { | ||
22 | // self.0 | ||
23 | // } | ||
24 | // | ||
25 | // pub fn y(&self) -> f32 { | ||
26 | // self.1 | ||
27 | // } | ||
28 | // } | ||
29 | // ``` | ||
30 | // -> | ||
31 | // ``` | ||
32 | // struct Point { field1: f32, field2: f32 } | ||
33 | // | ||
34 | // impl Point { | ||
35 | // pub fn new(x: f32, y: f32) -> Self { | ||
36 | // Point { field1: x, field2: y } | ||
37 | // } | ||
38 | // | ||
39 | // pub fn x(&self) -> f32 { | ||
40 | // self.field1 | ||
41 | // } | ||
42 | // | ||
43 | // pub fn y(&self) -> f32 { | ||
44 | // self.field2 | ||
45 | // } | ||
46 | // } | ||
47 | // ``` | ||
48 | pub(crate) fn convert_tuple_struct_to_named_struct( | ||
49 | acc: &mut Assists, | ||
50 | ctx: &AssistContext, | ||
51 | ) -> Option<()> { | ||
52 | let strukt = ctx.find_node_at_offset::<ast::Struct>()?; | ||
53 | let tuple_fields = match strukt.field_list()? { | ||
54 | ast::FieldList::TupleFieldList(it) => it, | ||
55 | ast::FieldList::RecordFieldList(_) => return None, | ||
56 | }; | ||
57 | let strukt_def = ctx.sema.to_def(&strukt)?; | ||
58 | |||
59 | let target = strukt.syntax().text_range(); | ||
60 | acc.add( | ||
61 | AssistId("convert_tuple_struct_to_named_struct", AssistKind::RefactorRewrite), | ||
62 | "Convert to named struct", | ||
63 | target, | ||
64 | |edit| { | ||
65 | let names = generate_names(tuple_fields.fields()); | ||
66 | edit_field_references(ctx, edit, tuple_fields.fields(), &names); | ||
67 | edit_struct_references(ctx, edit, strukt_def, &names); | ||
68 | edit_struct_def(ctx, edit, &strukt, tuple_fields, names); | ||
69 | }, | ||
70 | ) | ||
71 | } | ||
72 | |||
73 | fn edit_struct_def( | ||
74 | ctx: &AssistContext, | ||
75 | edit: &mut AssistBuilder, | ||
76 | strukt: &ast::Struct, | ||
77 | tuple_fields: ast::TupleFieldList, | ||
78 | names: Vec<ast::Name>, | ||
79 | ) { | ||
80 | let record_fields = tuple_fields | ||
81 | .fields() | ||
82 | .zip(names) | ||
83 | .filter_map(|(f, name)| Some(ast::make::record_field(f.visibility(), name, f.ty()?))); | ||
84 | let record_fields = ast::make::record_field_list(record_fields); | ||
85 | let tuple_fields_text_range = tuple_fields.syntax().text_range(); | ||
86 | |||
87 | edit.edit_file(ctx.frange.file_id); | ||
88 | |||
89 | if let Some(w) = strukt.where_clause() { | ||
90 | edit.delete(w.syntax().text_range()); | ||
91 | edit.insert(tuple_fields_text_range.start(), ast::make::tokens::single_newline().text()); | ||
92 | edit.insert(tuple_fields_text_range.start(), w.syntax().text()); | ||
93 | edit.insert(tuple_fields_text_range.start(), ","); | ||
94 | edit.insert(tuple_fields_text_range.start(), ast::make::tokens::single_newline().text()); | ||
95 | } else { | ||
96 | edit.insert(tuple_fields_text_range.start(), ast::make::tokens::single_space().text()); | ||
97 | } | ||
98 | |||
99 | edit.replace(tuple_fields_text_range, record_fields.to_string()); | ||
100 | strukt.semicolon_token().map(|t| edit.delete(t.text_range())); | ||
101 | } | ||
102 | |||
103 | fn edit_struct_references( | ||
104 | ctx: &AssistContext, | ||
105 | edit: &mut AssistBuilder, | ||
106 | strukt: hir::Struct, | ||
107 | names: &[ast::Name], | ||
108 | ) { | ||
109 | let strukt_def = Definition::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Struct(strukt))); | ||
110 | let usages = strukt_def.usages(&ctx.sema).include_self_kw_refs(true).all(); | ||
111 | |||
112 | let edit_node = |edit: &mut AssistBuilder, node: SyntaxNode| -> Option<()> { | ||
113 | match_ast! { | ||
114 | match node { | ||
115 | ast::TupleStructPat(tuple_struct_pat) => { | ||
116 | edit.replace( | ||
117 | tuple_struct_pat.syntax().text_range(), | ||
118 | ast::make::record_pat_with_fields( | ||
119 | tuple_struct_pat.path()?, | ||
120 | ast::make::record_pat_field_list(tuple_struct_pat.fields().zip(names).map( | ||
121 | |(pat, name)| { | ||
122 | ast::make::record_pat_field( | ||
123 | ast::make::name_ref(&name.to_string()), | ||
124 | pat, | ||
125 | ) | ||
126 | }, | ||
127 | )), | ||
128 | ) | ||
129 | .to_string(), | ||
130 | ); | ||
131 | }, | ||
132 | // for tuple struct creations like Foo(42) | ||
133 | ast::CallExpr(call_expr) => { | ||
134 | let path = call_expr.syntax().descendants().find_map(ast::PathExpr::cast).and_then(|expr| expr.path())?; | ||
135 | |||
136 | // this also includes method calls like Foo::new(42), we should skip them | ||
137 | if let Some(name_ref) = path.segment().and_then(|s| s.name_ref()) { | ||
138 | match NameRefClass::classify(&ctx.sema, &name_ref) { | ||
139 | Some(NameRefClass::Definition(Definition::SelfType(_))) => {}, | ||
140 | Some(NameRefClass::Definition(def)) if def == strukt_def => {}, | ||
141 | _ => return None, | ||
142 | }; | ||
143 | } | ||
144 | |||
145 | let arg_list = call_expr.syntax().descendants().find_map(ast::ArgList::cast)?; | ||
146 | |||
147 | edit.replace( | ||
148 | call_expr.syntax().text_range(), | ||
149 | ast::make::record_expr( | ||
150 | path, | ||
151 | ast::make::record_expr_field_list(arg_list.args().zip(names).map( | ||
152 | |(expr, name)| { | ||
153 | ast::make::record_expr_field( | ||
154 | ast::make::name_ref(&name.to_string()), | ||
155 | Some(expr), | ||
156 | ) | ||
157 | }, | ||
158 | )), | ||
159 | ) | ||
160 | .to_string(), | ||
161 | ); | ||
162 | }, | ||
163 | _ => return None, | ||
164 | } | ||
165 | } | ||
166 | Some(()) | ||
167 | }; | ||
168 | |||
169 | for (file_id, refs) in usages { | ||
170 | edit.edit_file(file_id); | ||
171 | for r in refs { | ||
172 | for node in r.name.syntax().ancestors() { | ||
173 | if edit_node(edit, node).is_some() { | ||
174 | break; | ||
175 | } | ||
176 | } | ||
177 | } | ||
178 | } | ||
179 | } | ||
180 | |||
181 | fn edit_field_references( | ||
182 | ctx: &AssistContext, | ||
183 | edit: &mut AssistBuilder, | ||
184 | fields: impl Iterator<Item = ast::TupleField>, | ||
185 | names: &[ast::Name], | ||
186 | ) { | ||
187 | for (field, name) in fields.zip(names) { | ||
188 | let field = match ctx.sema.to_def(&field) { | ||
189 | Some(it) => it, | ||
190 | None => continue, | ||
191 | }; | ||
192 | let def = Definition::Field(field); | ||
193 | let usages = def.usages(&ctx.sema).all(); | ||
194 | for (file_id, refs) in usages { | ||
195 | edit.edit_file(file_id); | ||
196 | for r in refs { | ||
197 | if let Some(name_ref) = r.name.as_name_ref() { | ||
198 | edit.replace(name_ref.syntax().text_range(), name.text()); | ||
199 | } | ||
200 | } | ||
201 | } | ||
202 | } | ||
203 | } | ||
204 | |||
205 | fn generate_names(fields: impl Iterator<Item = ast::TupleField>) -> Vec<ast::Name> { | ||
206 | fields.enumerate().map(|(i, _)| ast::make::name(&format!("field{}", i + 1))).collect() | ||
207 | } | ||
208 | |||
209 | #[cfg(test)] | ||
210 | mod tests { | ||
211 | use crate::tests::{check_assist, check_assist_not_applicable}; | ||
212 | |||
213 | use super::*; | ||
214 | |||
215 | #[test] | ||
216 | fn not_applicable_other_than_tuple_struct() { | ||
217 | check_assist_not_applicable( | ||
218 | convert_tuple_struct_to_named_struct, | ||
219 | r#"struct Foo$0 { bar: u32 };"#, | ||
220 | ); | ||
221 | check_assist_not_applicable(convert_tuple_struct_to_named_struct, r#"struct Foo$0;"#); | ||
222 | } | ||
223 | |||
224 | #[test] | ||
225 | fn convert_simple_struct() { | ||
226 | check_assist( | ||
227 | convert_tuple_struct_to_named_struct, | ||
228 | r#" | ||
229 | struct Inner; | ||
230 | struct A$0(Inner); | ||
231 | |||
232 | impl A { | ||
233 | fn new(inner: Inner) -> A { | ||
234 | A(inner) | ||
235 | } | ||
236 | |||
237 | fn new_with_default() -> A { | ||
238 | A::new(Inner) | ||
239 | } | ||
240 | |||
241 | fn into_inner(self) -> Inner { | ||
242 | self.0 | ||
243 | } | ||
244 | }"#, | ||
245 | r#" | ||
246 | struct Inner; | ||
247 | struct A { field1: Inner } | ||
248 | |||
249 | impl A { | ||
250 | fn new(inner: Inner) -> A { | ||
251 | A { field1: inner } | ||
252 | } | ||
253 | |||
254 | fn new_with_default() -> A { | ||
255 | A::new(Inner) | ||
256 | } | ||
257 | |||
258 | fn into_inner(self) -> Inner { | ||
259 | self.field1 | ||
260 | } | ||
261 | }"#, | ||
262 | ); | ||
263 | } | ||
264 | |||
265 | #[test] | ||
266 | fn convert_struct_referenced_via_self_kw() { | ||
267 | check_assist( | ||
268 | convert_tuple_struct_to_named_struct, | ||
269 | r#" | ||
270 | struct Inner; | ||
271 | struct A$0(Inner); | ||
272 | |||
273 | impl A { | ||
274 | fn new(inner: Inner) -> Self { | ||
275 | Self(inner) | ||
276 | } | ||
277 | |||
278 | fn new_with_default() -> Self { | ||
279 | Self::new(Inner) | ||
280 | } | ||
281 | |||
282 | fn into_inner(self) -> Inner { | ||
283 | self.0 | ||
284 | } | ||
285 | }"#, | ||
286 | r#" | ||
287 | struct Inner; | ||
288 | struct A { field1: Inner } | ||
289 | |||
290 | impl A { | ||
291 | fn new(inner: Inner) -> Self { | ||
292 | Self { field1: inner } | ||
293 | } | ||
294 | |||
295 | fn new_with_default() -> Self { | ||
296 | Self::new(Inner) | ||
297 | } | ||
298 | |||
299 | fn into_inner(self) -> Inner { | ||
300 | self.field1 | ||
301 | } | ||
302 | }"#, | ||
303 | ); | ||
304 | } | ||
305 | |||
306 | #[test] | ||
307 | fn convert_destructured_struct() { | ||
308 | check_assist( | ||
309 | convert_tuple_struct_to_named_struct, | ||
310 | r#" | ||
311 | struct Inner; | ||
312 | struct A$0(Inner); | ||
313 | |||
314 | impl A { | ||
315 | fn into_inner(self) -> Inner { | ||
316 | let A(first) = self; | ||
317 | first | ||
318 | } | ||
319 | |||
320 | fn into_inner_via_self(self) -> Inner { | ||
321 | let Self(first) = self; | ||
322 | first | ||
323 | } | ||
324 | }"#, | ||
325 | r#" | ||
326 | struct Inner; | ||
327 | struct A { field1: Inner } | ||
328 | |||
329 | impl A { | ||
330 | fn into_inner(self) -> Inner { | ||
331 | let A { field1: first } = self; | ||
332 | first | ||
333 | } | ||
334 | |||
335 | fn into_inner_via_self(self) -> Inner { | ||
336 | let Self { field1: first } = self; | ||
337 | first | ||
338 | } | ||
339 | }"#, | ||
340 | ); | ||
341 | } | ||
342 | |||
343 | #[test] | ||
344 | fn convert_struct_with_visibility() { | ||
345 | check_assist( | ||
346 | convert_tuple_struct_to_named_struct, | ||
347 | r#" | ||
348 | struct A$0(pub u32, pub(crate) u64); | ||
349 | |||
350 | impl A { | ||
351 | fn new() -> A { | ||
352 | A(42, 42) | ||
353 | } | ||
354 | |||
355 | fn into_first(self) -> u32 { | ||
356 | self.0 | ||
357 | } | ||
358 | |||
359 | fn into_second(self) -> u64 { | ||
360 | self.1 | ||
361 | } | ||
362 | }"#, | ||
363 | r#" | ||
364 | struct A { pub field1: u32, pub(crate) field2: u64 } | ||
365 | |||
366 | impl A { | ||
367 | fn new() -> A { | ||
368 | A { field1: 42, field2: 42 } | ||
369 | } | ||
370 | |||
371 | fn into_first(self) -> u32 { | ||
372 | self.field1 | ||
373 | } | ||
374 | |||
375 | fn into_second(self) -> u64 { | ||
376 | self.field2 | ||
377 | } | ||
378 | }"#, | ||
379 | ); | ||
380 | } | ||
381 | |||
382 | #[test] | ||
383 | fn convert_struct_with_wrapped_references() { | ||
384 | check_assist( | ||
385 | convert_tuple_struct_to_named_struct, | ||
386 | r#" | ||
387 | struct Inner$0(u32); | ||
388 | struct Outer(Inner); | ||
389 | |||
390 | impl Outer { | ||
391 | fn new() -> Self { | ||
392 | Self(Inner(42)) | ||
393 | } | ||
394 | |||
395 | fn into_inner(self) -> u32 { | ||
396 | (self.0).0 | ||
397 | } | ||
398 | |||
399 | fn into_inner_destructed(self) -> u32 { | ||
400 | let Outer(Inner(x)) = self; | ||
401 | x | ||
402 | } | ||
403 | }"#, | ||
404 | r#" | ||
405 | struct Inner { field1: u32 } | ||
406 | struct Outer(Inner); | ||
407 | |||
408 | impl Outer { | ||
409 | fn new() -> Self { | ||
410 | Self(Inner { field1: 42 }) | ||
411 | } | ||
412 | |||
413 | fn into_inner(self) -> u32 { | ||
414 | (self.0).field1 | ||
415 | } | ||
416 | |||
417 | fn into_inner_destructed(self) -> u32 { | ||
418 | let Outer(Inner { field1: x }) = self; | ||
419 | x | ||
420 | } | ||
421 | }"#, | ||
422 | ); | ||
423 | |||
424 | check_assist( | ||
425 | convert_tuple_struct_to_named_struct, | ||
426 | r#" | ||
427 | struct Inner(u32); | ||
428 | struct Outer$0(Inner); | ||
429 | |||
430 | impl Outer { | ||
431 | fn new() -> Self { | ||
432 | Self(Inner(42)) | ||
433 | } | ||
434 | |||
435 | fn into_inner(self) -> u32 { | ||
436 | (self.0).0 | ||
437 | } | ||
438 | |||
439 | fn into_inner_destructed(self) -> u32 { | ||
440 | let Outer(Inner(x)) = self; | ||
441 | x | ||
442 | } | ||
443 | }"#, | ||
444 | r#" | ||
445 | struct Inner(u32); | ||
446 | struct Outer { field1: Inner } | ||
447 | |||
448 | impl Outer { | ||
449 | fn new() -> Self { | ||
450 | Self { field1: Inner(42) } | ||
451 | } | ||
452 | |||
453 | fn into_inner(self) -> u32 { | ||
454 | (self.field1).0 | ||
455 | } | ||
456 | |||
457 | fn into_inner_destructed(self) -> u32 { | ||
458 | let Outer { field1: Inner(x) } = self; | ||
459 | x | ||
460 | } | ||
461 | }"#, | ||
462 | ); | ||
463 | } | ||
464 | |||
465 | #[test] | ||
466 | fn convert_struct_with_multi_file_references() { | ||
467 | check_assist( | ||
468 | convert_tuple_struct_to_named_struct, | ||
469 | r#" | ||
470 | //- /main.rs | ||
471 | struct Inner; | ||
472 | struct A$0(Inner); | ||
473 | |||
474 | mod foo; | ||
475 | |||
476 | //- /foo.rs | ||
477 | use crate::{A, Inner}; | ||
478 | fn f() { | ||
479 | let a = A(Inner); | ||
480 | } | ||
481 | "#, | ||
482 | r#" | ||
483 | //- /main.rs | ||
484 | struct Inner; | ||
485 | struct A { field1: Inner } | ||
486 | |||
487 | mod foo; | ||
488 | |||
489 | //- /foo.rs | ||
490 | use crate::{A, Inner}; | ||
491 | fn f() { | ||
492 | let a = A { field1: Inner }; | ||
493 | } | ||
494 | "#, | ||
495 | ); | ||
496 | } | ||
497 | |||
498 | #[test] | ||
499 | fn convert_struct_with_where_clause() { | ||
500 | check_assist( | ||
501 | convert_tuple_struct_to_named_struct, | ||
502 | r#" | ||
503 | struct Wrap$0<T>(T) | ||
504 | where | ||
505 | T: Display; | ||
506 | "#, | ||
507 | r#" | ||
508 | struct Wrap<T> | ||
509 | where | ||
510 | T: Display, | ||
511 | { field1: T } | ||
512 | |||
513 | "#, | ||
514 | ); | ||
515 | } | ||
516 | } | ||
diff --git a/crates/ide_assists/src/handlers/extract_function.rs b/crates/ide_assists/src/handlers/extract_function.rs index 78a57fbdc..5f80a40c8 100644 --- a/crates/ide_assists/src/handlers/extract_function.rs +++ b/crates/ide_assists/src/handlers/extract_function.rs | |||
@@ -1227,9 +1227,19 @@ fn make_body( | |||
1227 | FunctionBody::Expr(expr) => { | 1227 | FunctionBody::Expr(expr) => { |
1228 | let expr = rewrite_body_segment(ctx, &fun.params, &handler, expr.syntax()); | 1228 | let expr = rewrite_body_segment(ctx, &fun.params, &handler, expr.syntax()); |
1229 | let expr = ast::Expr::cast(expr).unwrap(); | 1229 | let expr = ast::Expr::cast(expr).unwrap(); |
1230 | let expr = expr.dedent(old_indent).indent(IndentLevel(1)); | 1230 | match expr { |
1231 | ast::Expr::BlockExpr(block) => { | ||
1232 | // If the extracted expression is itself a block, there is no need to wrap it inside another block. | ||
1233 | let block = block.dedent(old_indent); | ||
1234 | // Recreate the block for formatting consistency with other extracted functions. | ||
1235 | make::block_expr(block.statements(), block.tail_expr()) | ||
1236 | } | ||
1237 | _ => { | ||
1238 | let expr = expr.dedent(old_indent).indent(IndentLevel(1)); | ||
1231 | 1239 | ||
1232 | make::block_expr(Vec::new(), Some(expr)) | 1240 | make::block_expr(Vec::new(), Some(expr)) |
1241 | } | ||
1242 | } | ||
1233 | } | 1243 | } |
1234 | FunctionBody::Span { parent, text_range } => { | 1244 | FunctionBody::Span { parent, text_range } => { |
1235 | let mut elements: Vec<_> = parent | 1245 | let mut elements: Vec<_> = parent |
@@ -1544,7 +1554,7 @@ fn foo() { | |||
1544 | } | 1554 | } |
1545 | 1555 | ||
1546 | fn $0fun_name() -> i32 { | 1556 | fn $0fun_name() -> i32 { |
1547 | { 1 + 1 } | 1557 | 1 + 1 |
1548 | }"#, | 1558 | }"#, |
1549 | ); | 1559 | ); |
1550 | } | 1560 | } |
@@ -2526,17 +2536,15 @@ fn foo() { | |||
2526 | } | 2536 | } |
2527 | 2537 | ||
2528 | fn $0fun_name(n: &mut i32) { | 2538 | fn $0fun_name(n: &mut i32) { |
2529 | { | 2539 | *n += *n; |
2530 | *n += *n; | 2540 | bar(*n); |
2531 | bar(*n); | 2541 | bar(*n+1); |
2532 | bar(*n+1); | 2542 | bar(*n**n); |
2533 | bar(*n**n); | 2543 | bar(&*n); |
2534 | bar(&*n); | 2544 | n.inc(); |
2535 | n.inc(); | 2545 | let v = n; |
2536 | let v = n; | 2546 | *v = v.succ(); |
2537 | *v = v.succ(); | 2547 | n.succ(); |
2538 | n.succ(); | ||
2539 | } | ||
2540 | }", | 2548 | }", |
2541 | ); | 2549 | ); |
2542 | } | 2550 | } |
diff --git a/crates/ide_assists/src/handlers/extract_struct_from_enum_variant.rs b/crates/ide_assists/src/handlers/extract_struct_from_enum_variant.rs index a8d6355bd..66f274fa7 100644 --- a/crates/ide_assists/src/handlers/extract_struct_from_enum_variant.rs +++ b/crates/ide_assists/src/handlers/extract_struct_from_enum_variant.rs | |||
@@ -5,7 +5,7 @@ use hir::{Module, ModuleDef, Name, Variant}; | |||
5 | use ide_db::{ | 5 | use ide_db::{ |
6 | defs::Definition, | 6 | defs::Definition, |
7 | helpers::{ | 7 | helpers::{ |
8 | insert_use::{insert_use, ImportScope}, | 8 | insert_use::{insert_use, ImportScope, InsertUseConfig}, |
9 | mod_path_to_ast, | 9 | mod_path_to_ast, |
10 | }, | 10 | }, |
11 | search::FileReference, | 11 | search::FileReference, |
@@ -13,9 +13,9 @@ use ide_db::{ | |||
13 | }; | 13 | }; |
14 | use rustc_hash::FxHashSet; | 14 | use rustc_hash::FxHashSet; |
15 | use syntax::{ | 15 | use syntax::{ |
16 | algo::{find_node_at_offset, SyntaxRewriter}, | 16 | algo::find_node_at_offset, |
17 | ast::{self, edit::IndentLevel, make, AstNode, NameOwner, VisibilityOwner}, | 17 | ast::{self, make, AstNode, NameOwner, VisibilityOwner}, |
18 | SourceFile, SyntaxElement, SyntaxNode, T, | 18 | ted, SyntaxNode, T, |
19 | }; | 19 | }; |
20 | 20 | ||
21 | use crate::{AssistContext, AssistId, AssistKind, Assists}; | 21 | use crate::{AssistContext, AssistId, AssistKind, Assists}; |
@@ -62,40 +62,50 @@ pub(crate) fn extract_struct_from_enum_variant( | |||
62 | let mut visited_modules_set = FxHashSet::default(); | 62 | let mut visited_modules_set = FxHashSet::default(); |
63 | let current_module = enum_hir.module(ctx.db()); | 63 | let current_module = enum_hir.module(ctx.db()); |
64 | visited_modules_set.insert(current_module); | 64 | visited_modules_set.insert(current_module); |
65 | let mut def_rewriter = None; | 65 | // record file references of the file the def resides in, we only want to swap to the edited file in the builder once |
66 | let mut def_file_references = None; | ||
66 | for (file_id, references) in usages { | 67 | for (file_id, references) in usages { |
67 | let mut rewriter = SyntaxRewriter::default(); | ||
68 | let source_file = ctx.sema.parse(file_id); | ||
69 | for reference in references { | ||
70 | update_reference( | ||
71 | ctx, | ||
72 | &mut rewriter, | ||
73 | reference, | ||
74 | &source_file, | ||
75 | &enum_module_def, | ||
76 | &variant_hir_name, | ||
77 | &mut visited_modules_set, | ||
78 | ); | ||
79 | } | ||
80 | if file_id == ctx.frange.file_id { | 68 | if file_id == ctx.frange.file_id { |
81 | def_rewriter = Some(rewriter); | 69 | def_file_references = Some(references); |
82 | continue; | 70 | continue; |
83 | } | 71 | } |
84 | builder.edit_file(file_id); | 72 | builder.edit_file(file_id); |
85 | builder.rewrite(rewriter); | 73 | let source_file = builder.make_ast_mut(ctx.sema.parse(file_id)); |
74 | let processed = process_references( | ||
75 | ctx, | ||
76 | &mut visited_modules_set, | ||
77 | source_file.syntax(), | ||
78 | &enum_module_def, | ||
79 | &variant_hir_name, | ||
80 | references, | ||
81 | ); | ||
82 | processed.into_iter().for_each(|(path, node, import)| { | ||
83 | apply_references(ctx.config.insert_use, path, node, import) | ||
84 | }); | ||
86 | } | 85 | } |
87 | let mut rewriter = def_rewriter.unwrap_or_default(); | ||
88 | update_variant(&mut rewriter, &variant); | ||
89 | extract_struct_def( | ||
90 | &mut rewriter, | ||
91 | &enum_ast, | ||
92 | variant_name.clone(), | ||
93 | &field_list, | ||
94 | &variant.parent_enum().syntax().clone().into(), | ||
95 | enum_ast.visibility(), | ||
96 | ); | ||
97 | builder.edit_file(ctx.frange.file_id); | 86 | builder.edit_file(ctx.frange.file_id); |
98 | builder.rewrite(rewriter); | 87 | let source_file = builder.make_ast_mut(ctx.sema.parse(ctx.frange.file_id)); |
88 | let variant = builder.make_ast_mut(variant.clone()); | ||
89 | if let Some(references) = def_file_references { | ||
90 | let processed = process_references( | ||
91 | ctx, | ||
92 | &mut visited_modules_set, | ||
93 | source_file.syntax(), | ||
94 | &enum_module_def, | ||
95 | &variant_hir_name, | ||
96 | references, | ||
97 | ); | ||
98 | processed.into_iter().for_each(|(path, node, import)| { | ||
99 | apply_references(ctx.config.insert_use, path, node, import) | ||
100 | }); | ||
101 | } | ||
102 | |||
103 | let def = create_struct_def(variant_name.clone(), &field_list, enum_ast.visibility()); | ||
104 | let start_offset = &variant.parent_enum().syntax().clone(); | ||
105 | ted::insert_raw(ted::Position::before(start_offset), def.syntax()); | ||
106 | ted::insert_raw(ted::Position::before(start_offset), &make::tokens::blank_line()); | ||
107 | |||
108 | update_variant(&variant); | ||
99 | }, | 109 | }, |
100 | ) | 110 | ) |
101 | } | 111 | } |
@@ -136,34 +146,11 @@ fn existing_definition(db: &RootDatabase, variant_name: &ast::Name, variant: &Va | |||
136 | .any(|(name, _)| name.to_string() == variant_name.to_string()) | 146 | .any(|(name, _)| name.to_string() == variant_name.to_string()) |
137 | } | 147 | } |
138 | 148 | ||
139 | fn insert_import( | 149 | fn create_struct_def( |
140 | ctx: &AssistContext, | ||
141 | rewriter: &mut SyntaxRewriter, | ||
142 | scope_node: &SyntaxNode, | ||
143 | module: &Module, | ||
144 | enum_module_def: &ModuleDef, | ||
145 | variant_hir_name: &Name, | ||
146 | ) -> Option<()> { | ||
147 | let db = ctx.db(); | ||
148 | let mod_path = | ||
149 | module.find_use_path_prefixed(db, *enum_module_def, ctx.config.insert_use.prefix_kind); | ||
150 | if let Some(mut mod_path) = mod_path { | ||
151 | mod_path.pop_segment(); | ||
152 | mod_path.push_segment(variant_hir_name.clone()); | ||
153 | let scope = ImportScope::find_insert_use_container(scope_node, &ctx.sema)?; | ||
154 | *rewriter += insert_use(&scope, mod_path_to_ast(&mod_path), ctx.config.insert_use); | ||
155 | } | ||
156 | Some(()) | ||
157 | } | ||
158 | |||
159 | fn extract_struct_def( | ||
160 | rewriter: &mut SyntaxRewriter, | ||
161 | enum_: &ast::Enum, | ||
162 | variant_name: ast::Name, | 150 | variant_name: ast::Name, |
163 | field_list: &Either<ast::RecordFieldList, ast::TupleFieldList>, | 151 | field_list: &Either<ast::RecordFieldList, ast::TupleFieldList>, |
164 | start_offset: &SyntaxElement, | ||
165 | visibility: Option<ast::Visibility>, | 152 | visibility: Option<ast::Visibility>, |
166 | ) -> Option<()> { | 153 | ) -> ast::Struct { |
167 | let pub_vis = Some(make::visibility_pub()); | 154 | let pub_vis = Some(make::visibility_pub()); |
168 | let field_list = match field_list { | 155 | let field_list = match field_list { |
169 | Either::Left(field_list) => { | 156 | Either::Left(field_list) => { |
@@ -180,65 +167,90 @@ fn extract_struct_def( | |||
180 | .into(), | 167 | .into(), |
181 | }; | 168 | }; |
182 | 169 | ||
183 | rewriter.insert_before( | 170 | make::struct_(visibility, variant_name, None, field_list).clone_for_update() |
184 | start_offset, | ||
185 | make::struct_(visibility, variant_name, None, field_list).syntax(), | ||
186 | ); | ||
187 | rewriter.insert_before(start_offset, &make::tokens::blank_line()); | ||
188 | |||
189 | if let indent_level @ 1..=usize::MAX = IndentLevel::from_node(enum_.syntax()).0 as usize { | ||
190 | rewriter | ||
191 | .insert_before(start_offset, &make::tokens::whitespace(&" ".repeat(4 * indent_level))); | ||
192 | } | ||
193 | Some(()) | ||
194 | } | 171 | } |
195 | 172 | ||
196 | fn update_variant(rewriter: &mut SyntaxRewriter, variant: &ast::Variant) -> Option<()> { | 173 | fn update_variant(variant: &ast::Variant) -> Option<()> { |
197 | let name = variant.name()?; | 174 | let name = variant.name()?; |
198 | let tuple_field = make::tuple_field(None, make::ty(&name.text())); | 175 | let tuple_field = make::tuple_field(None, make::ty(&name.text())); |
199 | let replacement = make::variant( | 176 | let replacement = make::variant( |
200 | name, | 177 | name, |
201 | Some(ast::FieldList::TupleFieldList(make::tuple_field_list(iter::once(tuple_field)))), | 178 | Some(ast::FieldList::TupleFieldList(make::tuple_field_list(iter::once(tuple_field)))), |
202 | ); | 179 | ) |
203 | rewriter.replace(variant.syntax(), replacement.syntax()); | 180 | .clone_for_update(); |
181 | ted::replace(variant.syntax(), replacement.syntax()); | ||
204 | Some(()) | 182 | Some(()) |
205 | } | 183 | } |
206 | 184 | ||
207 | fn update_reference( | 185 | fn apply_references( |
186 | insert_use_cfg: InsertUseConfig, | ||
187 | segment: ast::PathSegment, | ||
188 | node: SyntaxNode, | ||
189 | import: Option<(ImportScope, hir::ModPath)>, | ||
190 | ) { | ||
191 | if let Some((scope, path)) = import { | ||
192 | insert_use(&scope, mod_path_to_ast(&path), insert_use_cfg); | ||
193 | } | ||
194 | ted::insert_raw( | ||
195 | ted::Position::before(segment.syntax()), | ||
196 | make::path_from_text(&format!("{}", segment)).clone_for_update().syntax(), | ||
197 | ); | ||
198 | ted::insert_raw(ted::Position::before(segment.syntax()), make::token(T!['('])); | ||
199 | ted::insert_raw(ted::Position::after(&node), make::token(T![')'])); | ||
200 | } | ||
201 | |||
202 | fn process_references( | ||
208 | ctx: &AssistContext, | 203 | ctx: &AssistContext, |
209 | rewriter: &mut SyntaxRewriter, | 204 | visited_modules: &mut FxHashSet<Module>, |
210 | reference: FileReference, | 205 | source_file: &SyntaxNode, |
211 | source_file: &SourceFile, | ||
212 | enum_module_def: &ModuleDef, | 206 | enum_module_def: &ModuleDef, |
213 | variant_hir_name: &Name, | 207 | variant_hir_name: &Name, |
214 | visited_modules_set: &mut FxHashSet<Module>, | 208 | refs: Vec<FileReference>, |
215 | ) -> Option<()> { | 209 | ) -> Vec<(ast::PathSegment, SyntaxNode, Option<(ImportScope, hir::ModPath)>)> { |
210 | // we have to recollect here eagerly as we are about to edit the tree we need to calculate the changes | ||
211 | // and corresponding nodes up front | ||
212 | refs.into_iter() | ||
213 | .flat_map(|reference| { | ||
214 | let (segment, scope_node, module) = | ||
215 | reference_to_node(&ctx.sema, source_file, reference)?; | ||
216 | if !visited_modules.contains(&module) { | ||
217 | let mod_path = module.find_use_path_prefixed( | ||
218 | ctx.sema.db, | ||
219 | *enum_module_def, | ||
220 | ctx.config.insert_use.prefix_kind, | ||
221 | ); | ||
222 | if let Some(mut mod_path) = mod_path { | ||
223 | mod_path.pop_segment(); | ||
224 | mod_path.push_segment(variant_hir_name.clone()); | ||
225 | let scope = ImportScope::find_insert_use_container(&scope_node)?; | ||
226 | visited_modules.insert(module); | ||
227 | return Some((segment, scope_node, Some((scope, mod_path)))); | ||
228 | } | ||
229 | } | ||
230 | Some((segment, scope_node, None)) | ||
231 | }) | ||
232 | .collect() | ||
233 | } | ||
234 | |||
235 | fn reference_to_node( | ||
236 | sema: &hir::Semantics<RootDatabase>, | ||
237 | source_file: &SyntaxNode, | ||
238 | reference: FileReference, | ||
239 | ) -> Option<(ast::PathSegment, SyntaxNode, hir::Module)> { | ||
216 | let offset = reference.range.start(); | 240 | let offset = reference.range.start(); |
217 | let (segment, expr) = if let Some(path_expr) = | 241 | if let Some(path_expr) = find_node_at_offset::<ast::PathExpr>(source_file, offset) { |
218 | find_node_at_offset::<ast::PathExpr>(source_file.syntax(), offset) | ||
219 | { | ||
220 | // tuple variant | 242 | // tuple variant |
221 | (path_expr.path()?.segment()?, path_expr.syntax().parent()?) | 243 | Some((path_expr.path()?.segment()?, path_expr.syntax().parent()?)) |
222 | } else if let Some(record_expr) = | 244 | } else if let Some(record_expr) = find_node_at_offset::<ast::RecordExpr>(source_file, offset) { |
223 | find_node_at_offset::<ast::RecordExpr>(source_file.syntax(), offset) | ||
224 | { | ||
225 | // record variant | 245 | // record variant |
226 | (record_expr.path()?.segment()?, record_expr.syntax().clone()) | 246 | Some((record_expr.path()?.segment()?, record_expr.syntax().clone())) |
227 | } else { | 247 | } else { |
228 | return None; | 248 | None |
229 | }; | ||
230 | |||
231 | let module = ctx.sema.scope(&expr).module()?; | ||
232 | if !visited_modules_set.contains(&module) { | ||
233 | if insert_import(ctx, rewriter, &expr, &module, enum_module_def, variant_hir_name).is_some() | ||
234 | { | ||
235 | visited_modules_set.insert(module); | ||
236 | } | ||
237 | } | 249 | } |
238 | rewriter.insert_after(segment.syntax(), &make::token(T!['('])); | 250 | .and_then(|(segment, expr)| { |
239 | rewriter.insert_after(segment.syntax(), segment.syntax()); | 251 | let module = sema.scope(&expr).module()?; |
240 | rewriter.insert_after(&expr, &make::token(T![')'])); | 252 | Some((segment, expr, module)) |
241 | Some(()) | 253 | }) |
242 | } | 254 | } |
243 | 255 | ||
244 | #[cfg(test)] | 256 | #[cfg(test)] |
@@ -345,7 +357,7 @@ mod my_mod { | |||
345 | 357 | ||
346 | pub struct MyField(pub u8, pub u8); | 358 | pub struct MyField(pub u8, pub u8); |
347 | 359 | ||
348 | pub enum MyEnum { | 360 | pub enum MyEnum { |
349 | MyField(MyField), | 361 | MyField(MyField), |
350 | } | 362 | } |
351 | } | 363 | } |
diff --git a/crates/ide_assists/src/handlers/merge_imports.rs b/crates/ide_assists/src/handlers/merge_imports.rs index 8e0794218..add7b8e37 100644 --- a/crates/ide_assists/src/handlers/merge_imports.rs +++ b/crates/ide_assists/src/handlers/merge_imports.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use ide_db::helpers::insert_use::{try_merge_imports, try_merge_trees, MergeBehavior}; | 1 | use ide_db::helpers::merge_imports::{try_merge_imports, try_merge_trees, MergeBehavior}; |
2 | use syntax::{algo::neighbor, ast, ted, AstNode}; | 2 | use syntax::{algo::neighbor, ast, ted, AstNode}; |
3 | 3 | ||
4 | use crate::{ | 4 | use crate::{ |
diff --git a/crates/ide_assists/src/handlers/reorder_fields.rs b/crates/ide_assists/src/handlers/reorder_fields.rs index 1a95135ca..e90bbdbcf 100644 --- a/crates/ide_assists/src/handlers/reorder_fields.rs +++ b/crates/ide_assists/src/handlers/reorder_fields.rs | |||
@@ -83,11 +83,9 @@ fn replace<T: AstNode + PartialEq>( | |||
83 | fields: impl Iterator<Item = T>, | 83 | fields: impl Iterator<Item = T>, |
84 | sorted_fields: impl IntoIterator<Item = T>, | 84 | sorted_fields: impl IntoIterator<Item = T>, |
85 | ) { | 85 | ) { |
86 | fields.zip(sorted_fields).filter(|(field, sorted)| field != sorted).for_each( | 86 | fields.zip(sorted_fields).for_each(|(field, sorted_field)| { |
87 | |(field, sorted_field)| { | 87 | ted::replace(field.syntax(), sorted_field.syntax().clone_for_update()) |
88 | ted::replace(field.syntax(), sorted_field.syntax().clone_for_update()); | 88 | }); |
89 | }, | ||
90 | ); | ||
91 | } | 89 | } |
92 | 90 | ||
93 | fn compute_fields_ranks(path: &ast::Path, ctx: &AssistContext) -> Option<FxHashMap<String, usize>> { | 91 | fn compute_fields_ranks(path: &ast::Path, ctx: &AssistContext) -> Option<FxHashMap<String, usize>> { |
diff --git a/crates/ide_assists/src/handlers/reorder_impl.rs b/crates/ide_assists/src/handlers/reorder_impl.rs index f976e73ad..72d889248 100644 --- a/crates/ide_assists/src/handlers/reorder_impl.rs +++ b/crates/ide_assists/src/handlers/reorder_impl.rs | |||
@@ -4,9 +4,8 @@ use rustc_hash::FxHashMap; | |||
4 | use hir::{PathResolution, Semantics}; | 4 | use hir::{PathResolution, Semantics}; |
5 | use ide_db::RootDatabase; | 5 | use ide_db::RootDatabase; |
6 | use syntax::{ | 6 | use syntax::{ |
7 | algo, | ||
8 | ast::{self, NameOwner}, | 7 | ast::{self, NameOwner}, |
9 | AstNode, | 8 | ted, AstNode, |
10 | }; | 9 | }; |
11 | 10 | ||
12 | use crate::{AssistContext, AssistId, AssistKind, Assists}; | 11 | use crate::{AssistContext, AssistId, AssistKind, Assists}; |
@@ -75,13 +74,16 @@ pub(crate) fn reorder_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<()> | |||
75 | } | 74 | } |
76 | 75 | ||
77 | let target = items.syntax().text_range(); | 76 | let target = items.syntax().text_range(); |
78 | acc.add(AssistId("reorder_impl", AssistKind::RefactorRewrite), "Sort methods", target, |edit| { | 77 | acc.add( |
79 | let mut rewriter = algo::SyntaxRewriter::default(); | 78 | AssistId("reorder_impl", AssistKind::RefactorRewrite), |
80 | for (old, new) in methods.iter().zip(&sorted) { | 79 | "Sort methods", |
81 | rewriter.replace(old.syntax(), new.syntax()); | 80 | target, |
82 | } | 81 | |builder| { |
83 | edit.rewrite(rewriter); | 82 | methods.into_iter().zip(sorted).for_each(|(old, new)| { |
84 | }) | 83 | ted::replace(builder.make_ast_mut(old).syntax(), new.clone_for_update().syntax()) |
84 | }); | ||
85 | }, | ||
86 | ) | ||
85 | } | 87 | } |
86 | 88 | ||
87 | fn compute_method_ranks(path: &ast::Path, ctx: &AssistContext) -> Option<FxHashMap<String, usize>> { | 89 | fn compute_method_ranks(path: &ast::Path, ctx: &AssistContext) -> Option<FxHashMap<String, usize>> { |
diff --git a/crates/ide_assists/src/handlers/replace_qualified_name_with_use.rs b/crates/ide_assists/src/handlers/replace_qualified_name_with_use.rs index 36d2e0331..99ba79860 100644 --- a/crates/ide_assists/src/handlers/replace_qualified_name_with_use.rs +++ b/crates/ide_assists/src/handlers/replace_qualified_name_with_use.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | use ide_db::helpers::insert_use::{insert_use, ImportScope}; | 1 | use ide_db::helpers::insert_use::{insert_use, ImportScope}; |
2 | use syntax::{algo::SyntaxRewriter, ast, match_ast, AstNode, SyntaxNode}; | 2 | use syntax::{ast, match_ast, ted, AstNode, SyntaxNode}; |
3 | 3 | ||
4 | use crate::{AssistContext, AssistId, AssistKind, Assists}; | 4 | use crate::{AssistContext, AssistId, AssistKind, Assists}; |
5 | 5 | ||
@@ -31,7 +31,7 @@ pub(crate) fn replace_qualified_name_with_use( | |||
31 | } | 31 | } |
32 | 32 | ||
33 | let target = path.syntax().text_range(); | 33 | let target = path.syntax().text_range(); |
34 | let scope = ImportScope::find_insert_use_container(path.syntax(), &ctx.sema)?; | 34 | let scope = ImportScope::find_insert_use_container_with_macros(path.syntax(), &ctx.sema)?; |
35 | let syntax = scope.as_syntax_node(); | 35 | let syntax = scope.as_syntax_node(); |
36 | acc.add( | 36 | acc.add( |
37 | AssistId("replace_qualified_name_with_use", AssistKind::RefactorRewrite), | 37 | AssistId("replace_qualified_name_with_use", AssistKind::RefactorRewrite), |
@@ -40,18 +40,17 @@ pub(crate) fn replace_qualified_name_with_use( | |||
40 | |builder| { | 40 | |builder| { |
41 | // Now that we've brought the name into scope, re-qualify all paths that could be | 41 | // Now that we've brought the name into scope, re-qualify all paths that could be |
42 | // affected (that is, all paths inside the node we added the `use` to). | 42 | // affected (that is, all paths inside the node we added the `use` to). |
43 | let mut rewriter = SyntaxRewriter::default(); | 43 | let syntax = builder.make_mut(syntax.clone()); |
44 | shorten_paths(&mut rewriter, syntax.clone(), &path); | ||
45 | if let Some(ref import_scope) = ImportScope::from(syntax.clone()) { | 44 | if let Some(ref import_scope) = ImportScope::from(syntax.clone()) { |
46 | rewriter += insert_use(import_scope, path, ctx.config.insert_use); | 45 | shorten_paths(&syntax, &path.clone_for_update()); |
47 | builder.rewrite(rewriter); | 46 | insert_use(import_scope, path, ctx.config.insert_use); |
48 | } | 47 | } |
49 | }, | 48 | }, |
50 | ) | 49 | ) |
51 | } | 50 | } |
52 | 51 | ||
53 | /// Adds replacements to `re` that shorten `path` in all descendants of `node`. | 52 | /// Adds replacements to `re` that shorten `path` in all descendants of `node`. |
54 | fn shorten_paths(rewriter: &mut SyntaxRewriter<'static>, node: SyntaxNode, path: &ast::Path) { | 53 | fn shorten_paths(node: &SyntaxNode, path: &ast::Path) { |
55 | for child in node.children() { | 54 | for child in node.children() { |
56 | match_ast! { | 55 | match_ast! { |
57 | match child { | 56 | match child { |
@@ -60,34 +59,26 @@ fn shorten_paths(rewriter: &mut SyntaxRewriter<'static>, node: SyntaxNode, path: | |||
60 | ast::Use(_it) => continue, | 59 | ast::Use(_it) => continue, |
61 | // Don't descend into submodules, they don't have the same `use` items in scope. | 60 | // Don't descend into submodules, they don't have the same `use` items in scope. |
62 | ast::Module(_it) => continue, | 61 | ast::Module(_it) => continue, |
63 | 62 | ast::Path(p) => if maybe_replace_path(p.clone(), path.clone()).is_none() { | |
64 | ast::Path(p) => { | 63 | shorten_paths(p.syntax(), path); |
65 | match maybe_replace_path(rewriter, p.clone(), path.clone()) { | ||
66 | Some(()) => {}, | ||
67 | None => shorten_paths(rewriter, p.syntax().clone(), path), | ||
68 | } | ||
69 | }, | 64 | }, |
70 | _ => shorten_paths(rewriter, child, path), | 65 | _ => shorten_paths(&child, path), |
71 | } | 66 | } |
72 | } | 67 | } |
73 | } | 68 | } |
74 | } | 69 | } |
75 | 70 | ||
76 | fn maybe_replace_path( | 71 | fn maybe_replace_path(path: ast::Path, target: ast::Path) -> Option<()> { |
77 | rewriter: &mut SyntaxRewriter<'static>, | ||
78 | path: ast::Path, | ||
79 | target: ast::Path, | ||
80 | ) -> Option<()> { | ||
81 | if !path_eq(path.clone(), target) { | 72 | if !path_eq(path.clone(), target) { |
82 | return None; | 73 | return None; |
83 | } | 74 | } |
84 | 75 | ||
85 | // Shorten `path`, leaving only its last segment. | 76 | // Shorten `path`, leaving only its last segment. |
86 | if let Some(parent) = path.qualifier() { | 77 | if let Some(parent) = path.qualifier() { |
87 | rewriter.delete(parent.syntax()); | 78 | ted::remove(parent.syntax()); |
88 | } | 79 | } |
89 | if let Some(double_colon) = path.coloncolon_token() { | 80 | if let Some(double_colon) = path.coloncolon_token() { |
90 | rewriter.delete(&double_colon); | 81 | ted::remove(&double_colon); |
91 | } | 82 | } |
92 | 83 | ||
93 | Some(()) | 84 | Some(()) |
@@ -150,6 +141,7 @@ Debug | |||
150 | ", | 141 | ", |
151 | ); | 142 | ); |
152 | } | 143 | } |
144 | |||
153 | #[test] | 145 | #[test] |
154 | fn test_replace_add_use_no_anchor_with_item_below() { | 146 | fn test_replace_add_use_no_anchor_with_item_below() { |
155 | check_assist( | 147 | check_assist( |
diff --git a/crates/ide_assists/src/lib.rs b/crates/ide_assists/src/lib.rs index 8996c1b61..88ae5c9a9 100644 --- a/crates/ide_assists/src/lib.rs +++ b/crates/ide_assists/src/lib.rs | |||
@@ -120,6 +120,7 @@ mod handlers { | |||
120 | mod convert_comment_block; | 120 | mod convert_comment_block; |
121 | mod convert_iter_for_each_to_for; | 121 | mod convert_iter_for_each_to_for; |
122 | mod convert_into_to_from; | 122 | mod convert_into_to_from; |
123 | mod convert_tuple_struct_to_named_struct; | ||
123 | mod early_return; | 124 | mod early_return; |
124 | mod expand_glob_import; | 125 | mod expand_glob_import; |
125 | mod extract_function; | 126 | mod extract_function; |
@@ -190,6 +191,7 @@ mod handlers { | |||
190 | convert_comment_block::convert_comment_block, | 191 | convert_comment_block::convert_comment_block, |
191 | convert_iter_for_each_to_for::convert_iter_for_each_to_for, | 192 | convert_iter_for_each_to_for::convert_iter_for_each_to_for, |
192 | convert_into_to_from::convert_into_to_from, | 193 | convert_into_to_from::convert_into_to_from, |
194 | convert_tuple_struct_to_named_struct::convert_tuple_struct_to_named_struct, | ||
193 | early_return::convert_to_guarded_return, | 195 | early_return::convert_to_guarded_return, |
194 | expand_glob_import::expand_glob_import, | 196 | expand_glob_import::expand_glob_import, |
195 | extract_struct_from_enum_variant::extract_struct_from_enum_variant, | 197 | extract_struct_from_enum_variant::extract_struct_from_enum_variant, |
diff --git a/crates/ide_assists/src/tests.rs b/crates/ide_assists/src/tests.rs index 49533e7d2..6f4f97361 100644 --- a/crates/ide_assists/src/tests.rs +++ b/crates/ide_assists/src/tests.rs | |||
@@ -4,10 +4,7 @@ use expect_test::expect; | |||
4 | use hir::Semantics; | 4 | use hir::Semantics; |
5 | use ide_db::{ | 5 | use ide_db::{ |
6 | base_db::{fixture::WithFixture, FileId, FileRange, SourceDatabaseExt}, | 6 | base_db::{fixture::WithFixture, FileId, FileRange, SourceDatabaseExt}, |
7 | helpers::{ | 7 | helpers::{insert_use::InsertUseConfig, merge_imports::MergeBehavior, SnippetCap}, |
8 | insert_use::{InsertUseConfig, MergeBehavior}, | ||
9 | SnippetCap, | ||
10 | }, | ||
11 | source_change::FileSystemEdit, | 8 | source_change::FileSystemEdit, |
12 | RootDatabase, | 9 | RootDatabase, |
13 | }; | 10 | }; |
diff --git a/crates/ide_assists/src/tests/generated.rs b/crates/ide_assists/src/tests/generated.rs index 41559b43a..59bcef8fb 100644 --- a/crates/ide_assists/src/tests/generated.rs +++ b/crates/ide_assists/src/tests/generated.rs | |||
@@ -292,6 +292,47 @@ fn main() { | |||
292 | } | 292 | } |
293 | 293 | ||
294 | #[test] | 294 | #[test] |
295 | fn doctest_convert_tuple_struct_to_named_struct() { | ||
296 | check_doc_test( | ||
297 | "convert_tuple_struct_to_named_struct", | ||
298 | r#####" | ||
299 | struct Point$0(f32, f32); | ||
300 | |||
301 | impl Point { | ||
302 | pub fn new(x: f32, y: f32) -> Self { | ||
303 | Point(x, y) | ||
304 | } | ||
305 | |||
306 | pub fn x(&self) -> f32 { | ||
307 | self.0 | ||
308 | } | ||
309 | |||
310 | pub fn y(&self) -> f32 { | ||
311 | self.1 | ||
312 | } | ||
313 | } | ||
314 | "#####, | ||
315 | r#####" | ||
316 | struct Point { field1: f32, field2: f32 } | ||
317 | |||
318 | impl Point { | ||
319 | pub fn new(x: f32, y: f32) -> Self { | ||
320 | Point { field1: x, field2: y } | ||
321 | } | ||
322 | |||
323 | pub fn x(&self) -> f32 { | ||
324 | self.field1 | ||
325 | } | ||
326 | |||
327 | pub fn y(&self) -> f32 { | ||
328 | self.field2 | ||
329 | } | ||
330 | } | ||
331 | "#####, | ||
332 | ) | ||
333 | } | ||
334 | |||
335 | #[test] | ||
295 | fn doctest_expand_glob_import() { | 336 | fn doctest_expand_glob_import() { |
296 | check_doc_test( | 337 | check_doc_test( |
297 | "expand_glob_import", | 338 | "expand_glob_import", |
diff --git a/crates/ide_assists/src/utils.rs b/crates/ide_assists/src/utils.rs index d67524937..5a90ad715 100644 --- a/crates/ide_assists/src/utils.rs +++ b/crates/ide_assists/src/utils.rs | |||
@@ -140,7 +140,8 @@ pub fn add_trait_assoc_items_to_impl( | |||
140 | 140 | ||
141 | let items = items | 141 | let items = items |
142 | .into_iter() | 142 | .into_iter() |
143 | .map(|it| ast_transform::apply(&*ast_transform, it)) | 143 | .map(|it| it.clone_for_update()) |
144 | .inspect(|it| ast_transform::apply(&*ast_transform, it)) | ||
144 | .map(|it| match it { | 145 | .map(|it| match it { |
145 | ast::AssocItem::Fn(def) => ast::AssocItem::Fn(add_body(def)), | 146 | ast::AssocItem::Fn(def) => ast::AssocItem::Fn(add_body(def)), |
146 | ast::AssocItem::TypeAlias(def) => ast::AssocItem::TypeAlias(def.remove_bounds()), | 147 | ast::AssocItem::TypeAlias(def) => ast::AssocItem::TypeAlias(def.remove_bounds()), |
diff --git a/crates/ide_completion/src/completions/flyimport.rs b/crates/ide_completion/src/completions/flyimport.rs index 8e211ae1e..9d5b61562 100644 --- a/crates/ide_completion/src/completions/flyimport.rs +++ b/crates/ide_completion/src/completions/flyimport.rs | |||
@@ -132,7 +132,7 @@ pub(crate) fn import_on_the_fly(acc: &mut Completions, ctx: &CompletionContext) | |||
132 | 132 | ||
133 | let user_input_lowercased = potential_import_name.to_lowercase(); | 133 | let user_input_lowercased = potential_import_name.to_lowercase(); |
134 | let import_assets = import_assets(ctx, potential_import_name)?; | 134 | let import_assets = import_assets(ctx, potential_import_name)?; |
135 | let import_scope = ImportScope::find_insert_use_container( | 135 | let import_scope = ImportScope::find_insert_use_container_with_macros( |
136 | position_for_import(ctx, Some(import_assets.import_candidate()))?, | 136 | position_for_import(ctx, Some(import_assets.import_candidate()))?, |
137 | &ctx.sema, | 137 | &ctx.sema, |
138 | )?; | 138 | )?; |
diff --git a/crates/ide_completion/src/item.rs b/crates/ide_completion/src/item.rs index 16991b688..99edb9499 100644 --- a/crates/ide_completion/src/item.rs +++ b/crates/ide_completion/src/item.rs | |||
@@ -377,11 +377,11 @@ impl ImportEdit { | |||
377 | pub fn to_text_edit(&self, cfg: InsertUseConfig) -> Option<TextEdit> { | 377 | pub fn to_text_edit(&self, cfg: InsertUseConfig) -> Option<TextEdit> { |
378 | let _p = profile::span("ImportEdit::to_text_edit"); | 378 | let _p = profile::span("ImportEdit::to_text_edit"); |
379 | 379 | ||
380 | let rewriter = | 380 | let new_ast = self.scope.clone_for_update(); |
381 | insert_use::insert_use(&self.scope, mod_path_to_ast(&self.import.import_path), cfg); | 381 | insert_use::insert_use(&new_ast, mod_path_to_ast(&self.import.import_path), cfg); |
382 | let old_ast = rewriter.rewrite_root()?; | ||
383 | let mut import_insert = TextEdit::builder(); | 382 | let mut import_insert = TextEdit::builder(); |
384 | algo::diff(&old_ast, &rewriter.rewrite(&old_ast)).into_text_edit(&mut import_insert); | 383 | algo::diff(self.scope.as_syntax_node(), new_ast.as_syntax_node()) |
384 | .into_text_edit(&mut import_insert); | ||
385 | 385 | ||
386 | Some(import_insert.finish()) | 386 | Some(import_insert.finish()) |
387 | } | 387 | } |
diff --git a/crates/ide_completion/src/lib.rs b/crates/ide_completion/src/lib.rs index 6f3d5c5c5..e32633565 100644 --- a/crates/ide_completion/src/lib.rs +++ b/crates/ide_completion/src/lib.rs | |||
@@ -179,7 +179,7 @@ pub fn resolve_completion_edits( | |||
179 | ) -> Option<Vec<TextEdit>> { | 179 | ) -> Option<Vec<TextEdit>> { |
180 | let ctx = CompletionContext::new(db, position, config)?; | 180 | let ctx = CompletionContext::new(db, position, config)?; |
181 | let position_for_import = position_for_import(&ctx, None)?; | 181 | let position_for_import = position_for_import(&ctx, None)?; |
182 | let scope = ImportScope::find_insert_use_container(position_for_import, &ctx.sema)?; | 182 | let scope = ImportScope::find_insert_use_container_with_macros(position_for_import, &ctx.sema)?; |
183 | 183 | ||
184 | let current_module = ctx.sema.scope(position_for_import).module()?; | 184 | let current_module = ctx.sema.scope(position_for_import).module()?; |
185 | let current_crate = current_module.krate(); | 185 | let current_crate = current_module.krate(); |
diff --git a/crates/ide_completion/src/test_utils.rs b/crates/ide_completion/src/test_utils.rs index 9da844031..c9857ec5f 100644 --- a/crates/ide_completion/src/test_utils.rs +++ b/crates/ide_completion/src/test_utils.rs | |||
@@ -3,10 +3,7 @@ | |||
3 | use hir::{PrefixKind, Semantics}; | 3 | use hir::{PrefixKind, Semantics}; |
4 | use ide_db::{ | 4 | use ide_db::{ |
5 | base_db::{fixture::ChangeFixture, FileLoader, FilePosition}, | 5 | base_db::{fixture::ChangeFixture, FileLoader, FilePosition}, |
6 | helpers::{ | 6 | helpers::{insert_use::InsertUseConfig, merge_imports::MergeBehavior, SnippetCap}, |
7 | insert_use::{InsertUseConfig, MergeBehavior}, | ||
8 | SnippetCap, | ||
9 | }, | ||
10 | RootDatabase, | 7 | RootDatabase, |
11 | }; | 8 | }; |
12 | use itertools::Itertools; | 9 | use itertools::Itertools; |
diff --git a/crates/ide_db/src/helpers.rs b/crates/ide_db/src/helpers.rs index 720de0d1f..21b48237a 100644 --- a/crates/ide_db/src/helpers.rs +++ b/crates/ide_db/src/helpers.rs | |||
@@ -1,6 +1,7 @@ | |||
1 | //! A module with ide helpers for high-level ide features. | 1 | //! A module with ide helpers for high-level ide features. |
2 | pub mod insert_use; | ||
3 | pub mod import_assets; | 2 | pub mod import_assets; |
3 | pub mod insert_use; | ||
4 | pub mod merge_imports; | ||
4 | pub mod rust_doc; | 5 | pub mod rust_doc; |
5 | 6 | ||
6 | use std::collections::VecDeque; | 7 | use std::collections::VecDeque; |
diff --git a/crates/ide_db/src/helpers/insert_use.rs b/crates/ide_db/src/helpers/insert_use.rs index be3a22725..55cdc4da3 100644 --- a/crates/ide_db/src/helpers/insert_use.rs +++ b/crates/ide_db/src/helpers/insert_use.rs | |||
@@ -1,19 +1,17 @@ | |||
1 | //! Handle syntactic aspects of inserting a new `use`. | 1 | //! Handle syntactic aspects of inserting a new `use`. |
2 | use std::{cmp::Ordering, iter::successors}; | 2 | use std::cmp::Ordering; |
3 | 3 | ||
4 | use hir::Semantics; | 4 | use hir::Semantics; |
5 | use itertools::{EitherOrBoth, Itertools}; | ||
6 | use syntax::{ | 5 | use syntax::{ |
7 | algo::SyntaxRewriter, | 6 | algo, |
8 | ast::{ | 7 | ast::{self, make, AstNode, PathSegmentKind}, |
9 | self, | 8 | ted, AstToken, Direction, NodeOrToken, SyntaxNode, SyntaxToken, |
10 | edit::{AstNodeEdit, IndentLevel}, | ||
11 | make, AstNode, AttrsOwner, PathSegmentKind, VisibilityOwner, | ||
12 | }, | ||
13 | AstToken, InsertPosition, NodeOrToken, SyntaxElement, SyntaxNode, SyntaxToken, | ||
14 | }; | 9 | }; |
15 | 10 | ||
16 | use crate::RootDatabase; | 11 | use crate::{ |
12 | helpers::merge_imports::{try_merge_imports, use_tree_path_cmp, MergeBehavior}, | ||
13 | RootDatabase, | ||
14 | }; | ||
17 | 15 | ||
18 | pub use hir::PrefixKind; | 16 | pub use hir::PrefixKind; |
19 | 17 | ||
@@ -42,13 +40,18 @@ impl ImportScope { | |||
42 | } | 40 | } |
43 | 41 | ||
44 | /// Determines the containing syntax node in which to insert a `use` statement affecting `position`. | 42 | /// Determines the containing syntax node in which to insert a `use` statement affecting `position`. |
45 | pub fn find_insert_use_container( | 43 | pub fn find_insert_use_container_with_macros( |
46 | position: &SyntaxNode, | 44 | position: &SyntaxNode, |
47 | sema: &Semantics<'_, RootDatabase>, | 45 | sema: &Semantics<'_, RootDatabase>, |
48 | ) -> Option<Self> { | 46 | ) -> Option<Self> { |
49 | sema.ancestors_with_macros(position.clone()).find_map(Self::from) | 47 | sema.ancestors_with_macros(position.clone()).find_map(Self::from) |
50 | } | 48 | } |
51 | 49 | ||
50 | /// Determines the containing syntax node in which to insert a `use` statement affecting `position`. | ||
51 | pub fn find_insert_use_container(position: &SyntaxNode) -> Option<Self> { | ||
52 | std::iter::successors(Some(position.clone()), SyntaxNode::parent).find_map(Self::from) | ||
53 | } | ||
54 | |||
52 | pub fn as_syntax_node(&self) -> &SyntaxNode { | 55 | pub fn as_syntax_node(&self) -> &SyntaxNode { |
53 | match self { | 56 | match self { |
54 | ImportScope::File(file) => file.syntax(), | 57 | ImportScope::File(file) => file.syntax(), |
@@ -56,434 +59,32 @@ impl ImportScope { | |||
56 | } | 59 | } |
57 | } | 60 | } |
58 | 61 | ||
59 | fn indent_level(&self) -> IndentLevel { | 62 | pub fn clone_for_update(&self) -> Self { |
60 | match self { | 63 | match self { |
61 | ImportScope::File(file) => file.indent_level(), | 64 | ImportScope::File(file) => ImportScope::File(file.clone_for_update()), |
62 | ImportScope::Module(item_list) => item_list.indent_level() + 1, | 65 | ImportScope::Module(item_list) => ImportScope::Module(item_list.clone_for_update()), |
63 | } | 66 | } |
64 | } | 67 | } |
65 | |||
66 | fn first_insert_pos(&self) -> (InsertPosition<SyntaxElement>, AddBlankLine) { | ||
67 | match self { | ||
68 | ImportScope::File(_) => (InsertPosition::First, AddBlankLine::AfterTwice), | ||
69 | // don't insert the imports before the item list's opening curly brace | ||
70 | ImportScope::Module(item_list) => item_list | ||
71 | .l_curly_token() | ||
72 | .map(|b| (InsertPosition::After(b.into()), AddBlankLine::Around)) | ||
73 | .unwrap_or((InsertPosition::First, AddBlankLine::AfterTwice)), | ||
74 | } | ||
75 | } | ||
76 | |||
77 | fn insert_pos_after_last_inner_element(&self) -> (InsertPosition<SyntaxElement>, AddBlankLine) { | ||
78 | self.as_syntax_node() | ||
79 | .children_with_tokens() | ||
80 | .filter(|child| match child { | ||
81 | NodeOrToken::Node(node) => is_inner_attribute(node.clone()), | ||
82 | NodeOrToken::Token(token) => is_inner_comment(token.clone()), | ||
83 | }) | ||
84 | .last() | ||
85 | .map(|last_inner_element| { | ||
86 | (InsertPosition::After(last_inner_element), AddBlankLine::BeforeTwice) | ||
87 | }) | ||
88 | .unwrap_or_else(|| self.first_insert_pos()) | ||
89 | } | ||
90 | } | ||
91 | |||
92 | fn is_inner_attribute(node: SyntaxNode) -> bool { | ||
93 | ast::Attr::cast(node).map(|attr| attr.kind()) == Some(ast::AttrKind::Inner) | ||
94 | } | ||
95 | |||
96 | fn is_inner_comment(token: SyntaxToken) -> bool { | ||
97 | ast::Comment::cast(token).and_then(|comment| comment.kind().doc) | ||
98 | == Some(ast::CommentPlacement::Inner) | ||
99 | } | 68 | } |
100 | 69 | ||
101 | /// Insert an import path into the given file/node. A `merge` value of none indicates that no import merging is allowed to occur. | 70 | /// Insert an import path into the given file/node. A `merge` value of none indicates that no import merging is allowed to occur. |
102 | pub fn insert_use<'a>( | 71 | pub fn insert_use<'a>(scope: &ImportScope, path: ast::Path, cfg: InsertUseConfig) { |
103 | scope: &ImportScope, | ||
104 | path: ast::Path, | ||
105 | cfg: InsertUseConfig, | ||
106 | ) -> SyntaxRewriter<'a> { | ||
107 | let _p = profile::span("insert_use"); | 72 | let _p = profile::span("insert_use"); |
108 | let mut rewriter = SyntaxRewriter::default(); | 73 | let use_item = |
109 | let use_item = make::use_(None, make::use_tree(path.clone(), None, None, false)); | 74 | make::use_(None, make::use_tree(path.clone(), None, None, false)).clone_for_update(); |
110 | // merge into existing imports if possible | 75 | // merge into existing imports if possible |
111 | if let Some(mb) = cfg.merge { | 76 | if let Some(mb) = cfg.merge { |
112 | for existing_use in scope.as_syntax_node().children().filter_map(ast::Use::cast) { | 77 | for existing_use in scope.as_syntax_node().children().filter_map(ast::Use::cast) { |
113 | if let Some(merged) = try_merge_imports(&existing_use, &use_item, mb) { | 78 | if let Some(merged) = try_merge_imports(&existing_use, &use_item, mb) { |
114 | rewriter.replace(existing_use.syntax(), merged.syntax()); | 79 | ted::replace(existing_use.syntax(), merged.syntax()); |
115 | return rewriter; | 80 | return; |
116 | } | 81 | } |
117 | } | 82 | } |
118 | } | 83 | } |
119 | 84 | ||
120 | // either we weren't allowed to merge or there is no import that fits the merge conditions | 85 | // either we weren't allowed to merge or there is no import that fits the merge conditions |
121 | // so look for the place we have to insert to | 86 | // so look for the place we have to insert to |
122 | let (insert_position, add_blank) = find_insert_position(scope, path, cfg.group); | 87 | insert_use_(scope, path, cfg.group, use_item); |
123 | |||
124 | let indent = if let ident_level @ 1..=usize::MAX = scope.indent_level().0 as usize { | ||
125 | Some(make::tokens::whitespace(&" ".repeat(4 * ident_level)).into()) | ||
126 | } else { | ||
127 | None | ||
128 | }; | ||
129 | |||
130 | let to_insert: Vec<SyntaxElement> = { | ||
131 | let mut buf = Vec::new(); | ||
132 | |||
133 | match add_blank { | ||
134 | AddBlankLine::Before | AddBlankLine::Around => { | ||
135 | buf.push(make::tokens::single_newline().into()) | ||
136 | } | ||
137 | AddBlankLine::BeforeTwice => buf.push(make::tokens::blank_line().into()), | ||
138 | _ => (), | ||
139 | } | ||
140 | |||
141 | if add_blank.has_before() { | ||
142 | if let Some(indent) = indent.clone() { | ||
143 | cov_mark::hit!(insert_use_indent_before); | ||
144 | buf.push(indent); | ||
145 | } | ||
146 | } | ||
147 | |||
148 | buf.push(use_item.syntax().clone().into()); | ||
149 | |||
150 | match add_blank { | ||
151 | AddBlankLine::After | AddBlankLine::Around => { | ||
152 | buf.push(make::tokens::single_newline().into()) | ||
153 | } | ||
154 | AddBlankLine::AfterTwice => buf.push(make::tokens::blank_line().into()), | ||
155 | _ => (), | ||
156 | } | ||
157 | |||
158 | // only add indentation *after* our stuff if there's another node directly after it | ||
159 | if add_blank.has_after() && matches!(insert_position, InsertPosition::Before(_)) { | ||
160 | if let Some(indent) = indent { | ||
161 | cov_mark::hit!(insert_use_indent_after); | ||
162 | buf.push(indent); | ||
163 | } | ||
164 | } else if add_blank.has_after() && matches!(insert_position, InsertPosition::After(_)) { | ||
165 | cov_mark::hit!(insert_use_no_indent_after); | ||
166 | } | ||
167 | |||
168 | buf | ||
169 | }; | ||
170 | |||
171 | match insert_position { | ||
172 | InsertPosition::First => { | ||
173 | rewriter.insert_many_as_first_children(scope.as_syntax_node(), to_insert) | ||
174 | } | ||
175 | InsertPosition::Last => return rewriter, // actually unreachable | ||
176 | InsertPosition::Before(anchor) => rewriter.insert_many_before(&anchor, to_insert), | ||
177 | InsertPosition::After(anchor) => rewriter.insert_many_after(&anchor, to_insert), | ||
178 | } | ||
179 | rewriter | ||
180 | } | ||
181 | |||
182 | fn eq_visibility(vis0: Option<ast::Visibility>, vis1: Option<ast::Visibility>) -> bool { | ||
183 | match (vis0, vis1) { | ||
184 | (None, None) => true, | ||
185 | // FIXME: Don't use the string representation to check for equality | ||
186 | // spaces inside of the node would break this comparison | ||
187 | (Some(vis0), Some(vis1)) => vis0.to_string() == vis1.to_string(), | ||
188 | _ => false, | ||
189 | } | ||
190 | } | ||
191 | |||
192 | fn eq_attrs( | ||
193 | attrs0: impl Iterator<Item = ast::Attr>, | ||
194 | attrs1: impl Iterator<Item = ast::Attr>, | ||
195 | ) -> bool { | ||
196 | let attrs0 = attrs0.map(|attr| attr.to_string()); | ||
197 | let attrs1 = attrs1.map(|attr| attr.to_string()); | ||
198 | attrs0.eq(attrs1) | ||
199 | } | ||
200 | |||
201 | pub fn try_merge_imports( | ||
202 | lhs: &ast::Use, | ||
203 | rhs: &ast::Use, | ||
204 | merge_behavior: MergeBehavior, | ||
205 | ) -> Option<ast::Use> { | ||
206 | // don't merge imports with different visibilities | ||
207 | if !eq_visibility(lhs.visibility(), rhs.visibility()) { | ||
208 | return None; | ||
209 | } | ||
210 | if !eq_attrs(lhs.attrs(), rhs.attrs()) { | ||
211 | return None; | ||
212 | } | ||
213 | |||
214 | let lhs_tree = lhs.use_tree()?; | ||
215 | let rhs_tree = rhs.use_tree()?; | ||
216 | let merged = try_merge_trees(&lhs_tree, &rhs_tree, merge_behavior)?; | ||
217 | Some(lhs.with_use_tree(merged).clone_for_update()) | ||
218 | } | ||
219 | |||
220 | pub fn try_merge_trees( | ||
221 | lhs: &ast::UseTree, | ||
222 | rhs: &ast::UseTree, | ||
223 | merge: MergeBehavior, | ||
224 | ) -> Option<ast::UseTree> { | ||
225 | let lhs_path = lhs.path()?; | ||
226 | let rhs_path = rhs.path()?; | ||
227 | |||
228 | let (lhs_prefix, rhs_prefix) = common_prefix(&lhs_path, &rhs_path)?; | ||
229 | let (lhs, rhs) = if is_simple_path(lhs) | ||
230 | && is_simple_path(rhs) | ||
231 | && lhs_path == lhs_prefix | ||
232 | && rhs_path == rhs_prefix | ||
233 | { | ||
234 | (lhs.clone(), rhs.clone()) | ||
235 | } else { | ||
236 | (lhs.split_prefix(&lhs_prefix), rhs.split_prefix(&rhs_prefix)) | ||
237 | }; | ||
238 | recursive_merge(&lhs, &rhs, merge).map(|it| it.clone_for_update()) | ||
239 | } | ||
240 | |||
241 | /// Recursively "zips" together lhs and rhs. | ||
242 | fn recursive_merge( | ||
243 | lhs: &ast::UseTree, | ||
244 | rhs: &ast::UseTree, | ||
245 | merge: MergeBehavior, | ||
246 | ) -> Option<ast::UseTree> { | ||
247 | let mut use_trees = lhs | ||
248 | .use_tree_list() | ||
249 | .into_iter() | ||
250 | .flat_map(|list| list.use_trees()) | ||
251 | // we use Option here to early return from this function(this is not the same as a `filter` op) | ||
252 | .map(|tree| match merge.is_tree_allowed(&tree) { | ||
253 | true => Some(tree), | ||
254 | false => None, | ||
255 | }) | ||
256 | .collect::<Option<Vec<_>>>()?; | ||
257 | use_trees.sort_unstable_by(|a, b| path_cmp_for_sort(a.path(), b.path())); | ||
258 | for rhs_t in rhs.use_tree_list().into_iter().flat_map(|list| list.use_trees()) { | ||
259 | if !merge.is_tree_allowed(&rhs_t) { | ||
260 | return None; | ||
261 | } | ||
262 | let rhs_path = rhs_t.path(); | ||
263 | match use_trees.binary_search_by(|lhs_t| { | ||
264 | let (lhs_t, rhs_t) = match lhs_t | ||
265 | .path() | ||
266 | .zip(rhs_path.clone()) | ||
267 | .and_then(|(lhs, rhs)| common_prefix(&lhs, &rhs)) | ||
268 | { | ||
269 | Some((lhs_p, rhs_p)) => (lhs_t.split_prefix(&lhs_p), rhs_t.split_prefix(&rhs_p)), | ||
270 | None => (lhs_t.clone(), rhs_t.clone()), | ||
271 | }; | ||
272 | |||
273 | path_cmp_bin_search(lhs_t.path(), rhs_t.path()) | ||
274 | }) { | ||
275 | Ok(idx) => { | ||
276 | let lhs_t = &mut use_trees[idx]; | ||
277 | let lhs_path = lhs_t.path()?; | ||
278 | let rhs_path = rhs_path?; | ||
279 | let (lhs_prefix, rhs_prefix) = common_prefix(&lhs_path, &rhs_path)?; | ||
280 | if lhs_prefix == lhs_path && rhs_prefix == rhs_path { | ||
281 | let tree_is_self = |tree: ast::UseTree| { | ||
282 | tree.path().as_ref().map(path_is_self).unwrap_or(false) | ||
283 | }; | ||
284 | // check if only one of the two trees has a tree list, and whether that then contains `self` or not. | ||
285 | // If this is the case we can skip this iteration since the path without the list is already included in the other one via `self` | ||
286 | let tree_contains_self = |tree: &ast::UseTree| { | ||
287 | tree.use_tree_list() | ||
288 | .map(|tree_list| tree_list.use_trees().any(tree_is_self)) | ||
289 | .unwrap_or(false) | ||
290 | }; | ||
291 | match (tree_contains_self(&lhs_t), tree_contains_self(&rhs_t)) { | ||
292 | (true, false) => continue, | ||
293 | (false, true) => { | ||
294 | *lhs_t = rhs_t; | ||
295 | continue; | ||
296 | } | ||
297 | _ => (), | ||
298 | } | ||
299 | |||
300 | // glob imports arent part of the use-tree lists so we need to special handle them here as well | ||
301 | // this special handling is only required for when we merge a module import into a glob import of said module | ||
302 | // see the `merge_self_glob` or `merge_mod_into_glob` tests | ||
303 | if lhs_t.star_token().is_some() || rhs_t.star_token().is_some() { | ||
304 | *lhs_t = make::use_tree( | ||
305 | make::path_unqualified(make::path_segment_self()), | ||
306 | None, | ||
307 | None, | ||
308 | false, | ||
309 | ); | ||
310 | use_trees.insert(idx, make::glob_use_tree()); | ||
311 | continue; | ||
312 | } | ||
313 | |||
314 | if lhs_t.use_tree_list().is_none() && rhs_t.use_tree_list().is_none() { | ||
315 | continue; | ||
316 | } | ||
317 | } | ||
318 | let lhs = lhs_t.split_prefix(&lhs_prefix); | ||
319 | let rhs = rhs_t.split_prefix(&rhs_prefix); | ||
320 | match recursive_merge(&lhs, &rhs, merge) { | ||
321 | Some(use_tree) => use_trees[idx] = use_tree, | ||
322 | None => return None, | ||
323 | } | ||
324 | } | ||
325 | Err(_) | ||
326 | if merge == MergeBehavior::Last | ||
327 | && use_trees.len() > 0 | ||
328 | && rhs_t.use_tree_list().is_some() => | ||
329 | { | ||
330 | return None | ||
331 | } | ||
332 | Err(idx) => { | ||
333 | use_trees.insert(idx, rhs_t); | ||
334 | } | ||
335 | } | ||
336 | } | ||
337 | Some(lhs.with_use_tree_list(make::use_tree_list(use_trees))) | ||
338 | } | ||
339 | |||
340 | /// Traverses both paths until they differ, returning the common prefix of both. | ||
341 | fn common_prefix(lhs: &ast::Path, rhs: &ast::Path) -> Option<(ast::Path, ast::Path)> { | ||
342 | let mut res = None; | ||
343 | let mut lhs_curr = first_path(&lhs); | ||
344 | let mut rhs_curr = first_path(&rhs); | ||
345 | loop { | ||
346 | match (lhs_curr.segment(), rhs_curr.segment()) { | ||
347 | (Some(lhs), Some(rhs)) if lhs.syntax().text() == rhs.syntax().text() => (), | ||
348 | _ => break res, | ||
349 | } | ||
350 | res = Some((lhs_curr.clone(), rhs_curr.clone())); | ||
351 | |||
352 | match lhs_curr.parent_path().zip(rhs_curr.parent_path()) { | ||
353 | Some((lhs, rhs)) => { | ||
354 | lhs_curr = lhs; | ||
355 | rhs_curr = rhs; | ||
356 | } | ||
357 | _ => break res, | ||
358 | } | ||
359 | } | ||
360 | } | ||
361 | |||
362 | fn is_simple_path(use_tree: &ast::UseTree) -> bool { | ||
363 | use_tree.use_tree_list().is_none() && use_tree.star_token().is_none() | ||
364 | } | ||
365 | |||
366 | fn path_is_self(path: &ast::Path) -> bool { | ||
367 | path.segment().and_then(|seg| seg.self_token()).is_some() && path.qualifier().is_none() | ||
368 | } | ||
369 | |||
370 | #[inline] | ||
371 | fn first_segment(path: &ast::Path) -> Option<ast::PathSegment> { | ||
372 | first_path(path).segment() | ||
373 | } | ||
374 | |||
375 | fn first_path(path: &ast::Path) -> ast::Path { | ||
376 | successors(Some(path.clone()), ast::Path::qualifier).last().unwrap() | ||
377 | } | ||
378 | |||
379 | fn segment_iter(path: &ast::Path) -> impl Iterator<Item = ast::PathSegment> + Clone { | ||
380 | // cant make use of SyntaxNode::siblings, because the returned Iterator is not clone | ||
381 | successors(first_segment(path), |p| p.parent_path().parent_path().and_then(|p| p.segment())) | ||
382 | } | ||
383 | |||
384 | fn path_len(path: ast::Path) -> usize { | ||
385 | segment_iter(&path).count() | ||
386 | } | ||
387 | |||
388 | /// Orders paths in the following way: | ||
389 | /// the sole self token comes first, after that come uppercase identifiers, then lowercase identifiers | ||
390 | // FIXME: rustfmt sorts lowercase idents before uppercase, in general we want to have the same ordering rustfmt has | ||
391 | // which is `self` and `super` first, then identifier imports with lowercase ones first, then glob imports and at last list imports. | ||
392 | // Example foo::{self, foo, baz, Baz, Qux, *, {Bar}} | ||
393 | fn path_cmp_for_sort(a: Option<ast::Path>, b: Option<ast::Path>) -> Ordering { | ||
394 | match (a, b) { | ||
395 | (None, None) => Ordering::Equal, | ||
396 | (None, Some(_)) => Ordering::Less, | ||
397 | (Some(_), None) => Ordering::Greater, | ||
398 | (Some(ref a), Some(ref b)) => match (path_is_self(a), path_is_self(b)) { | ||
399 | (true, true) => Ordering::Equal, | ||
400 | (true, false) => Ordering::Less, | ||
401 | (false, true) => Ordering::Greater, | ||
402 | (false, false) => path_cmp_short(a, b), | ||
403 | }, | ||
404 | } | ||
405 | } | ||
406 | |||
407 | /// Path comparison func for binary searching for merging. | ||
408 | fn path_cmp_bin_search(lhs: Option<ast::Path>, rhs: Option<ast::Path>) -> Ordering { | ||
409 | match (lhs.as_ref().and_then(first_segment), rhs.as_ref().and_then(first_segment)) { | ||
410 | (None, None) => Ordering::Equal, | ||
411 | (None, Some(_)) => Ordering::Less, | ||
412 | (Some(_), None) => Ordering::Greater, | ||
413 | (Some(ref a), Some(ref b)) => path_segment_cmp(a, b), | ||
414 | } | ||
415 | } | ||
416 | |||
417 | /// Short circuiting comparison, if both paths are equal until one of them ends they are considered | ||
418 | /// equal | ||
419 | fn path_cmp_short(a: &ast::Path, b: &ast::Path) -> Ordering { | ||
420 | let a = segment_iter(a); | ||
421 | let b = segment_iter(b); | ||
422 | // cmp_by would be useful for us here but that is currently unstable | ||
423 | // cmp doesnt work due the lifetimes on text's return type | ||
424 | a.zip(b) | ||
425 | .find_map(|(a, b)| match path_segment_cmp(&a, &b) { | ||
426 | Ordering::Equal => None, | ||
427 | ord => Some(ord), | ||
428 | }) | ||
429 | .unwrap_or(Ordering::Equal) | ||
430 | } | ||
431 | |||
432 | /// Compares to paths, if one ends earlier than the other the has_tl parameters decide which is | ||
433 | /// greater as a a path that has a tree list should be greater, while one that just ends without | ||
434 | /// a tree list should be considered less. | ||
435 | fn use_tree_path_cmp(a: &ast::Path, a_has_tl: bool, b: &ast::Path, b_has_tl: bool) -> Ordering { | ||
436 | let a_segments = segment_iter(a); | ||
437 | let b_segments = segment_iter(b); | ||
438 | // cmp_by would be useful for us here but that is currently unstable | ||
439 | // cmp doesnt work due the lifetimes on text's return type | ||
440 | a_segments | ||
441 | .zip_longest(b_segments) | ||
442 | .find_map(|zipped| match zipped { | ||
443 | EitherOrBoth::Both(ref a, ref b) => match path_segment_cmp(a, b) { | ||
444 | Ordering::Equal => None, | ||
445 | ord => Some(ord), | ||
446 | }, | ||
447 | EitherOrBoth::Left(_) if !b_has_tl => Some(Ordering::Greater), | ||
448 | EitherOrBoth::Left(_) => Some(Ordering::Less), | ||
449 | EitherOrBoth::Right(_) if !a_has_tl => Some(Ordering::Less), | ||
450 | EitherOrBoth::Right(_) => Some(Ordering::Greater), | ||
451 | }) | ||
452 | .unwrap_or(Ordering::Equal) | ||
453 | } | ||
454 | |||
455 | fn path_segment_cmp(a: &ast::PathSegment, b: &ast::PathSegment) -> Ordering { | ||
456 | let a = a.kind().and_then(|kind| match kind { | ||
457 | PathSegmentKind::Name(name_ref) => Some(name_ref), | ||
458 | _ => None, | ||
459 | }); | ||
460 | let b = b.kind().and_then(|kind| match kind { | ||
461 | PathSegmentKind::Name(name_ref) => Some(name_ref), | ||
462 | _ => None, | ||
463 | }); | ||
464 | a.as_ref().map(ast::NameRef::text).cmp(&b.as_ref().map(ast::NameRef::text)) | ||
465 | } | ||
466 | |||
467 | /// What type of merges are allowed. | ||
468 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] | ||
469 | pub enum MergeBehavior { | ||
470 | /// Merge everything together creating deeply nested imports. | ||
471 | Full, | ||
472 | /// Only merge the last import level, doesn't allow import nesting. | ||
473 | Last, | ||
474 | } | ||
475 | |||
476 | impl MergeBehavior { | ||
477 | #[inline] | ||
478 | fn is_tree_allowed(&self, tree: &ast::UseTree) -> bool { | ||
479 | match self { | ||
480 | MergeBehavior::Full => true, | ||
481 | // only simple single segment paths are allowed | ||
482 | MergeBehavior::Last => { | ||
483 | tree.use_tree_list().is_none() && tree.path().map(path_len) <= Some(1) | ||
484 | } | ||
485 | } | ||
486 | } | ||
487 | } | 88 | } |
488 | 89 | ||
489 | #[derive(Eq, PartialEq, PartialOrd, Ord)] | 90 | #[derive(Eq, PartialEq, PartialOrd, Ord)] |
@@ -500,7 +101,7 @@ impl ImportGroup { | |||
500 | fn new(path: &ast::Path) -> ImportGroup { | 101 | fn new(path: &ast::Path) -> ImportGroup { |
501 | let default = ImportGroup::ExternCrate; | 102 | let default = ImportGroup::ExternCrate; |
502 | 103 | ||
503 | let first_segment = match first_segment(path) { | 104 | let first_segment = match path.first_segment() { |
504 | Some(it) => it, | 105 | Some(it) => it, |
505 | None => return default, | 106 | None => return default, |
506 | }; | 107 | }; |
@@ -520,32 +121,15 @@ impl ImportGroup { | |||
520 | } | 121 | } |
521 | } | 122 | } |
522 | 123 | ||
523 | #[derive(PartialEq, Eq)] | 124 | fn insert_use_( |
524 | enum AddBlankLine { | ||
525 | Before, | ||
526 | BeforeTwice, | ||
527 | Around, | ||
528 | After, | ||
529 | AfterTwice, | ||
530 | } | ||
531 | |||
532 | impl AddBlankLine { | ||
533 | fn has_before(&self) -> bool { | ||
534 | matches!(self, AddBlankLine::Before | AddBlankLine::BeforeTwice | AddBlankLine::Around) | ||
535 | } | ||
536 | fn has_after(&self) -> bool { | ||
537 | matches!(self, AddBlankLine::After | AddBlankLine::AfterTwice | AddBlankLine::Around) | ||
538 | } | ||
539 | } | ||
540 | |||
541 | fn find_insert_position( | ||
542 | scope: &ImportScope, | 125 | scope: &ImportScope, |
543 | insert_path: ast::Path, | 126 | insert_path: ast::Path, |
544 | group_imports: bool, | 127 | group_imports: bool, |
545 | ) -> (InsertPosition<SyntaxElement>, AddBlankLine) { | 128 | use_item: ast::Use, |
129 | ) { | ||
130 | let scope_syntax = scope.as_syntax_node(); | ||
546 | let group = ImportGroup::new(&insert_path); | 131 | let group = ImportGroup::new(&insert_path); |
547 | let path_node_iter = scope | 132 | let path_node_iter = scope_syntax |
548 | .as_syntax_node() | ||
549 | .children() | 133 | .children() |
550 | .filter_map(|node| ast::Use::cast(node.clone()).zip(Some(node))) | 134 | .filter_map(|node| ast::Use::cast(node.clone()).zip(Some(node))) |
551 | .flat_map(|(use_, node)| { | 135 | .flat_map(|(use_, node)| { |
@@ -557,9 +141,14 @@ fn find_insert_position( | |||
557 | 141 | ||
558 | if !group_imports { | 142 | if !group_imports { |
559 | if let Some((_, _, node)) = path_node_iter.last() { | 143 | if let Some((_, _, node)) = path_node_iter.last() { |
560 | return (InsertPosition::After(node.into()), AddBlankLine::Before); | 144 | cov_mark::hit!(insert_no_grouping_last); |
145 | ted::insert(ted::Position::after(node), use_item.syntax()); | ||
146 | } else { | ||
147 | cov_mark::hit!(insert_no_grouping_last2); | ||
148 | ted::insert(ted::Position::first_child_of(scope_syntax), make::tokens::blank_line()); | ||
149 | ted::insert(ted::Position::first_child_of(scope_syntax), use_item.syntax()); | ||
561 | } | 150 | } |
562 | return (InsertPosition::First, AddBlankLine::AfterTwice); | 151 | return; |
563 | } | 152 | } |
564 | 153 | ||
565 | // Iterator that discards anything thats not in the required grouping | 154 | // Iterator that discards anything thats not in the required grouping |
@@ -572,43 +161,91 @@ fn find_insert_position( | |||
572 | // track the last element we iterated over, if this is still None after the iteration then that means we never iterated in the first place | 161 | // track the last element we iterated over, if this is still None after the iteration then that means we never iterated in the first place |
573 | let mut last = None; | 162 | let mut last = None; |
574 | // find the element that would come directly after our new import | 163 | // find the element that would come directly after our new import |
575 | let post_insert = group_iter.inspect(|(.., node)| last = Some(node.clone())).find( | 164 | let post_insert: Option<(_, _, SyntaxNode)> = group_iter |
576 | |&(ref path, has_tl, _)| { | 165 | .inspect(|(.., node)| last = Some(node.clone())) |
166 | .find(|&(ref path, has_tl, _)| { | ||
577 | use_tree_path_cmp(&insert_path, false, path, has_tl) != Ordering::Greater | 167 | use_tree_path_cmp(&insert_path, false, path, has_tl) != Ordering::Greater |
578 | }, | 168 | }); |
579 | ); | ||
580 | 169 | ||
581 | match post_insert { | 170 | if let Some((.., node)) = post_insert { |
171 | cov_mark::hit!(insert_group); | ||
582 | // insert our import before that element | 172 | // insert our import before that element |
583 | Some((.., node)) => (InsertPosition::Before(node.into()), AddBlankLine::After), | 173 | return ted::insert(ted::Position::before(node), use_item.syntax()); |
174 | } | ||
175 | if let Some(node) = last { | ||
176 | cov_mark::hit!(insert_group_last); | ||
584 | // there is no element after our new import, so append it to the end of the group | 177 | // there is no element after our new import, so append it to the end of the group |
585 | None => match last { | 178 | return ted::insert(ted::Position::after(node), use_item.syntax()); |
586 | Some(node) => (InsertPosition::After(node.into()), AddBlankLine::Before), | 179 | } |
587 | // the group we were looking for actually doesnt exist, so insert | 180 | |
181 | // the group we were looking for actually doesn't exist, so insert | ||
182 | |||
183 | let mut last = None; | ||
184 | // find the group that comes after where we want to insert | ||
185 | let post_group = path_node_iter | ||
186 | .inspect(|(.., node)| last = Some(node.clone())) | ||
187 | .find(|(p, ..)| ImportGroup::new(p) > group); | ||
188 | if let Some((.., node)) = post_group { | ||
189 | cov_mark::hit!(insert_group_new_group); | ||
190 | ted::insert(ted::Position::before(&node), use_item.syntax()); | ||
191 | if let Some(node) = algo::non_trivia_sibling(node.into(), Direction::Prev) { | ||
192 | ted::insert(ted::Position::after(node), make::tokens::single_newline()); | ||
193 | } | ||
194 | return; | ||
195 | } | ||
196 | // there is no such group, so append after the last one | ||
197 | if let Some(node) = last { | ||
198 | cov_mark::hit!(insert_group_no_group); | ||
199 | ted::insert(ted::Position::after(&node), use_item.syntax()); | ||
200 | ted::insert(ted::Position::after(node), make::tokens::single_newline()); | ||
201 | return; | ||
202 | } | ||
203 | // there are no imports in this file at all | ||
204 | if let Some(last_inner_element) = scope_syntax | ||
205 | .children_with_tokens() | ||
206 | .filter(|child| match child { | ||
207 | NodeOrToken::Node(node) => is_inner_attribute(node.clone()), | ||
208 | NodeOrToken::Token(token) => is_inner_comment(token.clone()), | ||
209 | }) | ||
210 | .last() | ||
211 | { | ||
212 | cov_mark::hit!(insert_group_empty_inner_attr); | ||
213 | ted::insert(ted::Position::after(&last_inner_element), use_item.syntax()); | ||
214 | ted::insert(ted::Position::after(last_inner_element), make::tokens::single_newline()); | ||
215 | return; | ||
216 | } | ||
217 | match scope { | ||
218 | ImportScope::File(_) => { | ||
219 | cov_mark::hit!(insert_group_empty_file); | ||
220 | ted::insert(ted::Position::first_child_of(scope_syntax), make::tokens::blank_line()); | ||
221 | ted::insert(ted::Position::first_child_of(scope_syntax), use_item.syntax()) | ||
222 | } | ||
223 | // don't insert the imports before the item list's opening curly brace | ||
224 | ImportScope::Module(item_list) => match item_list.l_curly_token() { | ||
225 | Some(b) => { | ||
226 | cov_mark::hit!(insert_group_empty_module); | ||
227 | ted::insert(ted::Position::after(&b), make::tokens::single_newline()); | ||
228 | ted::insert(ted::Position::after(&b), use_item.syntax()); | ||
229 | } | ||
588 | None => { | 230 | None => { |
589 | // similar concept here to the `last` from above | 231 | // This should never happens, broken module syntax node |
590 | let mut last = None; | 232 | ted::insert( |
591 | // find the group that comes after where we want to insert | 233 | ted::Position::first_child_of(scope_syntax), |
592 | let post_group = path_node_iter | 234 | make::tokens::blank_line(), |
593 | .inspect(|(.., node)| last = Some(node.clone())) | 235 | ); |
594 | .find(|(p, ..)| ImportGroup::new(p) > group); | 236 | ted::insert(ted::Position::first_child_of(scope_syntax), use_item.syntax()); |
595 | match post_group { | ||
596 | Some((.., node)) => { | ||
597 | (InsertPosition::Before(node.into()), AddBlankLine::AfterTwice) | ||
598 | } | ||
599 | // there is no such group, so append after the last one | ||
600 | None => match last { | ||
601 | Some(node) => { | ||
602 | (InsertPosition::After(node.into()), AddBlankLine::BeforeTwice) | ||
603 | } | ||
604 | // there are no imports in this file at all | ||
605 | None => scope.insert_pos_after_last_inner_element(), | ||
606 | }, | ||
607 | } | ||
608 | } | 237 | } |
609 | }, | 238 | }, |
610 | } | 239 | } |
611 | } | 240 | } |
612 | 241 | ||
242 | fn is_inner_attribute(node: SyntaxNode) -> bool { | ||
243 | ast::Attr::cast(node).map(|attr| attr.kind()) == Some(ast::AttrKind::Inner) | ||
244 | } | ||
245 | |||
246 | fn is_inner_comment(token: SyntaxToken) -> bool { | ||
247 | ast::Comment::cast(token).and_then(|comment| comment.kind().doc) | ||
248 | == Some(ast::CommentPlacement::Inner) | ||
249 | } | ||
613 | #[cfg(test)] | 250 | #[cfg(test)] |
614 | mod tests; | 251 | mod tests; |
diff --git a/crates/ide_db/src/helpers/insert_use/tests.rs b/crates/ide_db/src/helpers/insert_use/tests.rs index 3d151e629..048c213e2 100644 --- a/crates/ide_db/src/helpers/insert_use/tests.rs +++ b/crates/ide_db/src/helpers/insert_use/tests.rs | |||
@@ -5,6 +5,7 @@ use test_utils::assert_eq_text; | |||
5 | 5 | ||
6 | #[test] | 6 | #[test] |
7 | fn insert_not_group() { | 7 | fn insert_not_group() { |
8 | cov_mark::check!(insert_no_grouping_last); | ||
8 | check( | 9 | check( |
9 | "use external_crate2::bar::A", | 10 | "use external_crate2::bar::A", |
10 | r" | 11 | r" |
@@ -27,6 +28,21 @@ use external_crate2::bar::A;", | |||
27 | } | 28 | } |
28 | 29 | ||
29 | #[test] | 30 | #[test] |
31 | fn insert_not_group_empty() { | ||
32 | cov_mark::check!(insert_no_grouping_last2); | ||
33 | check( | ||
34 | "use external_crate2::bar::A", | ||
35 | r"", | ||
36 | r"use external_crate2::bar::A; | ||
37 | |||
38 | ", | ||
39 | None, | ||
40 | false, | ||
41 | false, | ||
42 | ); | ||
43 | } | ||
44 | |||
45 | #[test] | ||
30 | fn insert_existing() { | 46 | fn insert_existing() { |
31 | check_full("std::fs", "use std::fs;", "use std::fs;") | 47 | check_full("std::fs", "use std::fs;", "use std::fs;") |
32 | } | 48 | } |
@@ -51,21 +67,21 @@ use std::bar::G;", | |||
51 | 67 | ||
52 | #[test] | 68 | #[test] |
53 | fn insert_start_indent() { | 69 | fn insert_start_indent() { |
54 | cov_mark::check!(insert_use_indent_after); | ||
55 | check_none( | 70 | check_none( |
56 | "std::bar::AA", | 71 | "std::bar::AA", |
57 | r" | 72 | r" |
58 | use std::bar::B; | 73 | use std::bar::B; |
59 | use std::bar::D;", | 74 | use std::bar::C;", |
60 | r" | 75 | r" |
61 | use std::bar::AA; | 76 | use std::bar::AA; |
62 | use std::bar::B; | 77 | use std::bar::B; |
63 | use std::bar::D;", | 78 | use std::bar::C;", |
64 | ) | 79 | ); |
65 | } | 80 | } |
66 | 81 | ||
67 | #[test] | 82 | #[test] |
68 | fn insert_middle() { | 83 | fn insert_middle() { |
84 | cov_mark::check!(insert_group); | ||
69 | check_none( | 85 | check_none( |
70 | "std::bar::EE", | 86 | "std::bar::EE", |
71 | r" | 87 | r" |
@@ -102,6 +118,7 @@ fn insert_middle_indent() { | |||
102 | 118 | ||
103 | #[test] | 119 | #[test] |
104 | fn insert_end() { | 120 | fn insert_end() { |
121 | cov_mark::check!(insert_group_last); | ||
105 | check_none( | 122 | check_none( |
106 | "std::bar::ZZ", | 123 | "std::bar::ZZ", |
107 | r" | 124 | r" |
@@ -120,7 +137,6 @@ use std::bar::ZZ;", | |||
120 | 137 | ||
121 | #[test] | 138 | #[test] |
122 | fn insert_end_indent() { | 139 | fn insert_end_indent() { |
123 | cov_mark::check!(insert_use_indent_before); | ||
124 | check_none( | 140 | check_none( |
125 | "std::bar::ZZ", | 141 | "std::bar::ZZ", |
126 | r" | 142 | r" |
@@ -201,6 +217,7 @@ fn insert_first_matching_group() { | |||
201 | 217 | ||
202 | #[test] | 218 | #[test] |
203 | fn insert_missing_group_std() { | 219 | fn insert_missing_group_std() { |
220 | cov_mark::check!(insert_group_new_group); | ||
204 | check_none( | 221 | check_none( |
205 | "std::fmt", | 222 | "std::fmt", |
206 | r" | 223 | r" |
@@ -216,6 +233,7 @@ fn insert_missing_group_std() { | |||
216 | 233 | ||
217 | #[test] | 234 | #[test] |
218 | fn insert_missing_group_self() { | 235 | fn insert_missing_group_self() { |
236 | cov_mark::check!(insert_group_no_group); | ||
219 | check_none( | 237 | check_none( |
220 | "self::fmt", | 238 | "self::fmt", |
221 | r" | 239 | r" |
@@ -242,6 +260,7 @@ fn main() {}", | |||
242 | 260 | ||
243 | #[test] | 261 | #[test] |
244 | fn insert_empty_file() { | 262 | fn insert_empty_file() { |
263 | cov_mark::check!(insert_group_empty_file); | ||
245 | // empty files will get two trailing newlines | 264 | // empty files will get two trailing newlines |
246 | // this is due to the test case insert_no_imports above | 265 | // this is due to the test case insert_no_imports above |
247 | check_full( | 266 | check_full( |
@@ -255,7 +274,7 @@ fn insert_empty_file() { | |||
255 | 274 | ||
256 | #[test] | 275 | #[test] |
257 | fn insert_empty_module() { | 276 | fn insert_empty_module() { |
258 | cov_mark::check!(insert_use_no_indent_after); | 277 | cov_mark::check!(insert_group_empty_module); |
259 | check( | 278 | check( |
260 | "foo::bar", | 279 | "foo::bar", |
261 | "mod x {}", | 280 | "mod x {}", |
@@ -270,6 +289,7 @@ fn insert_empty_module() { | |||
270 | 289 | ||
271 | #[test] | 290 | #[test] |
272 | fn insert_after_inner_attr() { | 291 | fn insert_after_inner_attr() { |
292 | cov_mark::check!(insert_group_empty_inner_attr); | ||
273 | check_full( | 293 | check_full( |
274 | "foo::bar", | 294 | "foo::bar", |
275 | r"#![allow(unused_imports)]", | 295 | r"#![allow(unused_imports)]", |
@@ -615,7 +635,7 @@ fn check( | |||
615 | if module { | 635 | if module { |
616 | syntax = syntax.descendants().find_map(ast::Module::cast).unwrap().syntax().clone(); | 636 | syntax = syntax.descendants().find_map(ast::Module::cast).unwrap().syntax().clone(); |
617 | } | 637 | } |
618 | let file = super::ImportScope::from(syntax).unwrap(); | 638 | let file = super::ImportScope::from(syntax.clone_for_update()).unwrap(); |
619 | let path = ast::SourceFile::parse(&format!("use {};", path)) | 639 | let path = ast::SourceFile::parse(&format!("use {};", path)) |
620 | .tree() | 640 | .tree() |
621 | .syntax() | 641 | .syntax() |
@@ -623,12 +643,8 @@ fn check( | |||
623 | .find_map(ast::Path::cast) | 643 | .find_map(ast::Path::cast) |
624 | .unwrap(); | 644 | .unwrap(); |
625 | 645 | ||
626 | let rewriter = insert_use( | 646 | insert_use(&file, path, InsertUseConfig { merge: mb, prefix_kind: PrefixKind::Plain, group }); |
627 | &file, | 647 | let result = file.as_syntax_node().to_string(); |
628 | path, | ||
629 | InsertUseConfig { merge: mb, prefix_kind: PrefixKind::Plain, group }, | ||
630 | ); | ||
631 | let result = rewriter.rewrite(file.as_syntax_node()).to_string(); | ||
632 | assert_eq_text!(ra_fixture_after, &result); | 648 | assert_eq_text!(ra_fixture_after, &result); |
633 | } | 649 | } |
634 | 650 | ||
diff --git a/crates/ide_db/src/helpers/merge_imports.rs b/crates/ide_db/src/helpers/merge_imports.rs new file mode 100644 index 000000000..3f5bbef7f --- /dev/null +++ b/crates/ide_db/src/helpers/merge_imports.rs | |||
@@ -0,0 +1,309 @@ | |||
1 | //! Handle syntactic aspects of merging UseTrees. | ||
2 | use std::cmp::Ordering; | ||
3 | |||
4 | use itertools::{EitherOrBoth, Itertools}; | ||
5 | use syntax::ast::{ | ||
6 | self, edit::AstNodeEdit, make, AstNode, AttrsOwner, PathSegmentKind, VisibilityOwner, | ||
7 | }; | ||
8 | |||
9 | /// What type of merges are allowed. | ||
10 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] | ||
11 | pub enum MergeBehavior { | ||
12 | /// Merge everything together creating deeply nested imports. | ||
13 | Full, | ||
14 | /// Only merge the last import level, doesn't allow import nesting. | ||
15 | Last, | ||
16 | } | ||
17 | |||
18 | impl MergeBehavior { | ||
19 | #[inline] | ||
20 | fn is_tree_allowed(&self, tree: &ast::UseTree) -> bool { | ||
21 | match self { | ||
22 | MergeBehavior::Full => true, | ||
23 | // only simple single segment paths are allowed | ||
24 | MergeBehavior::Last => { | ||
25 | tree.use_tree_list().is_none() && tree.path().map(path_len) <= Some(1) | ||
26 | } | ||
27 | } | ||
28 | } | ||
29 | } | ||
30 | |||
31 | pub fn try_merge_imports( | ||
32 | lhs: &ast::Use, | ||
33 | rhs: &ast::Use, | ||
34 | merge_behavior: MergeBehavior, | ||
35 | ) -> Option<ast::Use> { | ||
36 | // don't merge imports with different visibilities | ||
37 | if !eq_visibility(lhs.visibility(), rhs.visibility()) { | ||
38 | return None; | ||
39 | } | ||
40 | if !eq_attrs(lhs.attrs(), rhs.attrs()) { | ||
41 | return None; | ||
42 | } | ||
43 | |||
44 | let lhs_tree = lhs.use_tree()?; | ||
45 | let rhs_tree = rhs.use_tree()?; | ||
46 | let merged = try_merge_trees(&lhs_tree, &rhs_tree, merge_behavior)?; | ||
47 | Some(lhs.with_use_tree(merged).clone_for_update()) | ||
48 | } | ||
49 | |||
50 | pub fn try_merge_trees( | ||
51 | lhs: &ast::UseTree, | ||
52 | rhs: &ast::UseTree, | ||
53 | merge: MergeBehavior, | ||
54 | ) -> Option<ast::UseTree> { | ||
55 | let lhs_path = lhs.path()?; | ||
56 | let rhs_path = rhs.path()?; | ||
57 | |||
58 | let (lhs_prefix, rhs_prefix) = common_prefix(&lhs_path, &rhs_path)?; | ||
59 | let (lhs, rhs) = if lhs.is_simple_path() | ||
60 | && rhs.is_simple_path() | ||
61 | && lhs_path == lhs_prefix | ||
62 | && rhs_path == rhs_prefix | ||
63 | { | ||
64 | (lhs.clone(), rhs.clone()) | ||
65 | } else { | ||
66 | (lhs.split_prefix(&lhs_prefix), rhs.split_prefix(&rhs_prefix)) | ||
67 | }; | ||
68 | recursive_merge(&lhs, &rhs, merge) | ||
69 | } | ||
70 | |||
71 | /// Recursively "zips" together lhs and rhs. | ||
72 | fn recursive_merge( | ||
73 | lhs: &ast::UseTree, | ||
74 | rhs: &ast::UseTree, | ||
75 | merge: MergeBehavior, | ||
76 | ) -> Option<ast::UseTree> { | ||
77 | let mut use_trees = lhs | ||
78 | .use_tree_list() | ||
79 | .into_iter() | ||
80 | .flat_map(|list| list.use_trees()) | ||
81 | // we use Option here to early return from this function(this is not the same as a `filter` op) | ||
82 | .map(|tree| match merge.is_tree_allowed(&tree) { | ||
83 | true => Some(tree), | ||
84 | false => None, | ||
85 | }) | ||
86 | .collect::<Option<Vec<_>>>()?; | ||
87 | use_trees.sort_unstable_by(|a, b| path_cmp_for_sort(a.path(), b.path())); | ||
88 | for rhs_t in rhs.use_tree_list().into_iter().flat_map(|list| list.use_trees()) { | ||
89 | if !merge.is_tree_allowed(&rhs_t) { | ||
90 | return None; | ||
91 | } | ||
92 | let rhs_path = rhs_t.path(); | ||
93 | match use_trees.binary_search_by(|lhs_t| { | ||
94 | let (lhs_t, rhs_t) = match lhs_t | ||
95 | .path() | ||
96 | .zip(rhs_path.clone()) | ||
97 | .and_then(|(lhs, rhs)| common_prefix(&lhs, &rhs)) | ||
98 | { | ||
99 | Some((lhs_p, rhs_p)) => (lhs_t.split_prefix(&lhs_p), rhs_t.split_prefix(&rhs_p)), | ||
100 | None => (lhs_t.clone(), rhs_t.clone()), | ||
101 | }; | ||
102 | |||
103 | path_cmp_bin_search(lhs_t.path(), rhs_t.path()) | ||
104 | }) { | ||
105 | Ok(idx) => { | ||
106 | let lhs_t = &mut use_trees[idx]; | ||
107 | let lhs_path = lhs_t.path()?; | ||
108 | let rhs_path = rhs_path?; | ||
109 | let (lhs_prefix, rhs_prefix) = common_prefix(&lhs_path, &rhs_path)?; | ||
110 | if lhs_prefix == lhs_path && rhs_prefix == rhs_path { | ||
111 | let tree_is_self = |tree: ast::UseTree| { | ||
112 | tree.path().as_ref().map(path_is_self).unwrap_or(false) | ||
113 | }; | ||
114 | // check if only one of the two trees has a tree list, and whether that then contains `self` or not. | ||
115 | // If this is the case we can skip this iteration since the path without the list is already included in the other one via `self` | ||
116 | let tree_contains_self = |tree: &ast::UseTree| { | ||
117 | tree.use_tree_list() | ||
118 | .map(|tree_list| tree_list.use_trees().any(tree_is_self)) | ||
119 | .unwrap_or(false) | ||
120 | }; | ||
121 | match (tree_contains_self(&lhs_t), tree_contains_self(&rhs_t)) { | ||
122 | (true, false) => continue, | ||
123 | (false, true) => { | ||
124 | *lhs_t = rhs_t; | ||
125 | continue; | ||
126 | } | ||
127 | _ => (), | ||
128 | } | ||
129 | |||
130 | // glob imports arent part of the use-tree lists so we need to special handle them here as well | ||
131 | // this special handling is only required for when we merge a module import into a glob import of said module | ||
132 | // see the `merge_self_glob` or `merge_mod_into_glob` tests | ||
133 | if lhs_t.star_token().is_some() || rhs_t.star_token().is_some() { | ||
134 | *lhs_t = make::use_tree( | ||
135 | make::path_unqualified(make::path_segment_self()), | ||
136 | None, | ||
137 | None, | ||
138 | false, | ||
139 | ); | ||
140 | use_trees.insert(idx, make::glob_use_tree()); | ||
141 | continue; | ||
142 | } | ||
143 | |||
144 | if lhs_t.use_tree_list().is_none() && rhs_t.use_tree_list().is_none() { | ||
145 | continue; | ||
146 | } | ||
147 | } | ||
148 | let lhs = lhs_t.split_prefix(&lhs_prefix); | ||
149 | let rhs = rhs_t.split_prefix(&rhs_prefix); | ||
150 | match recursive_merge(&lhs, &rhs, merge) { | ||
151 | Some(use_tree) => use_trees[idx] = use_tree, | ||
152 | None => return None, | ||
153 | } | ||
154 | } | ||
155 | Err(_) | ||
156 | if merge == MergeBehavior::Last | ||
157 | && use_trees.len() > 0 | ||
158 | && rhs_t.use_tree_list().is_some() => | ||
159 | { | ||
160 | return None | ||
161 | } | ||
162 | Err(idx) => { | ||
163 | use_trees.insert(idx, rhs_t); | ||
164 | } | ||
165 | } | ||
166 | } | ||
167 | |||
168 | Some(if let Some(old) = lhs.use_tree_list() { | ||
169 | lhs.replace_descendant(old, make::use_tree_list(use_trees)).clone_for_update() | ||
170 | } else { | ||
171 | lhs.clone() | ||
172 | }) | ||
173 | } | ||
174 | |||
175 | /// Traverses both paths until they differ, returning the common prefix of both. | ||
176 | fn common_prefix(lhs: &ast::Path, rhs: &ast::Path) -> Option<(ast::Path, ast::Path)> { | ||
177 | let mut res = None; | ||
178 | let mut lhs_curr = lhs.first_qualifier_or_self(); | ||
179 | let mut rhs_curr = rhs.first_qualifier_or_self(); | ||
180 | loop { | ||
181 | match (lhs_curr.segment(), rhs_curr.segment()) { | ||
182 | (Some(lhs), Some(rhs)) if lhs.syntax().text() == rhs.syntax().text() => (), | ||
183 | _ => break res, | ||
184 | } | ||
185 | res = Some((lhs_curr.clone(), rhs_curr.clone())); | ||
186 | |||
187 | match lhs_curr.parent_path().zip(rhs_curr.parent_path()) { | ||
188 | Some((lhs, rhs)) => { | ||
189 | lhs_curr = lhs; | ||
190 | rhs_curr = rhs; | ||
191 | } | ||
192 | _ => break res, | ||
193 | } | ||
194 | } | ||
195 | } | ||
196 | |||
197 | /// Orders paths in the following way: | ||
198 | /// the sole self token comes first, after that come uppercase identifiers, then lowercase identifiers | ||
199 | // FIXME: rustfmt sorts lowercase idents before uppercase, in general we want to have the same ordering rustfmt has | ||
200 | // which is `self` and `super` first, then identifier imports with lowercase ones first, then glob imports and at last list imports. | ||
201 | // Example foo::{self, foo, baz, Baz, Qux, *, {Bar}} | ||
202 | fn path_cmp_for_sort(a: Option<ast::Path>, b: Option<ast::Path>) -> Ordering { | ||
203 | match (a, b) { | ||
204 | (None, None) => Ordering::Equal, | ||
205 | (None, Some(_)) => Ordering::Less, | ||
206 | (Some(_), None) => Ordering::Greater, | ||
207 | (Some(ref a), Some(ref b)) => match (path_is_self(a), path_is_self(b)) { | ||
208 | (true, true) => Ordering::Equal, | ||
209 | (true, false) => Ordering::Less, | ||
210 | (false, true) => Ordering::Greater, | ||
211 | (false, false) => path_cmp_short(a, b), | ||
212 | }, | ||
213 | } | ||
214 | } | ||
215 | |||
216 | /// Path comparison func for binary searching for merging. | ||
217 | fn path_cmp_bin_search(lhs: Option<ast::Path>, rhs: Option<ast::Path>) -> Ordering { | ||
218 | match ( | ||
219 | lhs.as_ref().and_then(ast::Path::first_segment), | ||
220 | rhs.as_ref().and_then(ast::Path::first_segment), | ||
221 | ) { | ||
222 | (None, None) => Ordering::Equal, | ||
223 | (None, Some(_)) => Ordering::Less, | ||
224 | (Some(_), None) => Ordering::Greater, | ||
225 | (Some(ref a), Some(ref b)) => path_segment_cmp(a, b), | ||
226 | } | ||
227 | } | ||
228 | |||
229 | /// Short circuiting comparison, if both paths are equal until one of them ends they are considered | ||
230 | /// equal | ||
231 | fn path_cmp_short(a: &ast::Path, b: &ast::Path) -> Ordering { | ||
232 | let a = a.segments(); | ||
233 | let b = b.segments(); | ||
234 | // cmp_by would be useful for us here but that is currently unstable | ||
235 | // cmp doesn't work due the lifetimes on text's return type | ||
236 | a.zip(b) | ||
237 | .find_map(|(a, b)| match path_segment_cmp(&a, &b) { | ||
238 | Ordering::Equal => None, | ||
239 | ord => Some(ord), | ||
240 | }) | ||
241 | .unwrap_or(Ordering::Equal) | ||
242 | } | ||
243 | |||
244 | /// Compares two paths, if one ends earlier than the other the has_tl parameters decide which is | ||
245 | /// greater as a a path that has a tree list should be greater, while one that just ends without | ||
246 | /// a tree list should be considered less. | ||
247 | pub(super) fn use_tree_path_cmp( | ||
248 | a: &ast::Path, | ||
249 | a_has_tl: bool, | ||
250 | b: &ast::Path, | ||
251 | b_has_tl: bool, | ||
252 | ) -> Ordering { | ||
253 | let a_segments = a.segments(); | ||
254 | let b_segments = b.segments(); | ||
255 | // cmp_by would be useful for us here but that is currently unstable | ||
256 | // cmp doesn't work due the lifetimes on text's return type | ||
257 | a_segments | ||
258 | .zip_longest(b_segments) | ||
259 | .find_map(|zipped| match zipped { | ||
260 | EitherOrBoth::Both(ref a, ref b) => match path_segment_cmp(a, b) { | ||
261 | Ordering::Equal => None, | ||
262 | ord => Some(ord), | ||
263 | }, | ||
264 | EitherOrBoth::Left(_) if !b_has_tl => Some(Ordering::Greater), | ||
265 | EitherOrBoth::Left(_) => Some(Ordering::Less), | ||
266 | EitherOrBoth::Right(_) if !a_has_tl => Some(Ordering::Less), | ||
267 | EitherOrBoth::Right(_) => Some(Ordering::Greater), | ||
268 | }) | ||
269 | .unwrap_or(Ordering::Equal) | ||
270 | } | ||
271 | |||
272 | fn path_segment_cmp(a: &ast::PathSegment, b: &ast::PathSegment) -> Ordering { | ||
273 | let a = a.kind().and_then(|kind| match kind { | ||
274 | PathSegmentKind::Name(name_ref) => Some(name_ref), | ||
275 | _ => None, | ||
276 | }); | ||
277 | let b = b.kind().and_then(|kind| match kind { | ||
278 | PathSegmentKind::Name(name_ref) => Some(name_ref), | ||
279 | _ => None, | ||
280 | }); | ||
281 | a.as_ref().map(ast::NameRef::text).cmp(&b.as_ref().map(ast::NameRef::text)) | ||
282 | } | ||
283 | |||
284 | fn eq_visibility(vis0: Option<ast::Visibility>, vis1: Option<ast::Visibility>) -> bool { | ||
285 | match (vis0, vis1) { | ||
286 | (None, None) => true, | ||
287 | // FIXME: Don't use the string representation to check for equality | ||
288 | // spaces inside of the node would break this comparison | ||
289 | (Some(vis0), Some(vis1)) => vis0.to_string() == vis1.to_string(), | ||
290 | _ => false, | ||
291 | } | ||
292 | } | ||
293 | |||
294 | fn eq_attrs( | ||
295 | attrs0: impl Iterator<Item = ast::Attr>, | ||
296 | attrs1: impl Iterator<Item = ast::Attr>, | ||
297 | ) -> bool { | ||
298 | let attrs0 = attrs0.map(|attr| attr.to_string()); | ||
299 | let attrs1 = attrs1.map(|attr| attr.to_string()); | ||
300 | attrs0.eq(attrs1) | ||
301 | } | ||
302 | |||
303 | fn path_is_self(path: &ast::Path) -> bool { | ||
304 | path.segment().and_then(|seg| seg.self_token()).is_some() && path.qualifier().is_none() | ||
305 | } | ||
306 | |||
307 | fn path_len(path: ast::Path) -> usize { | ||
308 | path.segments().count() | ||
309 | } | ||
diff --git a/crates/ide_db/src/search.rs b/crates/ide_db/src/search.rs index b55e3851e..8f899ea56 100644 --- a/crates/ide_db/src/search.rs +++ b/crates/ide_db/src/search.rs | |||
@@ -7,7 +7,9 @@ | |||
7 | use std::{convert::TryInto, mem}; | 7 | use std::{convert::TryInto, mem}; |
8 | 8 | ||
9 | use base_db::{FileId, FileRange, SourceDatabase, SourceDatabaseExt}; | 9 | use base_db::{FileId, FileRange, SourceDatabase, SourceDatabaseExt}; |
10 | use hir::{DefWithBody, HasAttrs, HasSource, InFile, ModuleSource, Semantics, Visibility}; | 10 | use hir::{ |
11 | DefWithBody, HasAttrs, HasSource, InFile, ModuleDef, ModuleSource, Semantics, Visibility, | ||
12 | }; | ||
11 | use once_cell::unsync::Lazy; | 13 | use once_cell::unsync::Lazy; |
12 | use rustc_hash::FxHashMap; | 14 | use rustc_hash::FxHashMap; |
13 | use syntax::{ast, match_ast, AstNode, TextRange, TextSize}; | 15 | use syntax::{ast, match_ast, AstNode, TextRange, TextSize}; |
@@ -295,7 +297,7 @@ impl Definition { | |||
295 | } | 297 | } |
296 | 298 | ||
297 | pub fn usages<'a>(&'a self, sema: &'a Semantics<RootDatabase>) -> FindUsages<'a> { | 299 | pub fn usages<'a>(&'a self, sema: &'a Semantics<RootDatabase>) -> FindUsages<'a> { |
298 | FindUsages { def: self, sema, scope: None } | 300 | FindUsages { def: self, sema, scope: None, include_self_kw_refs: false } |
299 | } | 301 | } |
300 | } | 302 | } |
301 | 303 | ||
@@ -303,9 +305,15 @@ pub struct FindUsages<'a> { | |||
303 | def: &'a Definition, | 305 | def: &'a Definition, |
304 | sema: &'a Semantics<'a, RootDatabase>, | 306 | sema: &'a Semantics<'a, RootDatabase>, |
305 | scope: Option<SearchScope>, | 307 | scope: Option<SearchScope>, |
308 | include_self_kw_refs: bool, | ||
306 | } | 309 | } |
307 | 310 | ||
308 | impl<'a> FindUsages<'a> { | 311 | impl<'a> FindUsages<'a> { |
312 | pub fn include_self_kw_refs(mut self, include: bool) -> FindUsages<'a> { | ||
313 | self.include_self_kw_refs = include; | ||
314 | self | ||
315 | } | ||
316 | |||
309 | pub fn in_scope(self, scope: SearchScope) -> FindUsages<'a> { | 317 | pub fn in_scope(self, scope: SearchScope) -> FindUsages<'a> { |
310 | self.set_scope(Some(scope)) | 318 | self.set_scope(Some(scope)) |
311 | } | 319 | } |
@@ -352,6 +360,8 @@ impl<'a> FindUsages<'a> { | |||
352 | }; | 360 | }; |
353 | 361 | ||
354 | let pat = name.as_str(); | 362 | let pat = name.as_str(); |
363 | let search_for_self = self.include_self_kw_refs; | ||
364 | |||
355 | for (file_id, search_range) in search_scope { | 365 | for (file_id, search_range) in search_scope { |
356 | let text = sema.db.file_text(file_id); | 366 | let text = sema.db.file_text(file_id); |
357 | let search_range = | 367 | let search_range = |
@@ -359,31 +369,47 @@ impl<'a> FindUsages<'a> { | |||
359 | 369 | ||
360 | let tree = Lazy::new(|| sema.parse(file_id).syntax().clone()); | 370 | let tree = Lazy::new(|| sema.parse(file_id).syntax().clone()); |
361 | 371 | ||
362 | for (idx, _) in text.match_indices(pat) { | 372 | let mut handle_match = |idx: usize| -> bool { |
363 | let offset: TextSize = idx.try_into().unwrap(); | 373 | let offset: TextSize = idx.try_into().unwrap(); |
364 | if !search_range.contains_inclusive(offset) { | 374 | if !search_range.contains_inclusive(offset) { |
365 | continue; | 375 | return false; |
366 | } | 376 | } |
367 | 377 | ||
368 | if let Some(name) = sema.find_node_at_offset_with_descend(&tree, offset) { | 378 | if let Some(name) = sema.find_node_at_offset_with_descend(&tree, offset) { |
369 | match name { | 379 | match name { |
370 | ast::NameLike::NameRef(name_ref) => { | 380 | ast::NameLike::NameRef(name_ref) => { |
371 | if self.found_name_ref(&name_ref, sink) { | 381 | if self.found_name_ref(&name_ref, sink) { |
372 | return; | 382 | return true; |
373 | } | 383 | } |
374 | } | 384 | } |
375 | ast::NameLike::Name(name) => { | 385 | ast::NameLike::Name(name) => { |
376 | if self.found_name(&name, sink) { | 386 | if self.found_name(&name, sink) { |
377 | return; | 387 | return true; |
378 | } | 388 | } |
379 | } | 389 | } |
380 | ast::NameLike::Lifetime(lifetime) => { | 390 | ast::NameLike::Lifetime(lifetime) => { |
381 | if self.found_lifetime(&lifetime, sink) { | 391 | if self.found_lifetime(&lifetime, sink) { |
382 | return; | 392 | return true; |
383 | } | 393 | } |
384 | } | 394 | } |
385 | } | 395 | } |
386 | } | 396 | } |
397 | |||
398 | return false; | ||
399 | }; | ||
400 | |||
401 | for (idx, _) in text.match_indices(pat) { | ||
402 | if handle_match(idx) { | ||
403 | return; | ||
404 | } | ||
405 | } | ||
406 | |||
407 | if search_for_self { | ||
408 | for (idx, _) in text.match_indices("Self") { | ||
409 | if handle_match(idx) { | ||
410 | return; | ||
411 | } | ||
412 | } | ||
387 | } | 413 | } |
388 | } | 414 | } |
389 | } | 415 | } |
@@ -422,6 +448,24 @@ impl<'a> FindUsages<'a> { | |||
422 | }; | 448 | }; |
423 | sink(file_id, reference) | 449 | sink(file_id, reference) |
424 | } | 450 | } |
451 | Some(NameRefClass::Definition(Definition::SelfType(impl_))) => { | ||
452 | let ty = impl_.self_ty(self.sema.db); | ||
453 | |||
454 | if let Some(adt) = ty.as_adt() { | ||
455 | if &Definition::ModuleDef(ModuleDef::Adt(adt)) == self.def { | ||
456 | let FileRange { file_id, range } = | ||
457 | self.sema.original_range(name_ref.syntax()); | ||
458 | let reference = FileReference { | ||
459 | range, | ||
460 | name: ast::NameLike::NameRef(name_ref.clone()), | ||
461 | access: None, | ||
462 | }; | ||
463 | return sink(file_id, reference); | ||
464 | } | ||
465 | } | ||
466 | |||
467 | false | ||
468 | } | ||
425 | Some(NameRefClass::FieldShorthand { local_ref: local, field_ref: field }) => { | 469 | Some(NameRefClass::FieldShorthand { local_ref: local, field_ref: field }) => { |
426 | let FileRange { file_id, range } = self.sema.original_range(name_ref.syntax()); | 470 | let FileRange { file_id, range } = self.sema.original_range(name_ref.syntax()); |
427 | let reference = match self.def { | 471 | let reference = match self.def { |
diff --git a/crates/proc_macro_api/Cargo.toml b/crates/proc_macro_api/Cargo.toml index 16fd56c7e..1ba1e4abd 100644 --- a/crates/proc_macro_api/Cargo.toml +++ b/crates/proc_macro_api/Cargo.toml | |||
@@ -15,10 +15,11 @@ serde_json = { version = "1.0", features = ["unbounded_depth"] } | |||
15 | log = "0.4.8" | 15 | log = "0.4.8" |
16 | crossbeam-channel = "0.5.0" | 16 | crossbeam-channel = "0.5.0" |
17 | jod-thread = "0.1.1" | 17 | jod-thread = "0.1.1" |
18 | memmap = "0.7.0" | ||
19 | object = { version = "0.23.0", default-features = false, features = ["std", "read_core", "elf", "macho", "pe", "unaligned"] } | ||
20 | snap = "1.0" | ||
18 | 21 | ||
19 | tt = { path = "../tt", version = "0.0.0" } | 22 | tt = { path = "../tt", version = "0.0.0" } |
20 | base_db = { path = "../base_db", version = "0.0.0" } | 23 | base_db = { path = "../base_db", version = "0.0.0" } |
21 | stdx = { path = "../stdx", version = "0.0.0" } | 24 | stdx = { path = "../stdx", version = "0.0.0" } |
22 | snap = "1" | 25 | profile = { path = "../profile", version = "0.0.0" } |
23 | object = { version = "0.23.0", default-features = false, features = ["std", "read_core", "elf", "macho", "pe", "unaligned"] } | ||
24 | memmap = "0.7.0" | ||
diff --git a/crates/proc_macro_api/src/lib.rs b/crates/proc_macro_api/src/lib.rs index 2dd2a8541..654bd9943 100644 --- a/crates/proc_macro_api/src/lib.rs +++ b/crates/proc_macro_api/src/lib.rs | |||
@@ -77,6 +77,7 @@ impl ProcMacroClient { | |||
77 | } | 77 | } |
78 | 78 | ||
79 | pub fn by_dylib_path(&self, dylib_path: &Path) -> Vec<ProcMacro> { | 79 | pub fn by_dylib_path(&self, dylib_path: &Path) -> Vec<ProcMacro> { |
80 | let _p = profile::span("ProcMacroClient::by_dylib_path"); | ||
80 | match version::read_dylib_info(dylib_path) { | 81 | match version::read_dylib_info(dylib_path) { |
81 | Ok(info) => { | 82 | Ok(info) => { |
82 | if info.version.0 < 1 || info.version.1 < 47 { | 83 | if info.version.0 < 1 || info.version.1 < 47 { |
diff --git a/crates/project_model/src/build_data.rs b/crates/project_model/src/build_data.rs index faca336de..7b88dca63 100644 --- a/crates/project_model/src/build_data.rs +++ b/crates/project_model/src/build_data.rs | |||
@@ -143,7 +143,7 @@ impl WorkspaceBuildData { | |||
143 | cmd.env("RA_RUSTC_WRAPPER", "1"); | 143 | cmd.env("RA_RUSTC_WRAPPER", "1"); |
144 | } | 144 | } |
145 | 145 | ||
146 | cmd.args(&["check", "--workspace", "--message-format=json", "--manifest-path"]) | 146 | cmd.args(&["check", "--quiet", "--workspace", "--message-format=json", "--manifest-path"]) |
147 | .arg(cargo_toml.as_ref()); | 147 | .arg(cargo_toml.as_ref()); |
148 | 148 | ||
149 | // --all-targets includes tests, benches and examples in addition to the | 149 | // --all-targets includes tests, benches and examples in addition to the |
diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml index 0571a912c..3e8f4bf89 100644 --- a/crates/rust-analyzer/Cargo.toml +++ b/crates/rust-analyzer/Cargo.toml | |||
@@ -33,7 +33,7 @@ serde_path_to_error = "0.1" | |||
33 | threadpool = "1.7.1" | 33 | threadpool = "1.7.1" |
34 | rayon = "1.5" | 34 | rayon = "1.5" |
35 | mimalloc = { version = "0.1.19", default-features = false, optional = true } | 35 | mimalloc = { version = "0.1.19", default-features = false, optional = true } |
36 | lsp-server = "0.5.0" | 36 | lsp-server = "0.5.1" |
37 | tracing = "0.1" | 37 | tracing = "0.1" |
38 | tracing-subscriber = { version = "0.2", default-features = false, features = ["env-filter", "registry"] } | 38 | tracing-subscriber = { version = "0.2", default-features = false, features = ["env-filter", "registry"] } |
39 | tracing-tree = { version = "0.1.4" } | 39 | tracing-tree = { version = "0.1.4" } |
diff --git a/crates/rust-analyzer/build.rs b/crates/rust-analyzer/build.rs index 13b903891..bca6611d6 100644 --- a/crates/rust-analyzer/build.rs +++ b/crates/rust-analyzer/build.rs | |||
@@ -1,13 +1,10 @@ | |||
1 | //! Just embed git-hash to `--version` | 1 | //! Construct version in the `commit-hash date chanel` format |
2 | 2 | ||
3 | use std::{env, path::PathBuf, process::Command}; | 3 | use std::{env, path::PathBuf, process::Command}; |
4 | 4 | ||
5 | fn main() { | 5 | fn main() { |
6 | set_rerun(); | 6 | set_rerun(); |
7 | 7 | println!("cargo:rustc-env=REV={}", rev()) | |
8 | let rev = | ||
9 | env::var("RUST_ANALYZER_REV").ok().or_else(rev).unwrap_or_else(|| "???????".to_string()); | ||
10 | println!("cargo:rustc-env=REV={}", rev) | ||
11 | } | 8 | } |
12 | 9 | ||
13 | fn set_rerun() { | 10 | fn set_rerun() { |
@@ -18,29 +15,52 @@ fn set_rerun() { | |||
18 | ); | 15 | ); |
19 | 16 | ||
20 | while manifest_dir.parent().is_some() { | 17 | while manifest_dir.parent().is_some() { |
21 | if manifest_dir.join(".git/HEAD").exists() { | 18 | let head_ref = manifest_dir.join(".git/HEAD"); |
22 | let git_dir = manifest_dir.join(".git"); | 19 | if head_ref.exists() { |
23 | 20 | println!("cargo:rerun-if-changed={}", head_ref.display()); | |
24 | println!("cargo:rerun-if-changed={}", git_dir.join("HEAD").display()); | ||
25 | // current branch ref | ||
26 | if let Ok(output) = | ||
27 | Command::new("git").args(&["rev-parse", "--symbolic-full-name", "HEAD"]).output() | ||
28 | { | ||
29 | if let Ok(ref_link) = String::from_utf8(output.stdout) { | ||
30 | println!("cargo:rerun-if-changed={}", git_dir.join(ref_link).display()); | ||
31 | } | ||
32 | } | ||
33 | return; | 21 | return; |
34 | } | 22 | } |
35 | 23 | ||
36 | manifest_dir.pop(); | 24 | manifest_dir.pop(); |
37 | } | 25 | } |
26 | |||
38 | println!("cargo:warning=Could not find `.git/HEAD` from manifest dir!"); | 27 | println!("cargo:warning=Could not find `.git/HEAD` from manifest dir!"); |
39 | } | 28 | } |
40 | 29 | ||
41 | fn rev() -> Option<String> { | 30 | fn rev() -> String { |
42 | let output = | 31 | if let Ok(rev) = env::var("RUST_ANALYZER_REV") { |
43 | Command::new("git").args(&["describe", "--tags", "--exclude", "nightly"]).output().ok()?; | 32 | return rev; |
33 | } | ||
34 | |||
35 | if let Some(commit_hash) = commit_hash() { | ||
36 | let mut buf = commit_hash; | ||
37 | |||
38 | if let Some(date) = build_date() { | ||
39 | buf.push(' '); | ||
40 | buf.push_str(&date); | ||
41 | } | ||
42 | |||
43 | let channel = env::var("RUST_ANALYZER_CHANNEL").unwrap_or_else(|_| "dev".to_string()); | ||
44 | buf.push(' '); | ||
45 | buf.push_str(&channel); | ||
46 | |||
47 | return buf; | ||
48 | } | ||
49 | |||
50 | "???????".to_string() | ||
51 | } | ||
52 | |||
53 | fn commit_hash() -> Option<String> { | ||
54 | output_to_string("git rev-parse --short HEAD") | ||
55 | } | ||
56 | |||
57 | fn build_date() -> Option<String> { | ||
58 | output_to_string("date -u +%Y-%m-%d") | ||
59 | } | ||
60 | |||
61 | fn output_to_string(command: &str) -> Option<String> { | ||
62 | let args = command.split_ascii_whitespace().collect::<Vec<_>>(); | ||
63 | let output = Command::new(args[0]).args(&args[1..]).output().ok()?; | ||
44 | let stdout = String::from_utf8(output.stdout).ok()?; | 64 | let stdout = String::from_utf8(output.stdout).ok()?; |
45 | Some(stdout) | 65 | Some(stdout.trim().to_string()) |
46 | } | 66 | } |
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 1109d2daf..28bbbce19 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs | |||
@@ -12,7 +12,8 @@ use std::{ffi::OsString, iter, path::PathBuf}; | |||
12 | use flycheck::FlycheckConfig; | 12 | use flycheck::FlycheckConfig; |
13 | use ide::{AssistConfig, CompletionConfig, DiagnosticsConfig, HoverConfig, InlayHintsConfig}; | 13 | use ide::{AssistConfig, CompletionConfig, DiagnosticsConfig, HoverConfig, InlayHintsConfig}; |
14 | use ide_db::helpers::{ | 14 | use ide_db::helpers::{ |
15 | insert_use::{InsertUseConfig, MergeBehavior, PrefixKind}, | 15 | insert_use::{InsertUseConfig, PrefixKind}, |
16 | merge_imports::MergeBehavior, | ||
16 | SnippetCap, | 17 | SnippetCap, |
17 | }; | 18 | }; |
18 | use lsp_types::{ClientCapabilities, MarkupKind}; | 19 | use lsp_types::{ClientCapabilities, MarkupKind}; |
@@ -144,6 +145,8 @@ config_data! { | |||
144 | inlayHints_parameterHints: bool = "true", | 145 | inlayHints_parameterHints: bool = "true", |
145 | /// Whether to show inlay type hints for variables. | 146 | /// Whether to show inlay type hints for variables. |
146 | inlayHints_typeHints: bool = "true", | 147 | inlayHints_typeHints: bool = "true", |
148 | /// Whether inlay hints font size should be smaller than editor's font size. | ||
149 | inlayHints_smallerHints: bool = "true", | ||
147 | 150 | ||
148 | /// Whether to show `Debug` lens. Only applies when | 151 | /// Whether to show `Debug` lens. Only applies when |
149 | /// `#rust-analyzer.lens.enable#` is set. | 152 | /// `#rust-analyzer.lens.enable#` is set. |
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 6ea775d68..a766aacad 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs | |||
@@ -571,6 +571,12 @@ impl GlobalState { | |||
571 | this.cancel(id); | 571 | this.cancel(id); |
572 | Ok(()) | 572 | Ok(()) |
573 | })? | 573 | })? |
574 | .on::<lsp_types::notification::WorkDoneProgressCancel>(|_this, _params| { | ||
575 | // Just ignore this. It is OK to continue sending progress | ||
576 | // notifications for this token, as the client can't know when | ||
577 | // we accepted notification. | ||
578 | Ok(()) | ||
579 | })? | ||
574 | .on::<lsp_types::notification::DidOpenTextDocument>(|this, params| { | 580 | .on::<lsp_types::notification::DidOpenTextDocument>(|this, params| { |
575 | if let Ok(path) = from_proto::vfs_path(¶ms.text_document.uri) { | 581 | if let Ok(path) = from_proto::vfs_path(¶ms.text_document.uri) { |
576 | if this | 582 | if this |
diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index e51532d88..0ae2758cc 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/crates/rust-analyzer/src/reload.rs | |||
@@ -322,6 +322,7 @@ impl GlobalState { | |||
322 | let loader = &mut self.loader; | 322 | let loader = &mut self.loader; |
323 | let mem_docs = &self.mem_docs; | 323 | let mem_docs = &self.mem_docs; |
324 | let mut load = |path: &AbsPath| { | 324 | let mut load = |path: &AbsPath| { |
325 | let _p = profile::span("GlobalState::load"); | ||
325 | let vfs_path = vfs::VfsPath::from(path.to_path_buf()); | 326 | let vfs_path = vfs::VfsPath::from(path.to_path_buf()); |
326 | if !mem_docs.contains_key(&vfs_path) { | 327 | if !mem_docs.contains_key(&vfs_path) { |
327 | let contents = loader.handle.load_sync(path); | 328 | let contents = loader.handle.load_sync(path); |
diff --git a/crates/stdx/src/lib.rs b/crates/stdx/src/lib.rs index 857567a85..1b6211044 100644 --- a/crates/stdx/src/lib.rs +++ b/crates/stdx/src/lib.rs | |||
@@ -14,18 +14,8 @@ pub fn is_ci() -> bool { | |||
14 | 14 | ||
15 | #[must_use] | 15 | #[must_use] |
16 | pub fn timeit(label: &'static str) -> impl Drop { | 16 | pub fn timeit(label: &'static str) -> impl Drop { |
17 | struct Guard { | 17 | let start = Instant::now(); |
18 | label: &'static str, | 18 | defer(move || eprintln!("{}: {:.2?}", label, start.elapsed())) |
19 | start: Instant, | ||
20 | } | ||
21 | |||
22 | impl Drop for Guard { | ||
23 | fn drop(&mut self) { | ||
24 | eprintln!("{}: {:.2?}", self.label, self.start.elapsed()) | ||
25 | } | ||
26 | } | ||
27 | |||
28 | Guard { label, start: Instant::now() } | ||
29 | } | 19 | } |
30 | 20 | ||
31 | /// Prints backtrace to stderr, useful for debugging. | 21 | /// Prints backtrace to stderr, useful for debugging. |
@@ -179,6 +169,7 @@ where | |||
179 | start..start + len | 169 | start..start + len |
180 | } | 170 | } |
181 | 171 | ||
172 | #[must_use] | ||
182 | pub fn defer<F: FnOnce()>(f: F) -> impl Drop { | 173 | pub fn defer<F: FnOnce()>(f: F) -> impl Drop { |
183 | struct D<F: FnOnce()>(Option<F>); | 174 | struct D<F: FnOnce()>(Option<F>); |
184 | impl<F: FnOnce()> Drop for D<F> { | 175 | impl<F: FnOnce()> Drop for D<F> { |
diff --git a/crates/syntax/src/algo.rs b/crates/syntax/src/algo.rs index a153a9e1c..c9229c4e0 100644 --- a/crates/syntax/src/algo.rs +++ b/crates/syntax/src/algo.rs | |||
@@ -342,10 +342,10 @@ enum InsertPos { | |||
342 | 342 | ||
343 | #[derive(Default)] | 343 | #[derive(Default)] |
344 | pub struct SyntaxRewriter<'a> { | 344 | pub struct SyntaxRewriter<'a> { |
345 | f: Option<Box<dyn Fn(&SyntaxElement) -> Option<SyntaxElement> + 'a>>, | ||
346 | //FIXME: add debug_assertions that all elements are in fact from the same file. | 345 | //FIXME: add debug_assertions that all elements are in fact from the same file. |
347 | replacements: FxHashMap<SyntaxElement, Replacement>, | 346 | replacements: FxHashMap<SyntaxElement, Replacement>, |
348 | insertions: IndexMap<InsertPos, Vec<SyntaxElement>>, | 347 | insertions: IndexMap<InsertPos, Vec<SyntaxElement>>, |
348 | _pd: std::marker::PhantomData<&'a ()>, | ||
349 | } | 349 | } |
350 | 350 | ||
351 | impl fmt::Debug for SyntaxRewriter<'_> { | 351 | impl fmt::Debug for SyntaxRewriter<'_> { |
@@ -357,14 +357,7 @@ impl fmt::Debug for SyntaxRewriter<'_> { | |||
357 | } | 357 | } |
358 | } | 358 | } |
359 | 359 | ||
360 | impl<'a> SyntaxRewriter<'a> { | 360 | impl SyntaxRewriter<'_> { |
361 | pub fn from_fn(f: impl Fn(&SyntaxElement) -> Option<SyntaxElement> + 'a) -> SyntaxRewriter<'a> { | ||
362 | SyntaxRewriter { | ||
363 | f: Some(Box::new(f)), | ||
364 | replacements: FxHashMap::default(), | ||
365 | insertions: IndexMap::default(), | ||
366 | } | ||
367 | } | ||
368 | pub fn delete<T: Clone + Into<SyntaxElement>>(&mut self, what: &T) { | 361 | pub fn delete<T: Clone + Into<SyntaxElement>>(&mut self, what: &T) { |
369 | let what = what.clone().into(); | 362 | let what = what.clone().into(); |
370 | let replacement = Replacement::Delete; | 363 | let replacement = Replacement::Delete; |
@@ -470,7 +463,7 @@ impl<'a> SyntaxRewriter<'a> { | |||
470 | pub fn rewrite(&self, node: &SyntaxNode) -> SyntaxNode { | 463 | pub fn rewrite(&self, node: &SyntaxNode) -> SyntaxNode { |
471 | let _p = profile::span("rewrite"); | 464 | let _p = profile::span("rewrite"); |
472 | 465 | ||
473 | if self.f.is_none() && self.replacements.is_empty() && self.insertions.is_empty() { | 466 | if self.replacements.is_empty() && self.insertions.is_empty() { |
474 | return node.clone(); | 467 | return node.clone(); |
475 | } | 468 | } |
476 | let green = self.rewrite_children(node); | 469 | let green = self.rewrite_children(node); |
@@ -495,7 +488,6 @@ impl<'a> SyntaxRewriter<'a> { | |||
495 | } | 488 | } |
496 | } | 489 | } |
497 | 490 | ||
498 | assert!(self.f.is_none()); | ||
499 | self.replacements | 491 | self.replacements |
500 | .keys() | 492 | .keys() |
501 | .filter_map(element_to_node_or_parent) | 493 | .filter_map(element_to_node_or_parent) |
@@ -510,10 +502,6 @@ impl<'a> SyntaxRewriter<'a> { | |||
510 | } | 502 | } |
511 | 503 | ||
512 | fn replacement(&self, element: &SyntaxElement) -> Option<Replacement> { | 504 | fn replacement(&self, element: &SyntaxElement) -> Option<Replacement> { |
513 | if let Some(f) = &self.f { | ||
514 | assert!(self.replacements.is_empty()); | ||
515 | return f(element).map(Replacement::Single); | ||
516 | } | ||
517 | self.replacements.get(element).cloned() | 505 | self.replacements.get(element).cloned() |
518 | } | 506 | } |
519 | 507 | ||
@@ -574,7 +562,6 @@ fn element_to_green(element: SyntaxElement) -> NodeOrToken<rowan::GreenNode, row | |||
574 | 562 | ||
575 | impl ops::AddAssign for SyntaxRewriter<'_> { | 563 | impl ops::AddAssign for SyntaxRewriter<'_> { |
576 | fn add_assign(&mut self, rhs: SyntaxRewriter) { | 564 | fn add_assign(&mut self, rhs: SyntaxRewriter) { |
577 | assert!(rhs.f.is_none()); | ||
578 | self.replacements.extend(rhs.replacements); | 565 | self.replacements.extend(rhs.replacements); |
579 | for (pos, insertions) in rhs.insertions.into_iter() { | 566 | for (pos, insertions) in rhs.insertions.into_iter() { |
580 | match self.insertions.entry(pos) { | 567 | match self.insertions.entry(pos) { |
diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs index 4cf6f871e..42da09606 100644 --- a/crates/syntax/src/ast/make.rs +++ b/crates/syntax/src/ast/make.rs | |||
@@ -137,6 +137,17 @@ pub fn use_(visibility: Option<ast::Visibility>, use_tree: ast::UseTree) -> ast: | |||
137 | ast_from_text(&format!("{}use {};", visibility, use_tree)) | 137 | ast_from_text(&format!("{}use {};", visibility, use_tree)) |
138 | } | 138 | } |
139 | 139 | ||
140 | pub fn record_expr(path: ast::Path, fields: ast::RecordExprFieldList) -> ast::RecordExpr { | ||
141 | ast_from_text(&format!("fn f() {{ {} {} }}", path, fields)) | ||
142 | } | ||
143 | |||
144 | pub fn record_expr_field_list( | ||
145 | fields: impl IntoIterator<Item = ast::RecordExprField>, | ||
146 | ) -> ast::RecordExprFieldList { | ||
147 | let fields = fields.into_iter().join(", "); | ||
148 | ast_from_text(&format!("fn f() {{ S {{ {} }} }}", fields)) | ||
149 | } | ||
150 | |||
140 | pub fn record_expr_field(name: ast::NameRef, expr: Option<ast::Expr>) -> ast::RecordExprField { | 151 | pub fn record_expr_field(name: ast::NameRef, expr: Option<ast::Expr>) -> ast::RecordExprField { |
141 | return match expr { | 152 | return match expr { |
142 | Some(expr) => from_text(&format!("{}: {}", name, expr)), | 153 | Some(expr) => from_text(&format!("{}: {}", name, expr)), |
@@ -339,6 +350,21 @@ pub fn record_pat(path: ast::Path, pats: impl IntoIterator<Item = ast::Pat>) -> | |||
339 | } | 350 | } |
340 | } | 351 | } |
341 | 352 | ||
353 | pub fn record_pat_with_fields(path: ast::Path, fields: ast::RecordPatFieldList) -> ast::RecordPat { | ||
354 | ast_from_text(&format!("fn f({} {}: ()))", path, fields)) | ||
355 | } | ||
356 | |||
357 | pub fn record_pat_field_list( | ||
358 | fields: impl IntoIterator<Item = ast::RecordPatField>, | ||
359 | ) -> ast::RecordPatFieldList { | ||
360 | let fields = fields.into_iter().join(", "); | ||
361 | ast_from_text(&format!("fn f(S {{ {} }}: ()))", fields)) | ||
362 | } | ||
363 | |||
364 | pub fn record_pat_field(name_ref: ast::NameRef, pat: ast::Pat) -> ast::RecordPatField { | ||
365 | ast_from_text(&format!("fn f(S {{ {}: {} }}: ()))", name_ref, pat)) | ||
366 | } | ||
367 | |||
342 | /// Returns a `BindPat` if the path has just one segment, a `PathPat` otherwise. | 368 | /// Returns a `BindPat` if the path has just one segment, a `PathPat` otherwise. |
343 | pub fn path_pat(path: ast::Path) -> ast::Pat { | 369 | pub fn path_pat(path: ast::Path) -> ast::Pat { |
344 | return from_text(&path.to_string()); | 370 | return from_text(&path.to_string()); |
@@ -606,6 +632,7 @@ pub mod tokens { | |||
606 | SOURCE_FILE | 632 | SOURCE_FILE |
607 | .tree() | 633 | .tree() |
608 | .syntax() | 634 | .syntax() |
635 | .clone_for_update() | ||
609 | .descendants_with_tokens() | 636 | .descendants_with_tokens() |
610 | .filter_map(|it| it.into_token()) | 637 | .filter_map(|it| it.into_token()) |
611 | .find(|it| it.kind() == WHITESPACE && it.text() == "\n\n") | 638 | .find(|it| it.kind() == WHITESPACE && it.text() == "\n\n") |
diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs index 171099661..492fbc4a0 100644 --- a/crates/syntax/src/ast/node_ext.rs +++ b/crates/syntax/src/ast/node_ext.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | //! Various extension methods to ast Nodes, which are hard to code-generate. | 1 | //! Various extension methods to ast Nodes, which are hard to code-generate. |
2 | //! Extensions for various expressions live in a sibling `expr_extensions` module. | 2 | //! Extensions for various expressions live in a sibling `expr_extensions` module. |
3 | 3 | ||
4 | use std::fmt; | 4 | use std::{fmt, iter::successors}; |
5 | 5 | ||
6 | use itertools::Itertools; | 6 | use itertools::Itertools; |
7 | use parser::SyntaxKind; | 7 | use parser::SyntaxKind; |
@@ -237,6 +237,26 @@ impl ast::Path { | |||
237 | None => self.segment(), | 237 | None => self.segment(), |
238 | } | 238 | } |
239 | } | 239 | } |
240 | |||
241 | pub fn first_qualifier_or_self(&self) -> ast::Path { | ||
242 | successors(Some(self.clone()), ast::Path::qualifier).last().unwrap() | ||
243 | } | ||
244 | |||
245 | pub fn first_segment(&self) -> Option<ast::PathSegment> { | ||
246 | self.first_qualifier_or_self().segment() | ||
247 | } | ||
248 | |||
249 | pub fn segments(&self) -> impl Iterator<Item = ast::PathSegment> + Clone { | ||
250 | // cant make use of SyntaxNode::siblings, because the returned Iterator is not clone | ||
251 | successors(self.first_segment(), |p| { | ||
252 | p.parent_path().parent_path().and_then(|p| p.segment()) | ||
253 | }) | ||
254 | } | ||
255 | } | ||
256 | impl ast::UseTree { | ||
257 | pub fn is_simple_path(&self) -> bool { | ||
258 | self.use_tree_list().is_none() && self.star_token().is_none() | ||
259 | } | ||
240 | } | 260 | } |
241 | 261 | ||
242 | impl ast::UseTreeList { | 262 | impl ast::UseTreeList { |
diff --git a/crates/syntax/src/ted.rs b/crates/syntax/src/ted.rs index 450f2e447..91a06101f 100644 --- a/crates/syntax/src/ted.rs +++ b/crates/syntax/src/ted.rs | |||
@@ -7,7 +7,7 @@ use std::{mem, ops::RangeInclusive}; | |||
7 | use parser::T; | 7 | use parser::T; |
8 | 8 | ||
9 | use crate::{ | 9 | use crate::{ |
10 | ast::{edit::IndentLevel, make}, | 10 | ast::{self, edit::IndentLevel, make, AstNode}, |
11 | SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, | 11 | SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, |
12 | }; | 12 | }; |
13 | 13 | ||
@@ -147,6 +147,16 @@ pub fn append_child_raw(node: &(impl Into<SyntaxNode> + Clone), child: impl Elem | |||
147 | fn ws_before(position: &Position, new: &SyntaxElement) -> Option<SyntaxToken> { | 147 | fn ws_before(position: &Position, new: &SyntaxElement) -> Option<SyntaxToken> { |
148 | let prev = match &position.repr { | 148 | let prev = match &position.repr { |
149 | PositionRepr::FirstChild(_) => return None, | 149 | PositionRepr::FirstChild(_) => return None, |
150 | PositionRepr::After(it) if it.kind() == SyntaxKind::L_CURLY => { | ||
151 | if new.kind() == SyntaxKind::USE { | ||
152 | if let Some(item_list) = it.parent().and_then(ast::ItemList::cast) { | ||
153 | let mut indent = IndentLevel::from_element(&item_list.syntax().clone().into()); | ||
154 | indent.0 += 1; | ||
155 | return Some(make::tokens::whitespace(&format!("\n{}", indent))); | ||
156 | } | ||
157 | } | ||
158 | it | ||
159 | } | ||
150 | PositionRepr::After(it) => it, | 160 | PositionRepr::After(it) => it, |
151 | }; | 161 | }; |
152 | ws_between(prev, new) | 162 | ws_between(prev, new) |
@@ -173,7 +183,10 @@ fn ws_between(left: &SyntaxElement, right: &SyntaxElement) -> Option<SyntaxToken | |||
173 | } | 183 | } |
174 | 184 | ||
175 | if right.kind() == SyntaxKind::USE { | 185 | if right.kind() == SyntaxKind::USE { |
176 | let indent = IndentLevel::from_element(left); | 186 | let mut indent = IndentLevel::from_element(left); |
187 | if left.kind() == SyntaxKind::USE { | ||
188 | indent.0 = IndentLevel::from_element(right).0.max(indent.0); | ||
189 | } | ||
177 | return Some(make::tokens::whitespace(&format!("\n{}", indent))); | 190 | return Some(make::tokens::whitespace(&format!("\n{}", indent))); |
178 | } | 191 | } |
179 | Some(make::tokens::single_space()) | 192 | Some(make::tokens::single_space()) |
diff --git a/docs/dev/README.md b/docs/dev/README.md index b98ac4c0a..16b23adc6 100644 --- a/docs/dev/README.md +++ b/docs/dev/README.md | |||
@@ -208,20 +208,26 @@ Release process is handled by `release`, `dist` and `promote` xtasks, `release` | |||
208 | 208 | ||
209 | Additionally, it assumes that remote for `rust-analyzer` is called `upstream` (I use `origin` to point to my fork). | 209 | Additionally, it assumes that remote for `rust-analyzer` is called `upstream` (I use `origin` to point to my fork). |
210 | 210 | ||
211 | `release` calls the GitHub API calls to scrape pull request comments and categorize them in the changelog. | ||
212 | This step uses the `curl` and `jq` applications, which need to be available in `PATH`. | ||
213 | Finally, you need to obtain a GitHub personal access token and set the `GITHUB_TOKEN` environment variable. | ||
214 | |||
211 | Release steps: | 215 | Release steps: |
212 | 216 | ||
213 | 1. Inside rust-analyzer, run `cargo xtask release`. This will: | 217 | 1. Set the `GITHUB_TOKEN` environment variable. |
218 | 2. Inside rust-analyzer, run `cargo xtask release`. This will: | ||
214 | * checkout the `release` branch | 219 | * checkout the `release` branch |
215 | * reset it to `upstream/nightly` | 220 | * reset it to `upstream/nightly` |
216 | * push it to `upstream`. This triggers GitHub Actions which: | 221 | * push it to `upstream`. This triggers GitHub Actions which: |
217 | * runs `cargo xtask dist` to package binaries and VS Code extension | 222 | * runs `cargo xtask dist` to package binaries and VS Code extension |
218 | * makes a GitHub release | 223 | * makes a GitHub release |
219 | * pushes VS Code extension to the marketplace | 224 | * pushes VS Code extension to the marketplace |
220 | * create new changelog in `rust-analyzer.github.io` | 225 | * call the GitHub API for PR details |
221 | 2. While the release is in progress, fill in the changelog | 226 | * create a new changelog in `rust-analyzer.github.io` |
222 | 3. Commit & push the changelog | 227 | 3. While the release is in progress, fill in the changelog |
223 | 4. Tweet | 228 | 4. Commit & push the changelog |
224 | 5. Inside `rust-analyzer`, run `cargo xtask promote` -- this will create a PR to rust-lang/rust updating rust-analyzer's submodule. | 229 | 5. Tweet |
230 | 6. Inside `rust-analyzer`, run `cargo xtask promote` -- this will create a PR to rust-lang/rust updating rust-analyzer's submodule. | ||
225 | Self-approve the PR. | 231 | Self-approve the PR. |
226 | 232 | ||
227 | If the GitHub Actions release fails because of a transient problem like a timeout, you can re-run the job from the Actions console. | 233 | If the GitHub Actions release fails because of a transient problem like a timeout, you can re-run the job from the Actions console. |
diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index e28423e99..db3c5f7bb 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc | |||
@@ -234,6 +234,11 @@ site. | |||
234 | -- | 234 | -- |
235 | Whether to show inlay type hints for variables. | 235 | Whether to show inlay type hints for variables. |
236 | -- | 236 | -- |
237 | [[rust-analyzer.inlayHints.smallerHints]]rust-analyzer.inlayHints.smallerHints (default: `true`):: | ||
238 | + | ||
239 | -- | ||
240 | Whether inlay hints font size should be smaller than editor's font size. | ||
241 | -- | ||
237 | [[rust-analyzer.lens.debug]]rust-analyzer.lens.debug (default: `true`):: | 242 | [[rust-analyzer.lens.debug]]rust-analyzer.lens.debug (default: `true`):: |
238 | + | 243 | + |
239 | -- | 244 | -- |
diff --git a/editors/code/language-configuration.json b/editors/code/language-configuration.json index b20e0d978..382484bc7 100644 --- a/editors/code/language-configuration.json +++ b/editors/code/language-configuration.json | |||
@@ -23,7 +23,8 @@ | |||
23 | ["(", ")"], | 23 | ["(", ")"], |
24 | ["<", ">"], | 24 | ["<", ">"], |
25 | ["\"", "\""], | 25 | ["\"", "\""], |
26 | ["'", "'"] | 26 | ["'", "'"], |
27 | ["|", "|"] | ||
27 | ], | 28 | ], |
28 | "indentationRules": { | 29 | "indentationRules": { |
29 | "increaseIndentPattern": "^.*\\{[^}\"']*$|^.*\\([^\\)\"']*$", | 30 | "increaseIndentPattern": "^.*\\{[^}\"']*$|^.*\\([^\\)\"']*$", |
diff --git a/editors/code/package-lock.json b/editors/code/package-lock.json index 198c17556..df0c512d6 100644 --- a/editors/code/package-lock.json +++ b/editors/code/package-lock.json | |||
@@ -53,9 +53,9 @@ | |||
53 | "dev": true | 53 | "dev": true |
54 | }, | 54 | }, |
55 | "node_modules/@babel/highlight": { | 55 | "node_modules/@babel/highlight": { |
56 | "version": "7.12.13", | 56 | "version": "7.13.10", |
57 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.12.13.tgz", | 57 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.10.tgz", |
58 | "integrity": "sha512-kocDQvIbgMKlWxXe9fof3TQ+gkIPOUSEYhJjqUjvKMez3krV7vbzYCDq39Oj11UAVK7JqPVGQPlgE85dPNlQww==", | 58 | "integrity": "sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg==", |
59 | "dev": true, | 59 | "dev": true, |
60 | "dependencies": { | 60 | "dependencies": { |
61 | "@babel/helper-validator-identifier": "^7.12.11", | 61 | "@babel/helper-validator-identifier": "^7.12.11", |
@@ -135,9 +135,9 @@ | |||
135 | } | 135 | } |
136 | }, | 136 | }, |
137 | "node_modules/@eslint/eslintrc": { | 137 | "node_modules/@eslint/eslintrc": { |
138 | "version": "0.3.0", | 138 | "version": "0.4.0", |
139 | "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.3.0.tgz", | 139 | "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz", |
140 | "integrity": "sha512-1JTKgrOKAHVivSvOYw+sJOunkBjUOvjqWk1DPja7ZFhIS2mX/4EgTT8M7eTK9jrKhL/FvXXEbQwIs3pg1xp3dg==", | 140 | "integrity": "sha512-2ZPCc+uNbjV5ERJr+aKSPRwZgKd2z11x0EgLvb1PURmUrn9QNRXFqje0Ldq454PfAVyaJYyrDvvIKSFP4NnBog==", |
141 | "dev": true, | 141 | "dev": true, |
142 | "dependencies": { | 142 | "dependencies": { |
143 | "ajv": "^6.12.4", | 143 | "ajv": "^6.12.4", |
@@ -147,7 +147,6 @@ | |||
147 | "ignore": "^4.0.6", | 147 | "ignore": "^4.0.6", |
148 | "import-fresh": "^3.2.1", | 148 | "import-fresh": "^3.2.1", |
149 | "js-yaml": "^3.13.1", | 149 | "js-yaml": "^3.13.1", |
150 | "lodash": "^4.17.20", | ||
151 | "minimatch": "^3.0.4", | 150 | "minimatch": "^3.0.4", |
152 | "strip-json-comments": "^3.1.1" | 151 | "strip-json-comments": "^3.1.1" |
153 | }, | 152 | }, |
@@ -155,6 +154,30 @@ | |||
155 | "node": "^10.12.0 || >=12.0.0" | 154 | "node": "^10.12.0 || >=12.0.0" |
156 | } | 155 | } |
157 | }, | 156 | }, |
157 | "node_modules/@eslint/eslintrc/node_modules/globals": { | ||
158 | "version": "12.4.0", | ||
159 | "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", | ||
160 | "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", | ||
161 | "dev": true, | ||
162 | "dependencies": { | ||
163 | "type-fest": "^0.8.1" | ||
164 | }, | ||
165 | "engines": { | ||
166 | "node": ">=8" | ||
167 | }, | ||
168 | "funding": { | ||
169 | "url": "https://github.com/sponsors/sindresorhus" | ||
170 | } | ||
171 | }, | ||
172 | "node_modules/@eslint/eslintrc/node_modules/type-fest": { | ||
173 | "version": "0.8.1", | ||
174 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", | ||
175 | "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", | ||
176 | "dev": true, | ||
177 | "engines": { | ||
178 | "node": ">=8" | ||
179 | } | ||
180 | }, | ||
158 | "node_modules/@nodelib/fs.scandir": { | 181 | "node_modules/@nodelib/fs.scandir": { |
159 | "version": "2.1.4", | 182 | "version": "2.1.4", |
160 | "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", | 183 | "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", |
@@ -212,9 +235,9 @@ | |||
212 | } | 235 | } |
213 | }, | 236 | }, |
214 | "node_modules/@rollup/plugin-node-resolve": { | 237 | "node_modules/@rollup/plugin-node-resolve": { |
215 | "version": "11.2.0", | 238 | "version": "11.2.1", |
216 | "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.0.tgz", | 239 | "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz", |
217 | "integrity": "sha512-qHjNIKYt5pCcn+5RUBQxK8krhRvf1HnyVgUCcFFcweDS7fhkOLZeYh0mhHK6Ery8/bb9tvN/ubPzmfF0qjDCTA==", | 240 | "integrity": "sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==", |
218 | "dev": true, | 241 | "dev": true, |
219 | "dependencies": { | 242 | "dependencies": { |
220 | "@rollup/pluginutils": "^3.1.0", | 243 | "@rollup/pluginutils": "^3.1.0", |
@@ -286,15 +309,15 @@ | |||
286 | "dev": true | 309 | "dev": true |
287 | }, | 310 | }, |
288 | "node_modules/@types/minimatch": { | 311 | "node_modules/@types/minimatch": { |
289 | "version": "3.0.3", | 312 | "version": "3.0.4", |
290 | "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", | 313 | "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.4.tgz", |
291 | "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", | 314 | "integrity": "sha512-1z8k4wzFnNjVK/tlxvrWuK5WMt6mydWWP7+zvH5eFep4oj+UkrfiJTRtjCeBXNpwaA/FYqqtb4/QS4ianFpIRA==", |
292 | "dev": true | 315 | "dev": true |
293 | }, | 316 | }, |
294 | "node_modules/@types/mocha": { | 317 | "node_modules/@types/mocha": { |
295 | "version": "8.2.1", | 318 | "version": "8.2.2", |
296 | "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.1.tgz", | 319 | "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.2.tgz", |
297 | "integrity": "sha512-NysN+bNqj6E0Hv4CTGWSlPzMW6vTKjDpOteycDkV4IWBsO+PU48JonrPzV9ODjiI2XrjmA05KInLgF5ivZ/YGQ==", | 320 | "integrity": "sha512-Lwh0lzzqT5Pqh6z61P3c3P5nm6fzQK/MMHl9UKeneAeInVflBSz1O2EkX6gM6xfJd7FBXBY5purtLx7fUiZ7Hw==", |
298 | "dev": true | 321 | "dev": true |
299 | }, | 322 | }, |
300 | "node_modules/@types/node": { | 323 | "node_modules/@types/node": { |
@@ -304,9 +327,9 @@ | |||
304 | "dev": true | 327 | "dev": true |
305 | }, | 328 | }, |
306 | "node_modules/@types/node-fetch": { | 329 | "node_modules/@types/node-fetch": { |
307 | "version": "2.5.8", | 330 | "version": "2.5.10", |
308 | "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.8.tgz", | 331 | "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.10.tgz", |
309 | "integrity": "sha512-fbjI6ja0N5ZA8TV53RUqzsKNkl9fv8Oj3T7zxW7FGv1GSH7gwJaNF8dzCjrqKaxKeUpTz4yT1DaJFq/omNpGfw==", | 332 | "integrity": "sha512-IpkX0AasN44hgEad0gEF/V6EgR5n69VEqPEgnmoM8GsIGro3PowbWs4tR6IhxUTyPLpOn+fiGG6nrQhcmoCuIQ==", |
310 | "dev": true, | 333 | "dev": true, |
311 | "dependencies": { | 334 | "dependencies": { |
312 | "@types/node": "*", | 335 | "@types/node": "*", |
@@ -323,19 +346,19 @@ | |||
323 | } | 346 | } |
324 | }, | 347 | }, |
325 | "node_modules/@types/vscode": { | 348 | "node_modules/@types/vscode": { |
326 | "version": "1.53.0", | 349 | "version": "1.55.0", |
327 | "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.53.0.tgz", | 350 | "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.55.0.tgz", |
328 | "integrity": "sha512-XjFWbSPOM0EKIT2XhhYm3D3cx3nn3lshMUcWNy1eqefk+oqRuBq8unVb6BYIZqXy9lQZyeUl7eaBCOZWv+LcXQ==", | 351 | "integrity": "sha512-49hysH7jneTQoSC8TWbAi7nKK9Lc5osQNjmDHVosrcU8o3jecD9GrK0Qyul8q4aGPSXRfNGqIp9CBdb13akETg==", |
329 | "dev": true | 352 | "dev": true |
330 | }, | 353 | }, |
331 | "node_modules/@typescript-eslint/eslint-plugin": { | 354 | "node_modules/@typescript-eslint/eslint-plugin": { |
332 | "version": "4.15.2", | 355 | "version": "4.22.0", |
333 | "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.15.2.tgz", | 356 | "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.22.0.tgz", |
334 | "integrity": "sha512-uiQQeu9tWl3f1+oK0yoAv9lt/KXO24iafxgQTkIYO/kitruILGx3uH+QtIAHqxFV+yIsdnJH+alel9KuE3J15Q==", | 357 | "integrity": "sha512-U8SP9VOs275iDXaL08Ln1Fa/wLXfj5aTr/1c0t0j6CdbOnxh+TruXu1p4I0NAvdPBQgoPjHsgKn28mOi0FzfoA==", |
335 | "dev": true, | 358 | "dev": true, |
336 | "dependencies": { | 359 | "dependencies": { |
337 | "@typescript-eslint/experimental-utils": "4.15.2", | 360 | "@typescript-eslint/experimental-utils": "4.22.0", |
338 | "@typescript-eslint/scope-manager": "4.15.2", | 361 | "@typescript-eslint/scope-manager": "4.22.0", |
339 | "debug": "^4.1.1", | 362 | "debug": "^4.1.1", |
340 | "functional-red-black-tree": "^1.0.1", | 363 | "functional-red-black-tree": "^1.0.1", |
341 | "lodash": "^4.17.15", | 364 | "lodash": "^4.17.15", |
@@ -361,15 +384,15 @@ | |||
361 | } | 384 | } |
362 | }, | 385 | }, |
363 | "node_modules/@typescript-eslint/experimental-utils": { | 386 | "node_modules/@typescript-eslint/experimental-utils": { |
364 | "version": "4.15.2", | 387 | "version": "4.22.0", |
365 | "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.15.2.tgz", | 388 | "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.22.0.tgz", |
366 | "integrity": "sha512-Fxoshw8+R5X3/Vmqwsjc8nRO/7iTysRtDqx6rlfLZ7HbT8TZhPeQqbPjTyk2RheH3L8afumecTQnUc9EeXxohQ==", | 389 | "integrity": "sha512-xJXHHl6TuAxB5AWiVrGhvbGL8/hbiCQ8FiWwObO3r0fnvBdrbWEDy1hlvGQOAWc6qsCWuWMKdVWlLAEMpxnddg==", |
367 | "dev": true, | 390 | "dev": true, |
368 | "dependencies": { | 391 | "dependencies": { |
369 | "@types/json-schema": "^7.0.3", | 392 | "@types/json-schema": "^7.0.3", |
370 | "@typescript-eslint/scope-manager": "4.15.2", | 393 | "@typescript-eslint/scope-manager": "4.22.0", |
371 | "@typescript-eslint/types": "4.15.2", | 394 | "@typescript-eslint/types": "4.22.0", |
372 | "@typescript-eslint/typescript-estree": "4.15.2", | 395 | "@typescript-eslint/typescript-estree": "4.22.0", |
373 | "eslint-scope": "^5.0.0", | 396 | "eslint-scope": "^5.0.0", |
374 | "eslint-utils": "^2.0.0" | 397 | "eslint-utils": "^2.0.0" |
375 | }, | 398 | }, |
@@ -385,14 +408,14 @@ | |||
385 | } | 408 | } |
386 | }, | 409 | }, |
387 | "node_modules/@typescript-eslint/parser": { | 410 | "node_modules/@typescript-eslint/parser": { |
388 | "version": "4.15.2", | 411 | "version": "4.22.0", |
389 | "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.15.2.tgz", | 412 | "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.22.0.tgz", |
390 | "integrity": "sha512-SHeF8xbsC6z2FKXsaTb1tBCf0QZsjJ94H6Bo51Y1aVEZ4XAefaw5ZAilMoDPlGghe+qtq7XdTiDlGfVTOmvA+Q==", | 413 | "integrity": "sha512-z/bGdBJJZJN76nvAY9DkJANYgK3nlRstRRi74WHm3jjgf2I8AglrSY+6l7ogxOmn55YJ6oKZCLLy+6PW70z15Q==", |
391 | "dev": true, | 414 | "dev": true, |
392 | "dependencies": { | 415 | "dependencies": { |
393 | "@typescript-eslint/scope-manager": "4.15.2", | 416 | "@typescript-eslint/scope-manager": "4.22.0", |
394 | "@typescript-eslint/types": "4.15.2", | 417 | "@typescript-eslint/types": "4.22.0", |
395 | "@typescript-eslint/typescript-estree": "4.15.2", | 418 | "@typescript-eslint/typescript-estree": "4.22.0", |
396 | "debug": "^4.1.1" | 419 | "debug": "^4.1.1" |
397 | }, | 420 | }, |
398 | "engines": { | 421 | "engines": { |
@@ -412,13 +435,13 @@ | |||
412 | } | 435 | } |
413 | }, | 436 | }, |
414 | "node_modules/@typescript-eslint/scope-manager": { | 437 | "node_modules/@typescript-eslint/scope-manager": { |
415 | "version": "4.15.2", | 438 | "version": "4.22.0", |
416 | "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.15.2.tgz", | 439 | "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.22.0.tgz", |
417 | "integrity": "sha512-Zm0tf/MSKuX6aeJmuXexgdVyxT9/oJJhaCkijv0DvJVT3ui4zY6XYd6iwIo/8GEZGy43cd7w1rFMiCLHbRzAPQ==", | 440 | "integrity": "sha512-OcCO7LTdk6ukawUM40wo61WdeoA7NM/zaoq1/2cs13M7GyiF+T4rxuA4xM+6LeHWjWbss7hkGXjFDRcKD4O04Q==", |
418 | "dev": true, | 441 | "dev": true, |
419 | "dependencies": { | 442 | "dependencies": { |
420 | "@typescript-eslint/types": "4.15.2", | 443 | "@typescript-eslint/types": "4.22.0", |
421 | "@typescript-eslint/visitor-keys": "4.15.2" | 444 | "@typescript-eslint/visitor-keys": "4.22.0" |
422 | }, | 445 | }, |
423 | "engines": { | 446 | "engines": { |
424 | "node": "^8.10.0 || ^10.13.0 || >=11.10.1" | 447 | "node": "^8.10.0 || ^10.13.0 || >=11.10.1" |
@@ -429,9 +452,9 @@ | |||
429 | } | 452 | } |
430 | }, | 453 | }, |
431 | "node_modules/@typescript-eslint/types": { | 454 | "node_modules/@typescript-eslint/types": { |
432 | "version": "4.15.2", | 455 | "version": "4.22.0", |
433 | "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.15.2.tgz", | 456 | "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.22.0.tgz", |
434 | "integrity": "sha512-r7lW7HFkAarfUylJ2tKndyO9njwSyoy6cpfDKWPX6/ctZA+QyaYscAHXVAfJqtnY6aaTwDYrOhp+ginlbc7HfQ==", | 457 | "integrity": "sha512-sW/BiXmmyMqDPO2kpOhSy2Py5w6KvRRsKZnV0c4+0nr4GIcedJwXAq+RHNK4lLVEZAJYFltnnk1tJSlbeS9lYA==", |
435 | "dev": true, | 458 | "dev": true, |
436 | "engines": { | 459 | "engines": { |
437 | "node": "^8.10.0 || ^10.13.0 || >=11.10.1" | 460 | "node": "^8.10.0 || ^10.13.0 || >=11.10.1" |
@@ -442,13 +465,13 @@ | |||
442 | } | 465 | } |
443 | }, | 466 | }, |
444 | "node_modules/@typescript-eslint/typescript-estree": { | 467 | "node_modules/@typescript-eslint/typescript-estree": { |
445 | "version": "4.15.2", | 468 | "version": "4.22.0", |
446 | "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.15.2.tgz", | 469 | "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.22.0.tgz", |
447 | "integrity": "sha512-cGR8C2g5SPtHTQvAymEODeqx90pJHadWsgTtx6GbnTWKqsg7yp6Eaya9nFzUd4KrKhxdYTTFBiYeTPQaz/l8bw==", | 470 | "integrity": "sha512-TkIFeu5JEeSs5ze/4NID+PIcVjgoU3cUQUIZnH3Sb1cEn1lBo7StSV5bwPuJQuoxKXlzAObjYTilOEKRuhR5yg==", |
448 | "dev": true, | 471 | "dev": true, |
449 | "dependencies": { | 472 | "dependencies": { |
450 | "@typescript-eslint/types": "4.15.2", | 473 | "@typescript-eslint/types": "4.22.0", |
451 | "@typescript-eslint/visitor-keys": "4.15.2", | 474 | "@typescript-eslint/visitor-keys": "4.22.0", |
452 | "debug": "^4.1.1", | 475 | "debug": "^4.1.1", |
453 | "globby": "^11.0.1", | 476 | "globby": "^11.0.1", |
454 | "is-glob": "^4.0.1", | 477 | "is-glob": "^4.0.1", |
@@ -469,12 +492,12 @@ | |||
469 | } | 492 | } |
470 | }, | 493 | }, |
471 | "node_modules/@typescript-eslint/visitor-keys": { | 494 | "node_modules/@typescript-eslint/visitor-keys": { |
472 | "version": "4.15.2", | 495 | "version": "4.22.0", |
473 | "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.15.2.tgz", | 496 | "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.22.0.tgz", |
474 | "integrity": "sha512-TME1VgSb7wTwgENN5KVj4Nqg25hP8DisXxNBojM4Nn31rYaNDIocNm5cmjOFfh42n7NVERxWrDFoETO/76ePyg==", | 497 | "integrity": "sha512-nnMu4F+s4o0sll6cBSsTeVsT4cwxB7zECK3dFxzEjPBii9xLpq4yqqsy/FU5zMfan6G60DKZSCXAa3sHJZrcYw==", |
475 | "dev": true, | 498 | "dev": true, |
476 | "dependencies": { | 499 | "dependencies": { |
477 | "@typescript-eslint/types": "4.15.2", | 500 | "@typescript-eslint/types": "4.22.0", |
478 | "eslint-visitor-keys": "^2.0.0" | 501 | "eslint-visitor-keys": "^2.0.0" |
479 | }, | 502 | }, |
480 | "engines": { | 503 | "engines": { |
@@ -573,9 +596,9 @@ | |||
573 | } | 596 | } |
574 | }, | 597 | }, |
575 | "node_modules/anymatch": { | 598 | "node_modules/anymatch": { |
576 | "version": "3.1.1", | 599 | "version": "3.1.2", |
577 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", | 600 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", |
578 | "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", | 601 | "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", |
579 | "dev": true, | 602 | "dev": true, |
580 | "dependencies": { | 603 | "dependencies": { |
581 | "normalize-path": "^3.0.0", | 604 | "normalize-path": "^3.0.0", |
@@ -631,9 +654,9 @@ | |||
631 | } | 654 | } |
632 | }, | 655 | }, |
633 | "node_modules/balanced-match": { | 656 | "node_modules/balanced-match": { |
634 | "version": "1.0.0", | 657 | "version": "1.0.2", |
635 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", | 658 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", |
636 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" | 659 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" |
637 | }, | 660 | }, |
638 | "node_modules/big-integer": { | 661 | "node_modules/big-integer": { |
639 | "version": "1.6.48", | 662 | "version": "1.6.48", |
@@ -772,9 +795,9 @@ | |||
772 | } | 795 | } |
773 | }, | 796 | }, |
774 | "node_modules/chalk": { | 797 | "node_modules/chalk": { |
775 | "version": "4.1.0", | 798 | "version": "4.1.1", |
776 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", | 799 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", |
777 | "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", | 800 | "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", |
778 | "dev": true, | 801 | "dev": true, |
779 | "dependencies": { | 802 | "dependencies": { |
780 | "ansi-styles": "^4.1.0", | 803 | "ansi-styles": "^4.1.0", |
@@ -788,35 +811,33 @@ | |||
788 | } | 811 | } |
789 | }, | 812 | }, |
790 | "node_modules/cheerio": { | 813 | "node_modules/cheerio": { |
791 | "version": "1.0.0-rc.5", | 814 | "version": "1.0.0-rc.6", |
792 | "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.5.tgz", | 815 | "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.6.tgz", |
793 | "integrity": "sha512-yoqps/VCaZgN4pfXtenwHROTp8NG6/Hlt4Jpz2FEP0ZJQ+ZUkVDd0hAPDNKhj3nakpfPt/CNs57yEtxD1bXQiw==", | 816 | "integrity": "sha512-hjx1XE1M/D5pAtMgvWwE21QClmAEeGHOIDfycgmndisdNgI6PE1cGRQkMGBcsbUbmEQyWu5PJLUcAOjtQS8DWw==", |
794 | "dev": true, | 817 | "dev": true, |
795 | "dependencies": { | 818 | "dependencies": { |
796 | "cheerio-select-tmp": "^0.1.0", | 819 | "cheerio-select": "^1.3.0", |
797 | "dom-serializer": "~1.2.0", | 820 | "dom-serializer": "^1.3.1", |
798 | "domhandler": "^4.0.0", | 821 | "domhandler": "^4.1.0", |
799 | "entities": "~2.1.0", | 822 | "htmlparser2": "^6.1.0", |
800 | "htmlparser2": "^6.0.0", | 823 | "parse5": "^6.0.1", |
801 | "parse5": "^6.0.0", | 824 | "parse5-htmlparser2-tree-adapter": "^6.0.1" |
802 | "parse5-htmlparser2-tree-adapter": "^6.0.0" | ||
803 | }, | 825 | }, |
804 | "engines": { | 826 | "engines": { |
805 | "node": ">= 0.12" | 827 | "node": ">= 0.12" |
806 | } | 828 | } |
807 | }, | 829 | }, |
808 | "node_modules/cheerio-select-tmp": { | 830 | "node_modules/cheerio-select": { |
809 | "version": "0.1.1", | 831 | "version": "1.4.0", |
810 | "resolved": "https://registry.npmjs.org/cheerio-select-tmp/-/cheerio-select-tmp-0.1.1.tgz", | 832 | "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.4.0.tgz", |
811 | "integrity": "sha512-YYs5JvbpU19VYJyj+F7oYrIE2BOll1/hRU7rEy/5+v9BzkSo3bK81iAeeQEMI92vRIxz677m72UmJUiVwwgjfQ==", | 833 | "integrity": "sha512-sobR3Yqz27L553Qa7cK6rtJlMDbiKPdNywtR95Sj/YgfpLfy0u6CGJuaBKe5YE/vTc23SCRKxWSdlon/w6I/Ew==", |
812 | "deprecated": "Use cheerio-select instead", | ||
813 | "dev": true, | 834 | "dev": true, |
814 | "dependencies": { | 835 | "dependencies": { |
815 | "css-select": "^3.1.2", | 836 | "css-select": "^4.1.2", |
816 | "css-what": "^4.0.0", | 837 | "css-what": "^5.0.0", |
817 | "domelementtype": "^2.1.0", | 838 | "domelementtype": "^2.2.0", |
818 | "domhandler": "^4.0.0", | 839 | "domhandler": "^4.2.0", |
819 | "domutils": "^2.4.4" | 840 | "domutils": "^2.6.0" |
820 | }, | 841 | }, |
821 | "funding": { | 842 | "funding": { |
822 | "url": "https://github.com/sponsors/fb55" | 843 | "url": "https://github.com/sponsors/fb55" |
@@ -830,7 +851,6 @@ | |||
830 | "dependencies": { | 851 | "dependencies": { |
831 | "anymatch": "~3.1.1", | 852 | "anymatch": "~3.1.1", |
832 | "braces": "~3.0.2", | 853 | "braces": "~3.0.2", |
833 | "fsevents": "~2.3.1", | ||
834 | "glob-parent": "~5.1.0", | 854 | "glob-parent": "~5.1.0", |
835 | "is-binary-path": "~2.1.0", | 855 | "is-binary-path": "~2.1.0", |
836 | "is-glob": "~4.0.1", | 856 | "is-glob": "~4.0.1", |
@@ -929,15 +949,15 @@ | |||
929 | } | 949 | } |
930 | }, | 950 | }, |
931 | "node_modules/css-select": { | 951 | "node_modules/css-select": { |
932 | "version": "3.1.2", | 952 | "version": "4.1.2", |
933 | "resolved": "https://registry.npmjs.org/css-select/-/css-select-3.1.2.tgz", | 953 | "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.2.tgz", |
934 | "integrity": "sha512-qmss1EihSuBNWNNhHjxzxSfJoFBM/lERB/Q4EnsJQQC62R2evJDW481091oAdOr9uh46/0n4nrg0It5cAnj1RA==", | 954 | "integrity": "sha512-nu5ye2Hg/4ISq4XqdLY2bEatAcLIdt3OYGFc9Tm9n7VSlFBcfRv0gBNksHRgSdUDQGtN3XrZ94ztW+NfzkFSUw==", |
935 | "dev": true, | 955 | "dev": true, |
936 | "dependencies": { | 956 | "dependencies": { |
937 | "boolbase": "^1.0.0", | 957 | "boolbase": "^1.0.0", |
938 | "css-what": "^4.0.0", | 958 | "css-what": "^5.0.0", |
939 | "domhandler": "^4.0.0", | 959 | "domhandler": "^4.2.0", |
940 | "domutils": "^2.4.3", | 960 | "domutils": "^2.6.0", |
941 | "nth-check": "^2.0.0" | 961 | "nth-check": "^2.0.0" |
942 | }, | 962 | }, |
943 | "funding": { | 963 | "funding": { |
@@ -945,9 +965,9 @@ | |||
945 | } | 965 | } |
946 | }, | 966 | }, |
947 | "node_modules/css-what": { | 967 | "node_modules/css-what": { |
948 | "version": "4.0.0", | 968 | "version": "5.0.0", |
949 | "resolved": "https://registry.npmjs.org/css-what/-/css-what-4.0.0.tgz", | 969 | "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.0.0.tgz", |
950 | "integrity": "sha512-teijzG7kwYfNVsUh2H/YN62xW3KK9YhXEgSlbxMlcyjPNvdKJqFx5lrwlJgoFP1ZHlB89iGDlo/JyshKeRhv5A==", | 970 | "integrity": "sha512-qxyKHQvgKwzwDWC/rGbT821eJalfupxYW2qbSJSAtdSTimsr/MlaGONoNLllaUPZWf8QnbcKM/kPVYUQuEKAFA==", |
951 | "dev": true, | 971 | "dev": true, |
952 | "engines": { | 972 | "engines": { |
953 | "node": ">= 6" | 973 | "node": ">= 6" |
@@ -1048,9 +1068,9 @@ | |||
1048 | } | 1068 | } |
1049 | }, | 1069 | }, |
1050 | "node_modules/dom-serializer": { | 1070 | "node_modules/dom-serializer": { |
1051 | "version": "1.2.0", | 1071 | "version": "1.3.1", |
1052 | "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.2.0.tgz", | 1072 | "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.1.tgz", |
1053 | "integrity": "sha512-n6kZFH/KlCrqs/1GHMOd5i2fd/beQHuehKdWvNNffbGHTr/almdhuVvTVFb3V7fglz+nC50fFusu3lY33h12pA==", | 1073 | "integrity": "sha512-Pv2ZluG5ife96udGgEDovOOOA5UELkltfJpnIExPrAk1LTvecolUGn6lIaoLh86d83GiB86CjzciMd9BuRB71Q==", |
1054 | "dev": true, | 1074 | "dev": true, |
1055 | "dependencies": { | 1075 | "dependencies": { |
1056 | "domelementtype": "^2.0.1", | 1076 | "domelementtype": "^2.0.1", |
@@ -1062,9 +1082,9 @@ | |||
1062 | } | 1082 | } |
1063 | }, | 1083 | }, |
1064 | "node_modules/domelementtype": { | 1084 | "node_modules/domelementtype": { |
1065 | "version": "2.1.0", | 1085 | "version": "2.2.0", |
1066 | "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.1.0.tgz", | 1086 | "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", |
1067 | "integrity": "sha512-LsTgx/L5VpD+Q8lmsXSHW2WpA+eBlZ9HPf3erD1IoPF00/3JKHZ3BknUVA2QGDNu69ZNmyFmCWBSO45XjYKC5w==", | 1087 | "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", |
1068 | "dev": true, | 1088 | "dev": true, |
1069 | "funding": [ | 1089 | "funding": [ |
1070 | { | 1090 | { |
@@ -1074,12 +1094,12 @@ | |||
1074 | ] | 1094 | ] |
1075 | }, | 1095 | }, |
1076 | "node_modules/domhandler": { | 1096 | "node_modules/domhandler": { |
1077 | "version": "4.0.0", | 1097 | "version": "4.2.0", |
1078 | "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.0.0.tgz", | 1098 | "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.0.tgz", |
1079 | "integrity": "sha512-KPTbnGQ1JeEMQyO1iYXoagsI6so/C96HZiFyByU3T6iAzpXn8EGEvct6unm1ZGoed8ByO2oirxgwxBmqKF9haA==", | 1099 | "integrity": "sha512-zk7sgt970kzPks2Bf+dwT/PLzghLnsivb9CcxkvR8Mzr66Olr0Ofd8neSbglHJHaHa2MadfoSdNlKYAaafmWfA==", |
1080 | "dev": true, | 1100 | "dev": true, |
1081 | "dependencies": { | 1101 | "dependencies": { |
1082 | "domelementtype": "^2.1.0" | 1102 | "domelementtype": "^2.2.0" |
1083 | }, | 1103 | }, |
1084 | "engines": { | 1104 | "engines": { |
1085 | "node": ">= 4" | 1105 | "node": ">= 4" |
@@ -1089,14 +1109,14 @@ | |||
1089 | } | 1109 | } |
1090 | }, | 1110 | }, |
1091 | "node_modules/domutils": { | 1111 | "node_modules/domutils": { |
1092 | "version": "2.4.4", | 1112 | "version": "2.6.0", |
1093 | "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.4.4.tgz", | 1113 | "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.6.0.tgz", |
1094 | "integrity": "sha512-jBC0vOsECI4OMdD0GC9mGn7NXPLb+Qt6KW1YDQzeQYRUFKmNG8lh7mO5HiELfr+lLQE7loDVI4QcAxV80HS+RA==", | 1114 | "integrity": "sha512-y0BezHuy4MDYxh6OvolXYsH+1EMGmFbwv5FKW7ovwMG6zTPWqNPq3WF9ayZssFq+UlKdffGLbOEaghNdaOm1WA==", |
1095 | "dev": true, | 1115 | "dev": true, |
1096 | "dependencies": { | 1116 | "dependencies": { |
1097 | "dom-serializer": "^1.0.1", | 1117 | "dom-serializer": "^1.0.1", |
1098 | "domelementtype": "^2.0.1", | 1118 | "domelementtype": "^2.2.0", |
1099 | "domhandler": "^4.0.0" | 1119 | "domhandler": "^4.2.0" |
1100 | }, | 1120 | }, |
1101 | "funding": { | 1121 | "funding": { |
1102 | "url": "https://github.com/fb55/domutils?sponsor=1" | 1122 | "url": "https://github.com/fb55/domutils?sponsor=1" |
@@ -1167,9 +1187,9 @@ | |||
1167 | } | 1187 | } |
1168 | }, | 1188 | }, |
1169 | "node_modules/entities": { | 1189 | "node_modules/entities": { |
1170 | "version": "2.1.0", | 1190 | "version": "2.2.0", |
1171 | "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", | 1191 | "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", |
1172 | "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", | 1192 | "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", |
1173 | "dev": true, | 1193 | "dev": true, |
1174 | "funding": { | 1194 | "funding": { |
1175 | "url": "https://github.com/fb55/entities?sponsor=1" | 1195 | "url": "https://github.com/fb55/entities?sponsor=1" |
@@ -1197,13 +1217,13 @@ | |||
1197 | } | 1217 | } |
1198 | }, | 1218 | }, |
1199 | "node_modules/eslint": { | 1219 | "node_modules/eslint": { |
1200 | "version": "7.20.0", | 1220 | "version": "7.25.0", |
1201 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.20.0.tgz", | 1221 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.25.0.tgz", |
1202 | "integrity": "sha512-qGi0CTcOGP2OtCQBgWZlQjcTuP0XkIpYFj25XtRTQSHC+umNnp7UMshr2G8SLsRFYDdAPFeHOsiteadmMH02Yw==", | 1222 | "integrity": "sha512-TVpSovpvCNpLURIScDRB6g5CYu/ZFq9GfX2hLNIV4dSBKxIWojeDODvYl3t0k0VtMxYeR8OXPCFE5+oHMlGfhw==", |
1203 | "dev": true, | 1223 | "dev": true, |
1204 | "dependencies": { | 1224 | "dependencies": { |
1205 | "@babel/code-frame": "7.12.11", | 1225 | "@babel/code-frame": "7.12.11", |
1206 | "@eslint/eslintrc": "^0.3.0", | 1226 | "@eslint/eslintrc": "^0.4.0", |
1207 | "ajv": "^6.10.0", | 1227 | "ajv": "^6.10.0", |
1208 | "chalk": "^4.0.0", | 1228 | "chalk": "^4.0.0", |
1209 | "cross-spawn": "^7.0.2", | 1229 | "cross-spawn": "^7.0.2", |
@@ -1216,10 +1236,10 @@ | |||
1216 | "espree": "^7.3.1", | 1236 | "espree": "^7.3.1", |
1217 | "esquery": "^1.4.0", | 1237 | "esquery": "^1.4.0", |
1218 | "esutils": "^2.0.2", | 1238 | "esutils": "^2.0.2", |
1219 | "file-entry-cache": "^6.0.0", | 1239 | "file-entry-cache": "^6.0.1", |
1220 | "functional-red-black-tree": "^1.0.1", | 1240 | "functional-red-black-tree": "^1.0.1", |
1221 | "glob-parent": "^5.0.0", | 1241 | "glob-parent": "^5.0.0", |
1222 | "globals": "^12.1.0", | 1242 | "globals": "^13.6.0", |
1223 | "ignore": "^4.0.6", | 1243 | "ignore": "^4.0.6", |
1224 | "import-fresh": "^3.0.0", | 1244 | "import-fresh": "^3.0.0", |
1225 | "imurmurhash": "^0.1.4", | 1245 | "imurmurhash": "^0.1.4", |
@@ -1227,7 +1247,7 @@ | |||
1227 | "js-yaml": "^3.13.1", | 1247 | "js-yaml": "^3.13.1", |
1228 | "json-stable-stringify-without-jsonify": "^1.0.1", | 1248 | "json-stable-stringify-without-jsonify": "^1.0.1", |
1229 | "levn": "^0.4.1", | 1249 | "levn": "^0.4.1", |
1230 | "lodash": "^4.17.20", | 1250 | "lodash": "^4.17.21", |
1231 | "minimatch": "^3.0.4", | 1251 | "minimatch": "^3.0.4", |
1232 | "natural-compare": "^1.4.0", | 1252 | "natural-compare": "^1.4.0", |
1233 | "optionator": "^0.9.1", | 1253 | "optionator": "^0.9.1", |
@@ -1434,9 +1454,9 @@ | |||
1434 | "dev": true | 1454 | "dev": true |
1435 | }, | 1455 | }, |
1436 | "node_modules/fastq": { | 1456 | "node_modules/fastq": { |
1437 | "version": "1.10.1", | 1457 | "version": "1.11.0", |
1438 | "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.10.1.tgz", | 1458 | "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz", |
1439 | "integrity": "sha512-AWuv6Ery3pM+dY7LYS8YIaCiQvUaos9OB1RyNgaOWnaX+Tik7Onvcsf8x8c+YtDeT0maYLniBip2hox5KtEXXA==", | 1459 | "integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==", |
1440 | "dev": true, | 1460 | "dev": true, |
1441 | "dependencies": { | 1461 | "dependencies": { |
1442 | "reusify": "^1.0.4" | 1462 | "reusify": "^1.0.4" |
@@ -1622,9 +1642,9 @@ | |||
1622 | } | 1642 | } |
1623 | }, | 1643 | }, |
1624 | "node_modules/glob-parent": { | 1644 | "node_modules/glob-parent": { |
1625 | "version": "5.1.1", | 1645 | "version": "5.1.2", |
1626 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", | 1646 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", |
1627 | "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", | 1647 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", |
1628 | "dev": true, | 1648 | "dev": true, |
1629 | "dependencies": { | 1649 | "dependencies": { |
1630 | "is-glob": "^4.0.1" | 1650 | "is-glob": "^4.0.1" |
@@ -1634,12 +1654,12 @@ | |||
1634 | } | 1654 | } |
1635 | }, | 1655 | }, |
1636 | "node_modules/globals": { | 1656 | "node_modules/globals": { |
1637 | "version": "12.4.0", | 1657 | "version": "13.8.0", |
1638 | "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", | 1658 | "resolved": "https://registry.npmjs.org/globals/-/globals-13.8.0.tgz", |
1639 | "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", | 1659 | "integrity": "sha512-rHtdA6+PDBIjeEvA91rpqzEvk/k3/i7EeNQiryiWuJH0Hw9cpyJMAt2jtbAwUaRdhD+573X4vWw6IcjKPasi9Q==", |
1640 | "dev": true, | 1660 | "dev": true, |
1641 | "dependencies": { | 1661 | "dependencies": { |
1642 | "type-fest": "^0.8.1" | 1662 | "type-fest": "^0.20.2" |
1643 | }, | 1663 | }, |
1644 | "engines": { | 1664 | "engines": { |
1645 | "node": ">=8" | 1665 | "node": ">=8" |
@@ -1649,9 +1669,9 @@ | |||
1649 | } | 1669 | } |
1650 | }, | 1670 | }, |
1651 | "node_modules/globby": { | 1671 | "node_modules/globby": { |
1652 | "version": "11.0.2", | 1672 | "version": "11.0.3", |
1653 | "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.2.tgz", | 1673 | "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz", |
1654 | "integrity": "sha512-2ZThXDvvV8fYFRVIxnrMQBipZQDr7MxKAmQK1vujaj9/7eF0efG7BPUKJ7jP7G5SLF37xKDXvO4S/KKLj/Z0og==", | 1674 | "integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==", |
1655 | "dev": true, | 1675 | "dev": true, |
1656 | "dependencies": { | 1676 | "dependencies": { |
1657 | "array-union": "^2.1.0", | 1677 | "array-union": "^2.1.0", |
@@ -1723,9 +1743,9 @@ | |||
1723 | } | 1743 | } |
1724 | }, | 1744 | }, |
1725 | "node_modules/htmlparser2": { | 1745 | "node_modules/htmlparser2": { |
1726 | "version": "6.0.0", | 1746 | "version": "6.1.0", |
1727 | "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.0.0.tgz", | 1747 | "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", |
1728 | "integrity": "sha512-numTQtDZMoh78zJpaNdJ9MXb2cv5G3jwUoe3dMQODubZvLoGvTE/Ofp6sHvH8OGKcN/8A47pGLi/k58xHP/Tfw==", | 1748 | "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", |
1729 | "dev": true, | 1749 | "dev": true, |
1730 | "funding": [ | 1750 | "funding": [ |
1731 | "https://github.com/fb55/htmlparser2?sponsor=1", | 1751 | "https://github.com/fb55/htmlparser2?sponsor=1", |
@@ -1737,7 +1757,7 @@ | |||
1737 | "dependencies": { | 1757 | "dependencies": { |
1738 | "domelementtype": "^2.0.1", | 1758 | "domelementtype": "^2.0.1", |
1739 | "domhandler": "^4.0.0", | 1759 | "domhandler": "^4.0.0", |
1740 | "domutils": "^2.4.4", | 1760 | "domutils": "^2.5.2", |
1741 | "entities": "^2.0.0" | 1761 | "entities": "^2.0.0" |
1742 | } | 1762 | } |
1743 | }, | 1763 | }, |
@@ -1830,9 +1850,9 @@ | |||
1830 | } | 1850 | } |
1831 | }, | 1851 | }, |
1832 | "node_modules/is-core-module": { | 1852 | "node_modules/is-core-module": { |
1833 | "version": "2.2.0", | 1853 | "version": "2.3.0", |
1834 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", | 1854 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.3.0.tgz", |
1835 | "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", | 1855 | "integrity": "sha512-xSphU2KG9867tsYdLD4RWQ1VqdFl4HTO9Thf3I/3dLEfr0dbPTWKsuCKrgqMljg4nPE+Gq0VCnzT3gr0CyBmsw==", |
1836 | "dev": true, | 1856 | "dev": true, |
1837 | "dependencies": { | 1857 | "dependencies": { |
1838 | "has": "^1.0.3" | 1858 | "has": "^1.0.3" |
@@ -2005,6 +2025,24 @@ | |||
2005 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", | 2025 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", |
2006 | "dev": true | 2026 | "dev": true |
2007 | }, | 2027 | }, |
2028 | "node_modules/lodash.clonedeep": { | ||
2029 | "version": "4.5.0", | ||
2030 | "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", | ||
2031 | "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", | ||
2032 | "dev": true | ||
2033 | }, | ||
2034 | "node_modules/lodash.flatten": { | ||
2035 | "version": "4.4.0", | ||
2036 | "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", | ||
2037 | "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", | ||
2038 | "dev": true | ||
2039 | }, | ||
2040 | "node_modules/lodash.truncate": { | ||
2041 | "version": "4.4.2", | ||
2042 | "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", | ||
2043 | "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", | ||
2044 | "dev": true | ||
2045 | }, | ||
2008 | "node_modules/log-symbols": { | 2046 | "node_modules/log-symbols": { |
2009 | "version": "4.0.0", | 2047 | "version": "4.0.0", |
2010 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", | 2048 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", |
@@ -2075,16 +2113,16 @@ | |||
2075 | } | 2113 | } |
2076 | }, | 2114 | }, |
2077 | "node_modules/micromatch": { | 2115 | "node_modules/micromatch": { |
2078 | "version": "4.0.2", | 2116 | "version": "4.0.4", |
2079 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", | 2117 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", |
2080 | "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", | 2118 | "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", |
2081 | "dev": true, | 2119 | "dev": true, |
2082 | "dependencies": { | 2120 | "dependencies": { |
2083 | "braces": "^3.0.1", | 2121 | "braces": "^3.0.1", |
2084 | "picomatch": "^2.0.5" | 2122 | "picomatch": "^2.2.3" |
2085 | }, | 2123 | }, |
2086 | "engines": { | 2124 | "engines": { |
2087 | "node": ">=8" | 2125 | "node": ">=8.6" |
2088 | } | 2126 | } |
2089 | }, | 2127 | }, |
2090 | "node_modules/mime": { | 2128 | "node_modules/mime": { |
@@ -2100,21 +2138,21 @@ | |||
2100 | } | 2138 | } |
2101 | }, | 2139 | }, |
2102 | "node_modules/mime-db": { | 2140 | "node_modules/mime-db": { |
2103 | "version": "1.46.0", | 2141 | "version": "1.47.0", |
2104 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.46.0.tgz", | 2142 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz", |
2105 | "integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ==", | 2143 | "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==", |
2106 | "dev": true, | 2144 | "dev": true, |
2107 | "engines": { | 2145 | "engines": { |
2108 | "node": ">= 0.6" | 2146 | "node": ">= 0.6" |
2109 | } | 2147 | } |
2110 | }, | 2148 | }, |
2111 | "node_modules/mime-types": { | 2149 | "node_modules/mime-types": { |
2112 | "version": "2.1.29", | 2150 | "version": "2.1.30", |
2113 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.29.tgz", | 2151 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz", |
2114 | "integrity": "sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ==", | 2152 | "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", |
2115 | "dev": true, | 2153 | "dev": true, |
2116 | "dependencies": { | 2154 | "dependencies": { |
2117 | "mime-db": "1.46.0" | 2155 | "mime-db": "1.47.0" |
2118 | }, | 2156 | }, |
2119 | "engines": { | 2157 | "engines": { |
2120 | "node": ">= 0.6" | 2158 | "node": ">= 0.6" |
@@ -2150,9 +2188,9 @@ | |||
2150 | } | 2188 | } |
2151 | }, | 2189 | }, |
2152 | "node_modules/mocha": { | 2190 | "node_modules/mocha": { |
2153 | "version": "8.3.0", | 2191 | "version": "8.3.2", |
2154 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.3.0.tgz", | 2192 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.3.2.tgz", |
2155 | "integrity": "sha512-TQqyC89V1J/Vxx0DhJIXlq9gbbL9XFNdeLQ1+JsnZsVaSOV1z3tWfw0qZmQJGQRIfkvZcs7snQnZnOCKoldq1Q==", | 2193 | "integrity": "sha512-UdmISwr/5w+uXLPKspgoV7/RXZwKRTiTjJ2/AC5ZiEztIoOYdfKb19+9jNmEInzx5pBsCyJQzarAxqIGBNYJhg==", |
2156 | "dev": true, | 2194 | "dev": true, |
2157 | "dependencies": { | 2195 | "dependencies": { |
2158 | "@ungap/promise-all-settled": "1.1.2", | 2196 | "@ungap/promise-all-settled": "1.1.2", |
@@ -2474,9 +2512,9 @@ | |||
2474 | "dev": true | 2512 | "dev": true |
2475 | }, | 2513 | }, |
2476 | "node_modules/picomatch": { | 2514 | "node_modules/picomatch": { |
2477 | "version": "2.2.2", | 2515 | "version": "2.2.3", |
2478 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", | 2516 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz", |
2479 | "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", | 2517 | "integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==", |
2480 | "dev": true, | 2518 | "dev": true, |
2481 | "engines": { | 2519 | "engines": { |
2482 | "node": ">=8.6" | 2520 | "node": ">=8.6" |
@@ -2525,9 +2563,9 @@ | |||
2525 | } | 2563 | } |
2526 | }, | 2564 | }, |
2527 | "node_modules/queue-microtask": { | 2565 | "node_modules/queue-microtask": { |
2528 | "version": "1.2.2", | 2566 | "version": "1.2.3", |
2529 | "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.2.tgz", | 2567 | "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", |
2530 | "integrity": "sha512-dB15eXv3p2jDlbOiNLyMabYg1/sXvppd8DP2J3EOCQ0AkuSXCW2tP7mnVouVLJKgUMY6yP0kcQDVpLCN13h4Xg==", | 2568 | "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", |
2531 | "dev": true, | 2569 | "dev": true, |
2532 | "funding": [ | 2570 | "funding": [ |
2533 | { | 2571 | { |
@@ -2676,13 +2714,10 @@ | |||
2676 | } | 2714 | } |
2677 | }, | 2715 | }, |
2678 | "node_modules/rollup": { | 2716 | "node_modules/rollup": { |
2679 | "version": "2.39.1", | 2717 | "version": "2.45.2", |
2680 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.39.1.tgz", | 2718 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.45.2.tgz", |
2681 | "integrity": "sha512-9rfr0Z6j+vE+eayfNVFr1KZ+k+jiUl2+0e4quZafy1x6SFCjzFspfRSO2ZZQeWeX9noeDTUDgg6eCENiEPFvQg==", | 2719 | "integrity": "sha512-kRRU7wXzFHUzBIv0GfoFFIN3m9oteY4uAsKllIpQDId5cfnkWF2J130l+27dzDju0E6MScKiV0ZM5Bw8m4blYQ==", |
2682 | "dev": true, | 2720 | "dev": true, |
2683 | "dependencies": { | ||
2684 | "fsevents": "~2.3.1" | ||
2685 | }, | ||
2686 | "bin": { | 2721 | "bin": { |
2687 | "rollup": "dist/bin/rollup" | 2722 | "rollup": "dist/bin/rollup" |
2688 | }, | 2723 | }, |
@@ -2737,9 +2772,9 @@ | |||
2737 | ] | 2772 | ] |
2738 | }, | 2773 | }, |
2739 | "node_modules/semver": { | 2774 | "node_modules/semver": { |
2740 | "version": "7.3.4", | 2775 | "version": "7.3.5", |
2741 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", | 2776 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", |
2742 | "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", | 2777 | "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", |
2743 | "dependencies": { | 2778 | "dependencies": { |
2744 | "lru-cache": "^6.0.0" | 2779 | "lru-cache": "^6.0.0" |
2745 | }, | 2780 | }, |
@@ -2846,9 +2881,9 @@ | |||
2846 | "dev": true | 2881 | "dev": true |
2847 | }, | 2882 | }, |
2848 | "node_modules/string-width": { | 2883 | "node_modules/string-width": { |
2849 | "version": "4.2.0", | 2884 | "version": "4.2.2", |
2850 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", | 2885 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", |
2851 | "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", | 2886 | "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", |
2852 | "dev": true, | 2887 | "dev": true, |
2853 | "dependencies": { | 2888 | "dependencies": { |
2854 | "emoji-regex": "^8.0.0", | 2889 | "emoji-regex": "^8.0.0", |
@@ -2896,24 +2931,27 @@ | |||
2896 | } | 2931 | } |
2897 | }, | 2932 | }, |
2898 | "node_modules/table": { | 2933 | "node_modules/table": { |
2899 | "version": "6.0.7", | 2934 | "version": "6.5.1", |
2900 | "resolved": "https://registry.npmjs.org/table/-/table-6.0.7.tgz", | 2935 | "resolved": "https://registry.npmjs.org/table/-/table-6.5.1.tgz", |
2901 | "integrity": "sha512-rxZevLGTUzWna/qBLObOe16kB2RTnnbhciwgPbMMlazz1yZGVEgnZK762xyVdVznhqxrfCeBMmMkgOOaPwjH7g==", | 2936 | "integrity": "sha512-xGDXWTBJxahkzPQCsn1S9ESHEenU7TbMD5Iv4FeopXv/XwJyWatFjfbor+6ipI10/MNPXBYUamYukOrbPZ9L/w==", |
2902 | "dev": true, | 2937 | "dev": true, |
2903 | "dependencies": { | 2938 | "dependencies": { |
2904 | "ajv": "^7.0.2", | 2939 | "ajv": "^8.0.1", |
2905 | "lodash": "^4.17.20", | 2940 | "lodash.clonedeep": "^4.5.0", |
2941 | "lodash.flatten": "^4.4.0", | ||
2942 | "lodash.truncate": "^4.4.2", | ||
2906 | "slice-ansi": "^4.0.0", | 2943 | "slice-ansi": "^4.0.0", |
2907 | "string-width": "^4.2.0" | 2944 | "string-width": "^4.2.0", |
2945 | "strip-ansi": "^6.0.0" | ||
2908 | }, | 2946 | }, |
2909 | "engines": { | 2947 | "engines": { |
2910 | "node": ">=10.0.0" | 2948 | "node": ">=10.0.0" |
2911 | } | 2949 | } |
2912 | }, | 2950 | }, |
2913 | "node_modules/table/node_modules/ajv": { | 2951 | "node_modules/table/node_modules/ajv": { |
2914 | "version": "7.1.1", | 2952 | "version": "8.1.0", |
2915 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-7.1.1.tgz", | 2953 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.1.0.tgz", |
2916 | "integrity": "sha512-ga/aqDYnUy/o7vbsRTFhhTsNeXiYb5JWDIcRIeZfwRNCefwjNTVYCGdGSUrEmiu3yDK3vFvNbgJxvrQW4JXrYQ==", | 2954 | "integrity": "sha512-B/Sk2Ix7A36fs/ZkuGLIR86EdjbgR6fsAcbx9lOP/QBSXujDNbVmIS/U4Itz5k8fPFDeVZl/zQ/gJW4Jrq6XjQ==", |
2917 | "dev": true, | 2955 | "dev": true, |
2918 | "dependencies": { | 2956 | "dependencies": { |
2919 | "fast-deep-equal": "^3.1.1", | 2957 | "fast-deep-equal": "^3.1.1", |
@@ -2969,15 +3007,15 @@ | |||
2969 | "dev": true | 3007 | "dev": true |
2970 | }, | 3008 | }, |
2971 | "node_modules/tslib": { | 3009 | "node_modules/tslib": { |
2972 | "version": "2.1.0", | 3010 | "version": "2.2.0", |
2973 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", | 3011 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", |
2974 | "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==", | 3012 | "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==", |
2975 | "dev": true | 3013 | "dev": true |
2976 | }, | 3014 | }, |
2977 | "node_modules/tsutils": { | 3015 | "node_modules/tsutils": { |
2978 | "version": "3.20.0", | 3016 | "version": "3.21.0", |
2979 | "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.20.0.tgz", | 3017 | "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", |
2980 | "integrity": "sha512-RYbuQuvkhuqVeXweWT3tJLKOEJ/UUw9GjNEZGWdrLLlM+611o1gwLHBpxoFJKKl25fLprp2eVthtKs5JOrNeXg==", | 3018 | "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", |
2981 | "dev": true, | 3019 | "dev": true, |
2982 | "dependencies": { | 3020 | "dependencies": { |
2983 | "tslib": "^1.8.1" | 3021 | "tslib": "^1.8.1" |
@@ -3017,12 +3055,15 @@ | |||
3017 | } | 3055 | } |
3018 | }, | 3056 | }, |
3019 | "node_modules/type-fest": { | 3057 | "node_modules/type-fest": { |
3020 | "version": "0.8.1", | 3058 | "version": "0.20.2", |
3021 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", | 3059 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", |
3022 | "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", | 3060 | "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", |
3023 | "dev": true, | 3061 | "dev": true, |
3024 | "engines": { | 3062 | "engines": { |
3025 | "node": ">=8" | 3063 | "node": ">=10" |
3064 | }, | ||
3065 | "funding": { | ||
3066 | "url": "https://github.com/sponsors/sindresorhus" | ||
3026 | } | 3067 | } |
3027 | }, | 3068 | }, |
3028 | "node_modules/typed-rest-client": { | 3069 | "node_modules/typed-rest-client": { |
@@ -3036,9 +3077,9 @@ | |||
3036 | } | 3077 | } |
3037 | }, | 3078 | }, |
3038 | "node_modules/typescript": { | 3079 | "node_modules/typescript": { |
3039 | "version": "4.1.5", | 3080 | "version": "4.2.4", |
3040 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.5.tgz", | 3081 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz", |
3041 | "integrity": "sha512-6OSu9PTIzmn9TCDiovULTnET6BgXtDYL4Gg4szY+cGsc3JP1dQL8qvE8kShTRx1NIw4Q9IBHlwODjkjWEtMUyA==", | 3082 | "integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==", |
3042 | "dev": true, | 3083 | "dev": true, |
3043 | "bin": { | 3084 | "bin": { |
3044 | "tsc": "bin/tsc", | 3085 | "tsc": "bin/tsc", |
@@ -3119,15 +3160,15 @@ | |||
3119 | "dev": true | 3160 | "dev": true |
3120 | }, | 3161 | }, |
3121 | "node_modules/v8-compile-cache": { | 3162 | "node_modules/v8-compile-cache": { |
3122 | "version": "2.2.0", | 3163 | "version": "2.3.0", |
3123 | "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz", | 3164 | "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", |
3124 | "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==", | 3165 | "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", |
3125 | "dev": true | 3166 | "dev": true |
3126 | }, | 3167 | }, |
3127 | "node_modules/vsce": { | 3168 | "node_modules/vsce": { |
3128 | "version": "1.85.0", | 3169 | "version": "1.87.1", |
3129 | "resolved": "https://registry.npmjs.org/vsce/-/vsce-1.85.0.tgz", | 3170 | "resolved": "https://registry.npmjs.org/vsce/-/vsce-1.87.1.tgz", |
3130 | "integrity": "sha512-YVFwjXWvHRwk75mm3iL4Wr3auCdbBPTv2amtLf97ccqH0hkt0ZVBddu7iOs4HSEbSr9xiiaZwQHUsqMm6Ks0ag==", | 3171 | "integrity": "sha512-3tSUWZl9AmhZrqy/UVUpdPODSzBiCGjIr/AMSSgF2PuFLSdrh+6kiOr2Ath7bpQEXOxf55hNgz3qdO5MuEJmww==", |
3131 | "dev": true, | 3172 | "dev": true, |
3132 | "dependencies": { | 3173 | "dependencies": { |
3133 | "azure-devops-node-api": "^7.2.0", | 3174 | "azure-devops-node-api": "^7.2.0", |
@@ -3283,9 +3324,9 @@ | |||
3283 | "integrity": "sha512-VGzh06oynbYa6JbTKUbxOEZN7CYEtWhN7DK5wfzUpeCJl8X8xZX39g2PVfpqXrIEduu7dcJgK007KgnX9tHNKA==" | 3324 | "integrity": "sha512-VGzh06oynbYa6JbTKUbxOEZN7CYEtWhN7DK5wfzUpeCJl8X8xZX39g2PVfpqXrIEduu7dcJgK007KgnX9tHNKA==" |
3284 | }, | 3325 | }, |
3285 | "node_modules/vscode-test": { | 3326 | "node_modules/vscode-test": { |
3286 | "version": "1.5.1", | 3327 | "version": "1.5.2", |
3287 | "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-1.5.1.tgz", | 3328 | "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-1.5.2.tgz", |
3288 | "integrity": "sha512-tDloz6euDne+GeUSglhufL0c2xhuYAPAT74hjsuGxfflALfXF9bYnJ7ehZEeVkr/ZnQEh/T8EBrfPL+m0h5qEQ==", | 3329 | "integrity": "sha512-x9PVfKxF6EInH9iSFGQi0V8H5zIW1fC7RAer6yNQR6sy3WyOwlWkuT3I+wf75xW/cO53hxMi1aj/EvqQfDFOAg==", |
3289 | "dev": true, | 3330 | "dev": true, |
3290 | "dependencies": { | 3331 | "dependencies": { |
3291 | "http-proxy-agent": "^4.0.1", | 3332 | "http-proxy-agent": "^4.0.1", |
@@ -3403,9 +3444,9 @@ | |||
3403 | "dev": true | 3444 | "dev": true |
3404 | }, | 3445 | }, |
3405 | "node_modules/y18n": { | 3446 | "node_modules/y18n": { |
3406 | "version": "5.0.5", | 3447 | "version": "5.0.8", |
3407 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz", | 3448 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", |
3408 | "integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==", | 3449 | "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", |
3409 | "dev": true, | 3450 | "dev": true, |
3410 | "engines": { | 3451 | "engines": { |
3411 | "node": ">=10" | 3452 | "node": ">=10" |
@@ -3507,9 +3548,9 @@ | |||
3507 | "dev": true | 3548 | "dev": true |
3508 | }, | 3549 | }, |
3509 | "@babel/highlight": { | 3550 | "@babel/highlight": { |
3510 | "version": "7.12.13", | 3551 | "version": "7.13.10", |
3511 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.12.13.tgz", | 3552 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.10.tgz", |
3512 | "integrity": "sha512-kocDQvIbgMKlWxXe9fof3TQ+gkIPOUSEYhJjqUjvKMez3krV7vbzYCDq39Oj11UAVK7JqPVGQPlgE85dPNlQww==", | 3553 | "integrity": "sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg==", |
3513 | "dev": true, | 3554 | "dev": true, |
3514 | "requires": { | 3555 | "requires": { |
3515 | "@babel/helper-validator-identifier": "^7.12.11", | 3556 | "@babel/helper-validator-identifier": "^7.12.11", |
@@ -3576,9 +3617,9 @@ | |||
3576 | } | 3617 | } |
3577 | }, | 3618 | }, |
3578 | "@eslint/eslintrc": { | 3619 | "@eslint/eslintrc": { |
3579 | "version": "0.3.0", | 3620 | "version": "0.4.0", |
3580 | "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.3.0.tgz", | 3621 | "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz", |
3581 | "integrity": "sha512-1JTKgrOKAHVivSvOYw+sJOunkBjUOvjqWk1DPja7ZFhIS2mX/4EgTT8M7eTK9jrKhL/FvXXEbQwIs3pg1xp3dg==", | 3622 | "integrity": "sha512-2ZPCc+uNbjV5ERJr+aKSPRwZgKd2z11x0EgLvb1PURmUrn9QNRXFqje0Ldq454PfAVyaJYyrDvvIKSFP4NnBog==", |
3582 | "dev": true, | 3623 | "dev": true, |
3583 | "requires": { | 3624 | "requires": { |
3584 | "ajv": "^6.12.4", | 3625 | "ajv": "^6.12.4", |
@@ -3588,9 +3629,25 @@ | |||
3588 | "ignore": "^4.0.6", | 3629 | "ignore": "^4.0.6", |
3589 | "import-fresh": "^3.2.1", | 3630 | "import-fresh": "^3.2.1", |
3590 | "js-yaml": "^3.13.1", | 3631 | "js-yaml": "^3.13.1", |
3591 | "lodash": "^4.17.20", | ||
3592 | "minimatch": "^3.0.4", | 3632 | "minimatch": "^3.0.4", |
3593 | "strip-json-comments": "^3.1.1" | 3633 | "strip-json-comments": "^3.1.1" |
3634 | }, | ||
3635 | "dependencies": { | ||
3636 | "globals": { | ||
3637 | "version": "12.4.0", | ||
3638 | "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", | ||
3639 | "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", | ||
3640 | "dev": true, | ||
3641 | "requires": { | ||
3642 | "type-fest": "^0.8.1" | ||
3643 | } | ||
3644 | }, | ||
3645 | "type-fest": { | ||
3646 | "version": "0.8.1", | ||
3647 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", | ||
3648 | "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", | ||
3649 | "dev": true | ||
3650 | } | ||
3594 | } | 3651 | } |
3595 | }, | 3652 | }, |
3596 | "@nodelib/fs.scandir": { | 3653 | "@nodelib/fs.scandir": { |
@@ -3635,9 +3692,9 @@ | |||
3635 | } | 3692 | } |
3636 | }, | 3693 | }, |
3637 | "@rollup/plugin-node-resolve": { | 3694 | "@rollup/plugin-node-resolve": { |
3638 | "version": "11.2.0", | 3695 | "version": "11.2.1", |
3639 | "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.0.tgz", | 3696 | "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz", |
3640 | "integrity": "sha512-qHjNIKYt5pCcn+5RUBQxK8krhRvf1HnyVgUCcFFcweDS7fhkOLZeYh0mhHK6Ery8/bb9tvN/ubPzmfF0qjDCTA==", | 3697 | "integrity": "sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==", |
3641 | "dev": true, | 3698 | "dev": true, |
3642 | "requires": { | 3699 | "requires": { |
3643 | "@rollup/pluginutils": "^3.1.0", | 3700 | "@rollup/pluginutils": "^3.1.0", |
@@ -3696,15 +3753,15 @@ | |||
3696 | "dev": true | 3753 | "dev": true |
3697 | }, | 3754 | }, |
3698 | "@types/minimatch": { | 3755 | "@types/minimatch": { |
3699 | "version": "3.0.3", | 3756 | "version": "3.0.4", |
3700 | "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", | 3757 | "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.4.tgz", |
3701 | "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", | 3758 | "integrity": "sha512-1z8k4wzFnNjVK/tlxvrWuK5WMt6mydWWP7+zvH5eFep4oj+UkrfiJTRtjCeBXNpwaA/FYqqtb4/QS4ianFpIRA==", |
3702 | "dev": true | 3759 | "dev": true |
3703 | }, | 3760 | }, |
3704 | "@types/mocha": { | 3761 | "@types/mocha": { |
3705 | "version": "8.2.1", | 3762 | "version": "8.2.2", |
3706 | "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.1.tgz", | 3763 | "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.2.tgz", |
3707 | "integrity": "sha512-NysN+bNqj6E0Hv4CTGWSlPzMW6vTKjDpOteycDkV4IWBsO+PU48JonrPzV9ODjiI2XrjmA05KInLgF5ivZ/YGQ==", | 3764 | "integrity": "sha512-Lwh0lzzqT5Pqh6z61P3c3P5nm6fzQK/MMHl9UKeneAeInVflBSz1O2EkX6gM6xfJd7FBXBY5purtLx7fUiZ7Hw==", |
3708 | "dev": true | 3765 | "dev": true |
3709 | }, | 3766 | }, |
3710 | "@types/node": { | 3767 | "@types/node": { |
@@ -3714,9 +3771,9 @@ | |||
3714 | "dev": true | 3771 | "dev": true |
3715 | }, | 3772 | }, |
3716 | "@types/node-fetch": { | 3773 | "@types/node-fetch": { |
3717 | "version": "2.5.8", | 3774 | "version": "2.5.10", |
3718 | "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.8.tgz", | 3775 | "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.10.tgz", |
3719 | "integrity": "sha512-fbjI6ja0N5ZA8TV53RUqzsKNkl9fv8Oj3T7zxW7FGv1GSH7gwJaNF8dzCjrqKaxKeUpTz4yT1DaJFq/omNpGfw==", | 3776 | "integrity": "sha512-IpkX0AasN44hgEad0gEF/V6EgR5n69VEqPEgnmoM8GsIGro3PowbWs4tR6IhxUTyPLpOn+fiGG6nrQhcmoCuIQ==", |
3720 | "dev": true, | 3777 | "dev": true, |
3721 | "requires": { | 3778 | "requires": { |
3722 | "@types/node": "*", | 3779 | "@types/node": "*", |
@@ -3733,19 +3790,19 @@ | |||
3733 | } | 3790 | } |
3734 | }, | 3791 | }, |
3735 | "@types/vscode": { | 3792 | "@types/vscode": { |
3736 | "version": "1.53.0", | 3793 | "version": "1.55.0", |
3737 | "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.53.0.tgz", | 3794 | "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.55.0.tgz", |
3738 | "integrity": "sha512-XjFWbSPOM0EKIT2XhhYm3D3cx3nn3lshMUcWNy1eqefk+oqRuBq8unVb6BYIZqXy9lQZyeUl7eaBCOZWv+LcXQ==", | 3795 | "integrity": "sha512-49hysH7jneTQoSC8TWbAi7nKK9Lc5osQNjmDHVosrcU8o3jecD9GrK0Qyul8q4aGPSXRfNGqIp9CBdb13akETg==", |
3739 | "dev": true | 3796 | "dev": true |
3740 | }, | 3797 | }, |
3741 | "@typescript-eslint/eslint-plugin": { | 3798 | "@typescript-eslint/eslint-plugin": { |
3742 | "version": "4.15.2", | 3799 | "version": "4.22.0", |
3743 | "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.15.2.tgz", | 3800 | "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.22.0.tgz", |
3744 | "integrity": "sha512-uiQQeu9tWl3f1+oK0yoAv9lt/KXO24iafxgQTkIYO/kitruILGx3uH+QtIAHqxFV+yIsdnJH+alel9KuE3J15Q==", | 3801 | "integrity": "sha512-U8SP9VOs275iDXaL08Ln1Fa/wLXfj5aTr/1c0t0j6CdbOnxh+TruXu1p4I0NAvdPBQgoPjHsgKn28mOi0FzfoA==", |
3745 | "dev": true, | 3802 | "dev": true, |
3746 | "requires": { | 3803 | "requires": { |
3747 | "@typescript-eslint/experimental-utils": "4.15.2", | 3804 | "@typescript-eslint/experimental-utils": "4.22.0", |
3748 | "@typescript-eslint/scope-manager": "4.15.2", | 3805 | "@typescript-eslint/scope-manager": "4.22.0", |
3749 | "debug": "^4.1.1", | 3806 | "debug": "^4.1.1", |
3750 | "functional-red-black-tree": "^1.0.1", | 3807 | "functional-red-black-tree": "^1.0.1", |
3751 | "lodash": "^4.17.15", | 3808 | "lodash": "^4.17.15", |
@@ -3755,55 +3812,55 @@ | |||
3755 | } | 3812 | } |
3756 | }, | 3813 | }, |
3757 | "@typescript-eslint/experimental-utils": { | 3814 | "@typescript-eslint/experimental-utils": { |
3758 | "version": "4.15.2", | 3815 | "version": "4.22.0", |
3759 | "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.15.2.tgz", | 3816 | "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.22.0.tgz", |
3760 | "integrity": "sha512-Fxoshw8+R5X3/Vmqwsjc8nRO/7iTysRtDqx6rlfLZ7HbT8TZhPeQqbPjTyk2RheH3L8afumecTQnUc9EeXxohQ==", | 3817 | "integrity": "sha512-xJXHHl6TuAxB5AWiVrGhvbGL8/hbiCQ8FiWwObO3r0fnvBdrbWEDy1hlvGQOAWc6qsCWuWMKdVWlLAEMpxnddg==", |
3761 | "dev": true, | 3818 | "dev": true, |
3762 | "requires": { | 3819 | "requires": { |
3763 | "@types/json-schema": "^7.0.3", | 3820 | "@types/json-schema": "^7.0.3", |
3764 | "@typescript-eslint/scope-manager": "4.15.2", | 3821 | "@typescript-eslint/scope-manager": "4.22.0", |
3765 | "@typescript-eslint/types": "4.15.2", | 3822 | "@typescript-eslint/types": "4.22.0", |
3766 | "@typescript-eslint/typescript-estree": "4.15.2", | 3823 | "@typescript-eslint/typescript-estree": "4.22.0", |
3767 | "eslint-scope": "^5.0.0", | 3824 | "eslint-scope": "^5.0.0", |
3768 | "eslint-utils": "^2.0.0" | 3825 | "eslint-utils": "^2.0.0" |
3769 | } | 3826 | } |
3770 | }, | 3827 | }, |
3771 | "@typescript-eslint/parser": { | 3828 | "@typescript-eslint/parser": { |
3772 | "version": "4.15.2", | 3829 | "version": "4.22.0", |
3773 | "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.15.2.tgz", | 3830 | "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.22.0.tgz", |
3774 | "integrity": "sha512-SHeF8xbsC6z2FKXsaTb1tBCf0QZsjJ94H6Bo51Y1aVEZ4XAefaw5ZAilMoDPlGghe+qtq7XdTiDlGfVTOmvA+Q==", | 3831 | "integrity": "sha512-z/bGdBJJZJN76nvAY9DkJANYgK3nlRstRRi74WHm3jjgf2I8AglrSY+6l7ogxOmn55YJ6oKZCLLy+6PW70z15Q==", |
3775 | "dev": true, | 3832 | "dev": true, |
3776 | "requires": { | 3833 | "requires": { |
3777 | "@typescript-eslint/scope-manager": "4.15.2", | 3834 | "@typescript-eslint/scope-manager": "4.22.0", |
3778 | "@typescript-eslint/types": "4.15.2", | 3835 | "@typescript-eslint/types": "4.22.0", |
3779 | "@typescript-eslint/typescript-estree": "4.15.2", | 3836 | "@typescript-eslint/typescript-estree": "4.22.0", |
3780 | "debug": "^4.1.1" | 3837 | "debug": "^4.1.1" |
3781 | } | 3838 | } |
3782 | }, | 3839 | }, |
3783 | "@typescript-eslint/scope-manager": { | 3840 | "@typescript-eslint/scope-manager": { |
3784 | "version": "4.15.2", | 3841 | "version": "4.22.0", |
3785 | "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.15.2.tgz", | 3842 | "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.22.0.tgz", |
3786 | "integrity": "sha512-Zm0tf/MSKuX6aeJmuXexgdVyxT9/oJJhaCkijv0DvJVT3ui4zY6XYd6iwIo/8GEZGy43cd7w1rFMiCLHbRzAPQ==", | 3843 | "integrity": "sha512-OcCO7LTdk6ukawUM40wo61WdeoA7NM/zaoq1/2cs13M7GyiF+T4rxuA4xM+6LeHWjWbss7hkGXjFDRcKD4O04Q==", |
3787 | "dev": true, | 3844 | "dev": true, |
3788 | "requires": { | 3845 | "requires": { |
3789 | "@typescript-eslint/types": "4.15.2", | 3846 | "@typescript-eslint/types": "4.22.0", |
3790 | "@typescript-eslint/visitor-keys": "4.15.2" | 3847 | "@typescript-eslint/visitor-keys": "4.22.0" |
3791 | } | 3848 | } |
3792 | }, | 3849 | }, |
3793 | "@typescript-eslint/types": { | 3850 | "@typescript-eslint/types": { |
3794 | "version": "4.15.2", | 3851 | "version": "4.22.0", |
3795 | "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.15.2.tgz", | 3852 | "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.22.0.tgz", |
3796 | "integrity": "sha512-r7lW7HFkAarfUylJ2tKndyO9njwSyoy6cpfDKWPX6/ctZA+QyaYscAHXVAfJqtnY6aaTwDYrOhp+ginlbc7HfQ==", | 3853 | "integrity": "sha512-sW/BiXmmyMqDPO2kpOhSy2Py5w6KvRRsKZnV0c4+0nr4GIcedJwXAq+RHNK4lLVEZAJYFltnnk1tJSlbeS9lYA==", |
3797 | "dev": true | 3854 | "dev": true |
3798 | }, | 3855 | }, |
3799 | "@typescript-eslint/typescript-estree": { | 3856 | "@typescript-eslint/typescript-estree": { |
3800 | "version": "4.15.2", | 3857 | "version": "4.22.0", |
3801 | "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.15.2.tgz", | 3858 | "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.22.0.tgz", |
3802 | "integrity": "sha512-cGR8C2g5SPtHTQvAymEODeqx90pJHadWsgTtx6GbnTWKqsg7yp6Eaya9nFzUd4KrKhxdYTTFBiYeTPQaz/l8bw==", | 3859 | "integrity": "sha512-TkIFeu5JEeSs5ze/4NID+PIcVjgoU3cUQUIZnH3Sb1cEn1lBo7StSV5bwPuJQuoxKXlzAObjYTilOEKRuhR5yg==", |
3803 | "dev": true, | 3860 | "dev": true, |
3804 | "requires": { | 3861 | "requires": { |
3805 | "@typescript-eslint/types": "4.15.2", | 3862 | "@typescript-eslint/types": "4.22.0", |
3806 | "@typescript-eslint/visitor-keys": "4.15.2", | 3863 | "@typescript-eslint/visitor-keys": "4.22.0", |
3807 | "debug": "^4.1.1", | 3864 | "debug": "^4.1.1", |
3808 | "globby": "^11.0.1", | 3865 | "globby": "^11.0.1", |
3809 | "is-glob": "^4.0.1", | 3866 | "is-glob": "^4.0.1", |
@@ -3812,12 +3869,12 @@ | |||
3812 | } | 3869 | } |
3813 | }, | 3870 | }, |
3814 | "@typescript-eslint/visitor-keys": { | 3871 | "@typescript-eslint/visitor-keys": { |
3815 | "version": "4.15.2", | 3872 | "version": "4.22.0", |
3816 | "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.15.2.tgz", | 3873 | "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.22.0.tgz", |
3817 | "integrity": "sha512-TME1VgSb7wTwgENN5KVj4Nqg25hP8DisXxNBojM4Nn31rYaNDIocNm5cmjOFfh42n7NVERxWrDFoETO/76ePyg==", | 3874 | "integrity": "sha512-nnMu4F+s4o0sll6cBSsTeVsT4cwxB7zECK3dFxzEjPBii9xLpq4yqqsy/FU5zMfan6G60DKZSCXAa3sHJZrcYw==", |
3818 | "dev": true, | 3875 | "dev": true, |
3819 | "requires": { | 3876 | "requires": { |
3820 | "@typescript-eslint/types": "4.15.2", | 3877 | "@typescript-eslint/types": "4.22.0", |
3821 | "eslint-visitor-keys": "^2.0.0" | 3878 | "eslint-visitor-keys": "^2.0.0" |
3822 | } | 3879 | } |
3823 | }, | 3880 | }, |
@@ -3882,9 +3939,9 @@ | |||
3882 | } | 3939 | } |
3883 | }, | 3940 | }, |
3884 | "anymatch": { | 3941 | "anymatch": { |
3885 | "version": "3.1.1", | 3942 | "version": "3.1.2", |
3886 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", | 3943 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", |
3887 | "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", | 3944 | "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", |
3888 | "dev": true, | 3945 | "dev": true, |
3889 | "requires": { | 3946 | "requires": { |
3890 | "normalize-path": "^3.0.0", | 3947 | "normalize-path": "^3.0.0", |
@@ -3931,9 +3988,9 @@ | |||
3931 | } | 3988 | } |
3932 | }, | 3989 | }, |
3933 | "balanced-match": { | 3990 | "balanced-match": { |
3934 | "version": "1.0.0", | 3991 | "version": "1.0.2", |
3935 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", | 3992 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", |
3936 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" | 3993 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" |
3937 | }, | 3994 | }, |
3938 | "big-integer": { | 3995 | "big-integer": { |
3939 | "version": "1.6.48", | 3996 | "version": "1.6.48", |
@@ -4039,9 +4096,9 @@ | |||
4039 | } | 4096 | } |
4040 | }, | 4097 | }, |
4041 | "chalk": { | 4098 | "chalk": { |
4042 | "version": "4.1.0", | 4099 | "version": "4.1.1", |
4043 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", | 4100 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", |
4044 | "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", | 4101 | "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", |
4045 | "dev": true, | 4102 | "dev": true, |
4046 | "requires": { | 4103 | "requires": { |
4047 | "ansi-styles": "^4.1.0", | 4104 | "ansi-styles": "^4.1.0", |
@@ -4049,31 +4106,30 @@ | |||
4049 | } | 4106 | } |
4050 | }, | 4107 | }, |
4051 | "cheerio": { | 4108 | "cheerio": { |
4052 | "version": "1.0.0-rc.5", | 4109 | "version": "1.0.0-rc.6", |
4053 | "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.5.tgz", | 4110 | "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.6.tgz", |
4054 | "integrity": "sha512-yoqps/VCaZgN4pfXtenwHROTp8NG6/Hlt4Jpz2FEP0ZJQ+ZUkVDd0hAPDNKhj3nakpfPt/CNs57yEtxD1bXQiw==", | 4111 | "integrity": "sha512-hjx1XE1M/D5pAtMgvWwE21QClmAEeGHOIDfycgmndisdNgI6PE1cGRQkMGBcsbUbmEQyWu5PJLUcAOjtQS8DWw==", |
4055 | "dev": true, | 4112 | "dev": true, |
4056 | "requires": { | 4113 | "requires": { |
4057 | "cheerio-select-tmp": "^0.1.0", | 4114 | "cheerio-select": "^1.3.0", |
4058 | "dom-serializer": "~1.2.0", | 4115 | "dom-serializer": "^1.3.1", |
4059 | "domhandler": "^4.0.0", | 4116 | "domhandler": "^4.1.0", |
4060 | "entities": "~2.1.0", | 4117 | "htmlparser2": "^6.1.0", |
4061 | "htmlparser2": "^6.0.0", | 4118 | "parse5": "^6.0.1", |
4062 | "parse5": "^6.0.0", | 4119 | "parse5-htmlparser2-tree-adapter": "^6.0.1" |
4063 | "parse5-htmlparser2-tree-adapter": "^6.0.0" | ||
4064 | } | 4120 | } |
4065 | }, | 4121 | }, |
4066 | "cheerio-select-tmp": { | 4122 | "cheerio-select": { |
4067 | "version": "0.1.1", | 4123 | "version": "1.4.0", |
4068 | "resolved": "https://registry.npmjs.org/cheerio-select-tmp/-/cheerio-select-tmp-0.1.1.tgz", | 4124 | "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.4.0.tgz", |
4069 | "integrity": "sha512-YYs5JvbpU19VYJyj+F7oYrIE2BOll1/hRU7rEy/5+v9BzkSo3bK81iAeeQEMI92vRIxz677m72UmJUiVwwgjfQ==", | 4125 | "integrity": "sha512-sobR3Yqz27L553Qa7cK6rtJlMDbiKPdNywtR95Sj/YgfpLfy0u6CGJuaBKe5YE/vTc23SCRKxWSdlon/w6I/Ew==", |
4070 | "dev": true, | 4126 | "dev": true, |
4071 | "requires": { | 4127 | "requires": { |
4072 | "css-select": "^3.1.2", | 4128 | "css-select": "^4.1.2", |
4073 | "css-what": "^4.0.0", | 4129 | "css-what": "^5.0.0", |
4074 | "domelementtype": "^2.1.0", | 4130 | "domelementtype": "^2.2.0", |
4075 | "domhandler": "^4.0.0", | 4131 | "domhandler": "^4.2.0", |
4076 | "domutils": "^2.4.4" | 4132 | "domutils": "^2.6.0" |
4077 | } | 4133 | } |
4078 | }, | 4134 | }, |
4079 | "chokidar": { | 4135 | "chokidar": { |
@@ -4168,22 +4224,22 @@ | |||
4168 | } | 4224 | } |
4169 | }, | 4225 | }, |
4170 | "css-select": { | 4226 | "css-select": { |
4171 | "version": "3.1.2", | 4227 | "version": "4.1.2", |
4172 | "resolved": "https://registry.npmjs.org/css-select/-/css-select-3.1.2.tgz", | 4228 | "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.2.tgz", |
4173 | "integrity": "sha512-qmss1EihSuBNWNNhHjxzxSfJoFBM/lERB/Q4EnsJQQC62R2evJDW481091oAdOr9uh46/0n4nrg0It5cAnj1RA==", | 4229 | "integrity": "sha512-nu5ye2Hg/4ISq4XqdLY2bEatAcLIdt3OYGFc9Tm9n7VSlFBcfRv0gBNksHRgSdUDQGtN3XrZ94ztW+NfzkFSUw==", |
4174 | "dev": true, | 4230 | "dev": true, |
4175 | "requires": { | 4231 | "requires": { |
4176 | "boolbase": "^1.0.0", | 4232 | "boolbase": "^1.0.0", |
4177 | "css-what": "^4.0.0", | 4233 | "css-what": "^5.0.0", |
4178 | "domhandler": "^4.0.0", | 4234 | "domhandler": "^4.2.0", |
4179 | "domutils": "^2.4.3", | 4235 | "domutils": "^2.6.0", |
4180 | "nth-check": "^2.0.0" | 4236 | "nth-check": "^2.0.0" |
4181 | } | 4237 | } |
4182 | }, | 4238 | }, |
4183 | "css-what": { | 4239 | "css-what": { |
4184 | "version": "4.0.0", | 4240 | "version": "5.0.0", |
4185 | "resolved": "https://registry.npmjs.org/css-what/-/css-what-4.0.0.tgz", | 4241 | "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.0.0.tgz", |
4186 | "integrity": "sha512-teijzG7kwYfNVsUh2H/YN62xW3KK9YhXEgSlbxMlcyjPNvdKJqFx5lrwlJgoFP1ZHlB89iGDlo/JyshKeRhv5A==", | 4242 | "integrity": "sha512-qxyKHQvgKwzwDWC/rGbT821eJalfupxYW2qbSJSAtdSTimsr/MlaGONoNLllaUPZWf8QnbcKM/kPVYUQuEKAFA==", |
4187 | "dev": true | 4243 | "dev": true |
4188 | }, | 4244 | }, |
4189 | "debug": { | 4245 | "debug": { |
@@ -4249,9 +4305,9 @@ | |||
4249 | } | 4305 | } |
4250 | }, | 4306 | }, |
4251 | "dom-serializer": { | 4307 | "dom-serializer": { |
4252 | "version": "1.2.0", | 4308 | "version": "1.3.1", |
4253 | "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.2.0.tgz", | 4309 | "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.1.tgz", |
4254 | "integrity": "sha512-n6kZFH/KlCrqs/1GHMOd5i2fd/beQHuehKdWvNNffbGHTr/almdhuVvTVFb3V7fglz+nC50fFusu3lY33h12pA==", | 4310 | "integrity": "sha512-Pv2ZluG5ife96udGgEDovOOOA5UELkltfJpnIExPrAk1LTvecolUGn6lIaoLh86d83GiB86CjzciMd9BuRB71Q==", |
4255 | "dev": true, | 4311 | "dev": true, |
4256 | "requires": { | 4312 | "requires": { |
4257 | "domelementtype": "^2.0.1", | 4313 | "domelementtype": "^2.0.1", |
@@ -4260,29 +4316,29 @@ | |||
4260 | } | 4316 | } |
4261 | }, | 4317 | }, |
4262 | "domelementtype": { | 4318 | "domelementtype": { |
4263 | "version": "2.1.0", | 4319 | "version": "2.2.0", |
4264 | "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.1.0.tgz", | 4320 | "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", |
4265 | "integrity": "sha512-LsTgx/L5VpD+Q8lmsXSHW2WpA+eBlZ9HPf3erD1IoPF00/3JKHZ3BknUVA2QGDNu69ZNmyFmCWBSO45XjYKC5w==", | 4321 | "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", |
4266 | "dev": true | 4322 | "dev": true |
4267 | }, | 4323 | }, |
4268 | "domhandler": { | 4324 | "domhandler": { |
4269 | "version": "4.0.0", | 4325 | "version": "4.2.0", |
4270 | "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.0.0.tgz", | 4326 | "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.0.tgz", |
4271 | "integrity": "sha512-KPTbnGQ1JeEMQyO1iYXoagsI6so/C96HZiFyByU3T6iAzpXn8EGEvct6unm1ZGoed8ByO2oirxgwxBmqKF9haA==", | 4327 | "integrity": "sha512-zk7sgt970kzPks2Bf+dwT/PLzghLnsivb9CcxkvR8Mzr66Olr0Ofd8neSbglHJHaHa2MadfoSdNlKYAaafmWfA==", |
4272 | "dev": true, | 4328 | "dev": true, |
4273 | "requires": { | 4329 | "requires": { |
4274 | "domelementtype": "^2.1.0" | 4330 | "domelementtype": "^2.2.0" |
4275 | } | 4331 | } |
4276 | }, | 4332 | }, |
4277 | "domutils": { | 4333 | "domutils": { |
4278 | "version": "2.4.4", | 4334 | "version": "2.6.0", |
4279 | "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.4.4.tgz", | 4335 | "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.6.0.tgz", |
4280 | "integrity": "sha512-jBC0vOsECI4OMdD0GC9mGn7NXPLb+Qt6KW1YDQzeQYRUFKmNG8lh7mO5HiELfr+lLQE7loDVI4QcAxV80HS+RA==", | 4336 | "integrity": "sha512-y0BezHuy4MDYxh6OvolXYsH+1EMGmFbwv5FKW7ovwMG6zTPWqNPq3WF9ayZssFq+UlKdffGLbOEaghNdaOm1WA==", |
4281 | "dev": true, | 4337 | "dev": true, |
4282 | "requires": { | 4338 | "requires": { |
4283 | "dom-serializer": "^1.0.1", | 4339 | "dom-serializer": "^1.0.1", |
4284 | "domelementtype": "^2.0.1", | 4340 | "domelementtype": "^2.2.0", |
4285 | "domhandler": "^4.0.0" | 4341 | "domhandler": "^4.2.0" |
4286 | } | 4342 | } |
4287 | }, | 4343 | }, |
4288 | "duplexer2": { | 4344 | "duplexer2": { |
@@ -4346,9 +4402,9 @@ | |||
4346 | } | 4402 | } |
4347 | }, | 4403 | }, |
4348 | "entities": { | 4404 | "entities": { |
4349 | "version": "2.1.0", | 4405 | "version": "2.2.0", |
4350 | "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", | 4406 | "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", |
4351 | "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", | 4407 | "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", |
4352 | "dev": true | 4408 | "dev": true |
4353 | }, | 4409 | }, |
4354 | "escalade": { | 4410 | "escalade": { |
@@ -4364,13 +4420,13 @@ | |||
4364 | "dev": true | 4420 | "dev": true |
4365 | }, | 4421 | }, |
4366 | "eslint": { | 4422 | "eslint": { |
4367 | "version": "7.20.0", | 4423 | "version": "7.25.0", |
4368 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.20.0.tgz", | 4424 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.25.0.tgz", |
4369 | "integrity": "sha512-qGi0CTcOGP2OtCQBgWZlQjcTuP0XkIpYFj25XtRTQSHC+umNnp7UMshr2G8SLsRFYDdAPFeHOsiteadmMH02Yw==", | 4425 | "integrity": "sha512-TVpSovpvCNpLURIScDRB6g5CYu/ZFq9GfX2hLNIV4dSBKxIWojeDODvYl3t0k0VtMxYeR8OXPCFE5+oHMlGfhw==", |
4370 | "dev": true, | 4426 | "dev": true, |
4371 | "requires": { | 4427 | "requires": { |
4372 | "@babel/code-frame": "7.12.11", | 4428 | "@babel/code-frame": "7.12.11", |
4373 | "@eslint/eslintrc": "^0.3.0", | 4429 | "@eslint/eslintrc": "^0.4.0", |
4374 | "ajv": "^6.10.0", | 4430 | "ajv": "^6.10.0", |
4375 | "chalk": "^4.0.0", | 4431 | "chalk": "^4.0.0", |
4376 | "cross-spawn": "^7.0.2", | 4432 | "cross-spawn": "^7.0.2", |
@@ -4383,10 +4439,10 @@ | |||
4383 | "espree": "^7.3.1", | 4439 | "espree": "^7.3.1", |
4384 | "esquery": "^1.4.0", | 4440 | "esquery": "^1.4.0", |
4385 | "esutils": "^2.0.2", | 4441 | "esutils": "^2.0.2", |
4386 | "file-entry-cache": "^6.0.0", | 4442 | "file-entry-cache": "^6.0.1", |
4387 | "functional-red-black-tree": "^1.0.1", | 4443 | "functional-red-black-tree": "^1.0.1", |
4388 | "glob-parent": "^5.0.0", | 4444 | "glob-parent": "^5.0.0", |
4389 | "globals": "^12.1.0", | 4445 | "globals": "^13.6.0", |
4390 | "ignore": "^4.0.6", | 4446 | "ignore": "^4.0.6", |
4391 | "import-fresh": "^3.0.0", | 4447 | "import-fresh": "^3.0.0", |
4392 | "imurmurhash": "^0.1.4", | 4448 | "imurmurhash": "^0.1.4", |
@@ -4394,7 +4450,7 @@ | |||
4394 | "js-yaml": "^3.13.1", | 4450 | "js-yaml": "^3.13.1", |
4395 | "json-stable-stringify-without-jsonify": "^1.0.1", | 4451 | "json-stable-stringify-without-jsonify": "^1.0.1", |
4396 | "levn": "^0.4.1", | 4452 | "levn": "^0.4.1", |
4397 | "lodash": "^4.17.20", | 4453 | "lodash": "^4.17.21", |
4398 | "minimatch": "^3.0.4", | 4454 | "minimatch": "^3.0.4", |
4399 | "natural-compare": "^1.4.0", | 4455 | "natural-compare": "^1.4.0", |
4400 | "optionator": "^0.9.1", | 4456 | "optionator": "^0.9.1", |
@@ -4551,9 +4607,9 @@ | |||
4551 | "dev": true | 4607 | "dev": true |
4552 | }, | 4608 | }, |
4553 | "fastq": { | 4609 | "fastq": { |
4554 | "version": "1.10.1", | 4610 | "version": "1.11.0", |
4555 | "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.10.1.tgz", | 4611 | "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz", |
4556 | "integrity": "sha512-AWuv6Ery3pM+dY7LYS8YIaCiQvUaos9OB1RyNgaOWnaX+Tik7Onvcsf8x8c+YtDeT0maYLniBip2hox5KtEXXA==", | 4612 | "integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==", |
4557 | "dev": true, | 4613 | "dev": true, |
4558 | "requires": { | 4614 | "requires": { |
4559 | "reusify": "^1.0.4" | 4615 | "reusify": "^1.0.4" |
@@ -4698,27 +4754,27 @@ | |||
4698 | } | 4754 | } |
4699 | }, | 4755 | }, |
4700 | "glob-parent": { | 4756 | "glob-parent": { |
4701 | "version": "5.1.1", | 4757 | "version": "5.1.2", |
4702 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", | 4758 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", |
4703 | "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", | 4759 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", |
4704 | "dev": true, | 4760 | "dev": true, |
4705 | "requires": { | 4761 | "requires": { |
4706 | "is-glob": "^4.0.1" | 4762 | "is-glob": "^4.0.1" |
4707 | } | 4763 | } |
4708 | }, | 4764 | }, |
4709 | "globals": { | 4765 | "globals": { |
4710 | "version": "12.4.0", | 4766 | "version": "13.8.0", |
4711 | "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", | 4767 | "resolved": "https://registry.npmjs.org/globals/-/globals-13.8.0.tgz", |
4712 | "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", | 4768 | "integrity": "sha512-rHtdA6+PDBIjeEvA91rpqzEvk/k3/i7EeNQiryiWuJH0Hw9cpyJMAt2jtbAwUaRdhD+573X4vWw6IcjKPasi9Q==", |
4713 | "dev": true, | 4769 | "dev": true, |
4714 | "requires": { | 4770 | "requires": { |
4715 | "type-fest": "^0.8.1" | 4771 | "type-fest": "^0.20.2" |
4716 | } | 4772 | } |
4717 | }, | 4773 | }, |
4718 | "globby": { | 4774 | "globby": { |
4719 | "version": "11.0.2", | 4775 | "version": "11.0.3", |
4720 | "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.2.tgz", | 4776 | "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz", |
4721 | "integrity": "sha512-2ZThXDvvV8fYFRVIxnrMQBipZQDr7MxKAmQK1vujaj9/7eF0efG7BPUKJ7jP7G5SLF37xKDXvO4S/KKLj/Z0og==", | 4777 | "integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==", |
4722 | "dev": true, | 4778 | "dev": true, |
4723 | "requires": { | 4779 | "requires": { |
4724 | "array-union": "^2.1.0", | 4780 | "array-union": "^2.1.0", |
@@ -4771,14 +4827,14 @@ | |||
4771 | "dev": true | 4827 | "dev": true |
4772 | }, | 4828 | }, |
4773 | "htmlparser2": { | 4829 | "htmlparser2": { |
4774 | "version": "6.0.0", | 4830 | "version": "6.1.0", |
4775 | "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.0.0.tgz", | 4831 | "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", |
4776 | "integrity": "sha512-numTQtDZMoh78zJpaNdJ9MXb2cv5G3jwUoe3dMQODubZvLoGvTE/Ofp6sHvH8OGKcN/8A47pGLi/k58xHP/Tfw==", | 4832 | "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", |
4777 | "dev": true, | 4833 | "dev": true, |
4778 | "requires": { | 4834 | "requires": { |
4779 | "domelementtype": "^2.0.1", | 4835 | "domelementtype": "^2.0.1", |
4780 | "domhandler": "^4.0.0", | 4836 | "domhandler": "^4.0.0", |
4781 | "domutils": "^2.4.4", | 4837 | "domutils": "^2.5.2", |
4782 | "entities": "^2.0.0" | 4838 | "entities": "^2.0.0" |
4783 | } | 4839 | } |
4784 | }, | 4840 | }, |
@@ -4850,9 +4906,9 @@ | |||
4850 | } | 4906 | } |
4851 | }, | 4907 | }, |
4852 | "is-core-module": { | 4908 | "is-core-module": { |
4853 | "version": "2.2.0", | 4909 | "version": "2.3.0", |
4854 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", | 4910 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.3.0.tgz", |
4855 | "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", | 4911 | "integrity": "sha512-xSphU2KG9867tsYdLD4RWQ1VqdFl4HTO9Thf3I/3dLEfr0dbPTWKsuCKrgqMljg4nPE+Gq0VCnzT3gr0CyBmsw==", |
4856 | "dev": true, | 4912 | "dev": true, |
4857 | "requires": { | 4913 | "requires": { |
4858 | "has": "^1.0.3" | 4914 | "has": "^1.0.3" |
@@ -4992,6 +5048,24 @@ | |||
4992 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", | 5048 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", |
4993 | "dev": true | 5049 | "dev": true |
4994 | }, | 5050 | }, |
5051 | "lodash.clonedeep": { | ||
5052 | "version": "4.5.0", | ||
5053 | "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", | ||
5054 | "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", | ||
5055 | "dev": true | ||
5056 | }, | ||
5057 | "lodash.flatten": { | ||
5058 | "version": "4.4.0", | ||
5059 | "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", | ||
5060 | "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", | ||
5061 | "dev": true | ||
5062 | }, | ||
5063 | "lodash.truncate": { | ||
5064 | "version": "4.4.2", | ||
5065 | "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", | ||
5066 | "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", | ||
5067 | "dev": true | ||
5068 | }, | ||
4995 | "log-symbols": { | 5069 | "log-symbols": { |
4996 | "version": "4.0.0", | 5070 | "version": "4.0.0", |
4997 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", | 5071 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", |
@@ -5052,13 +5126,13 @@ | |||
5052 | "dev": true | 5126 | "dev": true |
5053 | }, | 5127 | }, |
5054 | "micromatch": { | 5128 | "micromatch": { |
5055 | "version": "4.0.2", | 5129 | "version": "4.0.4", |
5056 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", | 5130 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", |
5057 | "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", | 5131 | "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", |
5058 | "dev": true, | 5132 | "dev": true, |
5059 | "requires": { | 5133 | "requires": { |
5060 | "braces": "^3.0.1", | 5134 | "braces": "^3.0.1", |
5061 | "picomatch": "^2.0.5" | 5135 | "picomatch": "^2.2.3" |
5062 | } | 5136 | } |
5063 | }, | 5137 | }, |
5064 | "mime": { | 5138 | "mime": { |
@@ -5068,18 +5142,18 @@ | |||
5068 | "dev": true | 5142 | "dev": true |
5069 | }, | 5143 | }, |
5070 | "mime-db": { | 5144 | "mime-db": { |
5071 | "version": "1.46.0", | 5145 | "version": "1.47.0", |
5072 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.46.0.tgz", | 5146 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz", |
5073 | "integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ==", | 5147 | "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==", |
5074 | "dev": true | 5148 | "dev": true |
5075 | }, | 5149 | }, |
5076 | "mime-types": { | 5150 | "mime-types": { |
5077 | "version": "2.1.29", | 5151 | "version": "2.1.30", |
5078 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.29.tgz", | 5152 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz", |
5079 | "integrity": "sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ==", | 5153 | "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", |
5080 | "dev": true, | 5154 | "dev": true, |
5081 | "requires": { | 5155 | "requires": { |
5082 | "mime-db": "1.46.0" | 5156 | "mime-db": "1.47.0" |
5083 | } | 5157 | } |
5084 | }, | 5158 | }, |
5085 | "minimatch": { | 5159 | "minimatch": { |
@@ -5106,9 +5180,9 @@ | |||
5106 | } | 5180 | } |
5107 | }, | 5181 | }, |
5108 | "mocha": { | 5182 | "mocha": { |
5109 | "version": "8.3.0", | 5183 | "version": "8.3.2", |
5110 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.3.0.tgz", | 5184 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.3.2.tgz", |
5111 | "integrity": "sha512-TQqyC89V1J/Vxx0DhJIXlq9gbbL9XFNdeLQ1+JsnZsVaSOV1z3tWfw0qZmQJGQRIfkvZcs7snQnZnOCKoldq1Q==", | 5185 | "integrity": "sha512-UdmISwr/5w+uXLPKspgoV7/RXZwKRTiTjJ2/AC5ZiEztIoOYdfKb19+9jNmEInzx5pBsCyJQzarAxqIGBNYJhg==", |
5112 | "dev": true, | 5186 | "dev": true, |
5113 | "requires": { | 5187 | "requires": { |
5114 | "@ungap/promise-all-settled": "1.1.2", | 5188 | "@ungap/promise-all-settled": "1.1.2", |
@@ -5360,9 +5434,9 @@ | |||
5360 | "dev": true | 5434 | "dev": true |
5361 | }, | 5435 | }, |
5362 | "picomatch": { | 5436 | "picomatch": { |
5363 | "version": "2.2.2", | 5437 | "version": "2.2.3", |
5364 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", | 5438 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz", |
5365 | "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", | 5439 | "integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==", |
5366 | "dev": true | 5440 | "dev": true |
5367 | }, | 5441 | }, |
5368 | "prelude-ls": { | 5442 | "prelude-ls": { |
@@ -5396,9 +5470,9 @@ | |||
5396 | "dev": true | 5470 | "dev": true |
5397 | }, | 5471 | }, |
5398 | "queue-microtask": { | 5472 | "queue-microtask": { |
5399 | "version": "1.2.2", | 5473 | "version": "1.2.3", |
5400 | "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.2.tgz", | 5474 | "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", |
5401 | "integrity": "sha512-dB15eXv3p2jDlbOiNLyMabYg1/sXvppd8DP2J3EOCQ0AkuSXCW2tP7mnVouVLJKgUMY6yP0kcQDVpLCN13h4Xg==", | 5475 | "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", |
5402 | "dev": true | 5476 | "dev": true |
5403 | }, | 5477 | }, |
5404 | "randombytes": { | 5478 | "randombytes": { |
@@ -5501,9 +5575,9 @@ | |||
5501 | } | 5575 | } |
5502 | }, | 5576 | }, |
5503 | "rollup": { | 5577 | "rollup": { |
5504 | "version": "2.39.1", | 5578 | "version": "2.45.2", |
5505 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.39.1.tgz", | 5579 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.45.2.tgz", |
5506 | "integrity": "sha512-9rfr0Z6j+vE+eayfNVFr1KZ+k+jiUl2+0e4quZafy1x6SFCjzFspfRSO2ZZQeWeX9noeDTUDgg6eCENiEPFvQg==", | 5580 | "integrity": "sha512-kRRU7wXzFHUzBIv0GfoFFIN3m9oteY4uAsKllIpQDId5cfnkWF2J130l+27dzDju0E6MScKiV0ZM5Bw8m4blYQ==", |
5507 | "dev": true, | 5581 | "dev": true, |
5508 | "requires": { | 5582 | "requires": { |
5509 | "fsevents": "~2.3.1" | 5583 | "fsevents": "~2.3.1" |
@@ -5525,9 +5599,9 @@ | |||
5525 | "dev": true | 5599 | "dev": true |
5526 | }, | 5600 | }, |
5527 | "semver": { | 5601 | "semver": { |
5528 | "version": "7.3.4", | 5602 | "version": "7.3.5", |
5529 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", | 5603 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", |
5530 | "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", | 5604 | "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", |
5531 | "requires": { | 5605 | "requires": { |
5532 | "lru-cache": "^6.0.0" | 5606 | "lru-cache": "^6.0.0" |
5533 | } | 5607 | } |
@@ -5615,9 +5689,9 @@ | |||
5615 | } | 5689 | } |
5616 | }, | 5690 | }, |
5617 | "string-width": { | 5691 | "string-width": { |
5618 | "version": "4.2.0", | 5692 | "version": "4.2.2", |
5619 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", | 5693 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", |
5620 | "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", | 5694 | "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", |
5621 | "dev": true, | 5695 | "dev": true, |
5622 | "requires": { | 5696 | "requires": { |
5623 | "emoji-regex": "^8.0.0", | 5697 | "emoji-regex": "^8.0.0", |
@@ -5650,21 +5724,24 @@ | |||
5650 | } | 5724 | } |
5651 | }, | 5725 | }, |
5652 | "table": { | 5726 | "table": { |
5653 | "version": "6.0.7", | 5727 | "version": "6.5.1", |
5654 | "resolved": "https://registry.npmjs.org/table/-/table-6.0.7.tgz", | 5728 | "resolved": "https://registry.npmjs.org/table/-/table-6.5.1.tgz", |
5655 | "integrity": "sha512-rxZevLGTUzWna/qBLObOe16kB2RTnnbhciwgPbMMlazz1yZGVEgnZK762xyVdVznhqxrfCeBMmMkgOOaPwjH7g==", | 5729 | "integrity": "sha512-xGDXWTBJxahkzPQCsn1S9ESHEenU7TbMD5Iv4FeopXv/XwJyWatFjfbor+6ipI10/MNPXBYUamYukOrbPZ9L/w==", |
5656 | "dev": true, | 5730 | "dev": true, |
5657 | "requires": { | 5731 | "requires": { |
5658 | "ajv": "^7.0.2", | 5732 | "ajv": "^8.0.1", |
5659 | "lodash": "^4.17.20", | 5733 | "lodash.clonedeep": "^4.5.0", |
5734 | "lodash.flatten": "^4.4.0", | ||
5735 | "lodash.truncate": "^4.4.2", | ||
5660 | "slice-ansi": "^4.0.0", | 5736 | "slice-ansi": "^4.0.0", |
5661 | "string-width": "^4.2.0" | 5737 | "string-width": "^4.2.0", |
5738 | "strip-ansi": "^6.0.0" | ||
5662 | }, | 5739 | }, |
5663 | "dependencies": { | 5740 | "dependencies": { |
5664 | "ajv": { | 5741 | "ajv": { |
5665 | "version": "7.1.1", | 5742 | "version": "8.1.0", |
5666 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-7.1.1.tgz", | 5743 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.1.0.tgz", |
5667 | "integrity": "sha512-ga/aqDYnUy/o7vbsRTFhhTsNeXiYb5JWDIcRIeZfwRNCefwjNTVYCGdGSUrEmiu3yDK3vFvNbgJxvrQW4JXrYQ==", | 5744 | "integrity": "sha512-B/Sk2Ix7A36fs/ZkuGLIR86EdjbgR6fsAcbx9lOP/QBSXujDNbVmIS/U4Itz5k8fPFDeVZl/zQ/gJW4Jrq6XjQ==", |
5668 | "dev": true, | 5745 | "dev": true, |
5669 | "requires": { | 5746 | "requires": { |
5670 | "fast-deep-equal": "^3.1.1", | 5747 | "fast-deep-equal": "^3.1.1", |
@@ -5712,15 +5789,15 @@ | |||
5712 | "dev": true | 5789 | "dev": true |
5713 | }, | 5790 | }, |
5714 | "tslib": { | 5791 | "tslib": { |
5715 | "version": "2.1.0", | 5792 | "version": "2.2.0", |
5716 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", | 5793 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", |
5717 | "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==", | 5794 | "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==", |
5718 | "dev": true | 5795 | "dev": true |
5719 | }, | 5796 | }, |
5720 | "tsutils": { | 5797 | "tsutils": { |
5721 | "version": "3.20.0", | 5798 | "version": "3.21.0", |
5722 | "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.20.0.tgz", | 5799 | "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", |
5723 | "integrity": "sha512-RYbuQuvkhuqVeXweWT3tJLKOEJ/UUw9GjNEZGWdrLLlM+611o1gwLHBpxoFJKKl25fLprp2eVthtKs5JOrNeXg==", | 5800 | "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", |
5724 | "dev": true, | 5801 | "dev": true, |
5725 | "requires": { | 5802 | "requires": { |
5726 | "tslib": "^1.8.1" | 5803 | "tslib": "^1.8.1" |
@@ -5750,9 +5827,9 @@ | |||
5750 | } | 5827 | } |
5751 | }, | 5828 | }, |
5752 | "type-fest": { | 5829 | "type-fest": { |
5753 | "version": "0.8.1", | 5830 | "version": "0.20.2", |
5754 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", | 5831 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", |
5755 | "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", | 5832 | "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", |
5756 | "dev": true | 5833 | "dev": true |
5757 | }, | 5834 | }, |
5758 | "typed-rest-client": { | 5835 | "typed-rest-client": { |
@@ -5766,9 +5843,9 @@ | |||
5766 | } | 5843 | } |
5767 | }, | 5844 | }, |
5768 | "typescript": { | 5845 | "typescript": { |
5769 | "version": "4.1.5", | 5846 | "version": "4.2.4", |
5770 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.5.tgz", | 5847 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz", |
5771 | "integrity": "sha512-6OSu9PTIzmn9TCDiovULTnET6BgXtDYL4Gg4szY+cGsc3JP1dQL8qvE8kShTRx1NIw4Q9IBHlwODjkjWEtMUyA==", | 5848 | "integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==", |
5772 | "dev": true | 5849 | "dev": true |
5773 | }, | 5850 | }, |
5774 | "typescript-formatter": { | 5851 | "typescript-formatter": { |
@@ -5833,15 +5910,15 @@ | |||
5833 | "dev": true | 5910 | "dev": true |
5834 | }, | 5911 | }, |
5835 | "v8-compile-cache": { | 5912 | "v8-compile-cache": { |
5836 | "version": "2.2.0", | 5913 | "version": "2.3.0", |
5837 | "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz", | 5914 | "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", |
5838 | "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==", | 5915 | "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", |
5839 | "dev": true | 5916 | "dev": true |
5840 | }, | 5917 | }, |
5841 | "vsce": { | 5918 | "vsce": { |
5842 | "version": "1.85.0", | 5919 | "version": "1.87.1", |
5843 | "resolved": "https://registry.npmjs.org/vsce/-/vsce-1.85.0.tgz", | 5920 | "resolved": "https://registry.npmjs.org/vsce/-/vsce-1.87.1.tgz", |
5844 | "integrity": "sha512-YVFwjXWvHRwk75mm3iL4Wr3auCdbBPTv2amtLf97ccqH0hkt0ZVBddu7iOs4HSEbSr9xiiaZwQHUsqMm6Ks0ag==", | 5921 | "integrity": "sha512-3tSUWZl9AmhZrqy/UVUpdPODSzBiCGjIr/AMSSgF2PuFLSdrh+6kiOr2Ath7bpQEXOxf55hNgz3qdO5MuEJmww==", |
5845 | "dev": true, | 5922 | "dev": true, |
5846 | "requires": { | 5923 | "requires": { |
5847 | "azure-devops-node-api": "^7.2.0", | 5924 | "azure-devops-node-api": "^7.2.0", |
@@ -5966,9 +6043,9 @@ | |||
5966 | "integrity": "sha512-VGzh06oynbYa6JbTKUbxOEZN7CYEtWhN7DK5wfzUpeCJl8X8xZX39g2PVfpqXrIEduu7dcJgK007KgnX9tHNKA==" | 6043 | "integrity": "sha512-VGzh06oynbYa6JbTKUbxOEZN7CYEtWhN7DK5wfzUpeCJl8X8xZX39g2PVfpqXrIEduu7dcJgK007KgnX9tHNKA==" |
5967 | }, | 6044 | }, |
5968 | "vscode-test": { | 6045 | "vscode-test": { |
5969 | "version": "1.5.1", | 6046 | "version": "1.5.2", |
5970 | "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-1.5.1.tgz", | 6047 | "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-1.5.2.tgz", |
5971 | "integrity": "sha512-tDloz6euDne+GeUSglhufL0c2xhuYAPAT74hjsuGxfflALfXF9bYnJ7ehZEeVkr/ZnQEh/T8EBrfPL+m0h5qEQ==", | 6048 | "integrity": "sha512-x9PVfKxF6EInH9iSFGQi0V8H5zIW1fC7RAer6yNQR6sy3WyOwlWkuT3I+wf75xW/cO53hxMi1aj/EvqQfDFOAg==", |
5972 | "dev": true, | 6049 | "dev": true, |
5973 | "requires": { | 6050 | "requires": { |
5974 | "http-proxy-agent": "^4.0.1", | 6051 | "http-proxy-agent": "^4.0.1", |
@@ -6058,9 +6135,9 @@ | |||
6058 | "dev": true | 6135 | "dev": true |
6059 | }, | 6136 | }, |
6060 | "y18n": { | 6137 | "y18n": { |
6061 | "version": "5.0.5", | 6138 | "version": "5.0.8", |
6062 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz", | 6139 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", |
6063 | "integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==", | 6140 | "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", |
6064 | "dev": true | 6141 | "dev": true |
6065 | }, | 6142 | }, |
6066 | "yallist": { | 6143 | "yallist": { |
diff --git a/editors/code/package.json b/editors/code/package.json index 5437a0648..35b50e669 100644 --- a/editors/code/package.json +++ b/editors/code/package.json | |||
@@ -654,6 +654,11 @@ | |||
654 | "default": true, | 654 | "default": true, |
655 | "type": "boolean" | 655 | "type": "boolean" |
656 | }, | 656 | }, |
657 | "rust-analyzer.inlayHints.smallerHints": { | ||
658 | "markdownDescription": "Whether inlay hints font size should be smaller than editor's font size.", | ||
659 | "default": true, | ||
660 | "type": "boolean" | ||
661 | }, | ||
657 | "rust-analyzer.lens.debug": { | 662 | "rust-analyzer.lens.debug": { |
658 | "markdownDescription": "Whether to show `Debug` lens. Only applies when\n`#rust-analyzer.lens.enable#` is set.", | 663 | "markdownDescription": "Whether to show `Debug` lens. Only applies when\n`#rust-analyzer.lens.enable#` is set.", |
659 | "default": true, | 664 | "default": true, |
diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index 603ff930d..e858f80bc 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts | |||
@@ -115,6 +115,7 @@ export class Config { | |||
115 | typeHints: this.get<boolean>("inlayHints.typeHints"), | 115 | typeHints: this.get<boolean>("inlayHints.typeHints"), |
116 | parameterHints: this.get<boolean>("inlayHints.parameterHints"), | 116 | parameterHints: this.get<boolean>("inlayHints.parameterHints"), |
117 | chainingHints: this.get<boolean>("inlayHints.chainingHints"), | 117 | chainingHints: this.get<boolean>("inlayHints.chainingHints"), |
118 | smallerHints: this.get<boolean>("inlayHints.smallerHints"), | ||
118 | maxLength: this.get<null | number>("inlayHints.maxLength"), | 119 | maxLength: this.get<null | number>("inlayHints.maxLength"), |
119 | }; | 120 | }; |
120 | } | 121 | } |
diff --git a/editors/code/src/inlay_hints.ts b/editors/code/src/inlay_hints.ts index 61db6b8d0..c23d6f738 100644 --- a/editors/code/src/inlay_hints.ts +++ b/editors/code/src/inlay_hints.ts | |||
@@ -5,6 +5,17 @@ import * as ra from './lsp_ext'; | |||
5 | import { Ctx, Disposable } from './ctx'; | 5 | import { Ctx, Disposable } from './ctx'; |
6 | import { sendRequestWithRetry, isRustDocument, RustDocument, RustEditor, sleep } from './util'; | 6 | import { sendRequestWithRetry, isRustDocument, RustDocument, RustEditor, sleep } from './util'; |
7 | 7 | ||
8 | interface InlayHintStyle { | ||
9 | decorationType: vscode.TextEditorDecorationType; | ||
10 | toDecoration(hint: ra.InlayHint, conv: lc.Protocol2CodeConverter): vscode.DecorationOptions; | ||
11 | }; | ||
12 | |||
13 | interface InlayHintsStyles { | ||
14 | typeHints: InlayHintStyle; | ||
15 | paramHints: InlayHintStyle; | ||
16 | chainingHints: InlayHintStyle; | ||
17 | } | ||
18 | |||
8 | 19 | ||
9 | export function activateInlayHints(ctx: Ctx) { | 20 | export function activateInlayHints(ctx: Ctx) { |
10 | const maybeUpdater = { | 21 | const maybeUpdater = { |
@@ -19,6 +30,7 @@ export function activateInlayHints(ctx: Ctx) { | |||
19 | 30 | ||
20 | await sleep(100); | 31 | await sleep(100); |
21 | if (this.updater) { | 32 | if (this.updater) { |
33 | this.updater.updateInlayHintsStyles(); | ||
22 | this.updater.syncCacheAndRenderHints(); | 34 | this.updater.syncCacheAndRenderHints(); |
23 | } else { | 35 | } else { |
24 | this.updater = new HintsUpdater(ctx); | 36 | this.updater = new HintsUpdater(ctx); |
@@ -39,11 +51,7 @@ export function activateInlayHints(ctx: Ctx) { | |||
39 | maybeUpdater.onConfigChange().catch(console.error); | 51 | maybeUpdater.onConfigChange().catch(console.error); |
40 | } | 52 | } |
41 | 53 | ||
42 | const typeHints = createHintStyle("type"); | 54 | function createHintStyle(hintKind: "type" | "parameter" | "chaining", smallerHints: boolean): InlayHintStyle { |
43 | const paramHints = createHintStyle("parameter"); | ||
44 | const chainingHints = createHintStyle("chaining"); | ||
45 | |||
46 | function createHintStyle(hintKind: "type" | "parameter" | "chaining") { | ||
47 | // U+200C is a zero-width non-joiner to prevent the editor from forming a ligature | 55 | // U+200C is a zero-width non-joiner to prevent the editor from forming a ligature |
48 | // between code and type hints | 56 | // between code and type hints |
49 | const [pos, render] = ({ | 57 | const [pos, render] = ({ |
@@ -61,7 +69,7 @@ function createHintStyle(hintKind: "type" | "parameter" | "chaining") { | |||
61 | backgroundColor: bg, | 69 | backgroundColor: bg, |
62 | fontStyle: "normal", | 70 | fontStyle: "normal", |
63 | fontWeight: "normal", | 71 | fontWeight: "normal", |
64 | textDecoration: ";font-size:smaller", | 72 | textDecoration: smallerHints ? ";font-size:smaller" : "none", |
65 | }, | 73 | }, |
66 | }), | 74 | }), |
67 | toDecoration(hint: ra.InlayHint, conv: lc.Protocol2CodeConverter): vscode.DecorationOptions { | 75 | toDecoration(hint: ra.InlayHint, conv: lc.Protocol2CodeConverter): vscode.DecorationOptions { |
@@ -73,9 +81,23 @@ function createHintStyle(hintKind: "type" | "parameter" | "chaining") { | |||
73 | }; | 81 | }; |
74 | } | 82 | } |
75 | 83 | ||
84 | const smallHintsStyles = { | ||
85 | typeHints: createHintStyle("type", true), | ||
86 | paramHints: createHintStyle("parameter", true), | ||
87 | chainingHints: createHintStyle("chaining", true), | ||
88 | }; | ||
89 | |||
90 | const biggerHintsStyles = { | ||
91 | typeHints: createHintStyle("type", false), | ||
92 | paramHints: createHintStyle("parameter", false), | ||
93 | chainingHints: createHintStyle("chaining", false), | ||
94 | }; | ||
95 | |||
76 | class HintsUpdater implements Disposable { | 96 | class HintsUpdater implements Disposable { |
77 | private sourceFiles = new Map<string, RustSourceFile>(); // map Uri -> RustSourceFile | 97 | private sourceFiles = new Map<string, RustSourceFile>(); // map Uri -> RustSourceFile |
78 | private readonly disposables: Disposable[] = []; | 98 | private readonly disposables: Disposable[] = []; |
99 | private pendingDisposeDecorations: undefined | InlayHintsStyles = undefined; | ||
100 | private inlayHintsStyles!: InlayHintsStyles; | ||
79 | 101 | ||
80 | constructor(private readonly ctx: Ctx) { | 102 | constructor(private readonly ctx: Ctx) { |
81 | vscode.window.onDidChangeVisibleTextEditors( | 103 | vscode.window.onDidChangeVisibleTextEditors( |
@@ -100,6 +122,7 @@ class HintsUpdater implements Disposable { | |||
100 | } | 122 | } |
101 | )); | 123 | )); |
102 | 124 | ||
125 | this.updateInlayHintsStyles(); | ||
103 | this.syncCacheAndRenderHints(); | 126 | this.syncCacheAndRenderHints(); |
104 | } | 127 | } |
105 | 128 | ||
@@ -114,6 +137,15 @@ class HintsUpdater implements Disposable { | |||
114 | this.syncCacheAndRenderHints(); | 137 | this.syncCacheAndRenderHints(); |
115 | } | 138 | } |
116 | 139 | ||
140 | updateInlayHintsStyles() { | ||
141 | const inlayHintsStyles = this.ctx.config.inlayHints.smallerHints ? smallHintsStyles : biggerHintsStyles; | ||
142 | |||
143 | if (inlayHintsStyles !== this.inlayHintsStyles) { | ||
144 | this.pendingDisposeDecorations = this.inlayHintsStyles; | ||
145 | this.inlayHintsStyles = inlayHintsStyles; | ||
146 | } | ||
147 | } | ||
148 | |||
117 | syncCacheAndRenderHints() { | 149 | syncCacheAndRenderHints() { |
118 | this.sourceFiles.forEach((file, uri) => this.fetchHints(file).then(hints => { | 150 | this.sourceFiles.forEach((file, uri) => this.fetchHints(file).then(hints => { |
119 | if (!hints) return; | 151 | if (!hints) return; |
@@ -161,12 +193,20 @@ class HintsUpdater implements Disposable { | |||
161 | } | 193 | } |
162 | 194 | ||
163 | private renderDecorations(editor: RustEditor, decorations: InlaysDecorations) { | 195 | private renderDecorations(editor: RustEditor, decorations: InlaysDecorations) { |
196 | const { typeHints, paramHints, chainingHints } = this.inlayHintsStyles; | ||
197 | if (this.pendingDisposeDecorations !== undefined) { | ||
198 | const { typeHints, paramHints, chainingHints } = this.pendingDisposeDecorations; | ||
199 | editor.setDecorations(typeHints.decorationType, []); | ||
200 | editor.setDecorations(paramHints.decorationType, []); | ||
201 | editor.setDecorations(chainingHints.decorationType, []); | ||
202 | } | ||
164 | editor.setDecorations(typeHints.decorationType, decorations.type); | 203 | editor.setDecorations(typeHints.decorationType, decorations.type); |
165 | editor.setDecorations(paramHints.decorationType, decorations.param); | 204 | editor.setDecorations(paramHints.decorationType, decorations.param); |
166 | editor.setDecorations(chainingHints.decorationType, decorations.chaining); | 205 | editor.setDecorations(chainingHints.decorationType, decorations.chaining); |
167 | } | 206 | } |
168 | 207 | ||
169 | private hintsToDecorations(hints: ra.InlayHint[]): InlaysDecorations { | 208 | private hintsToDecorations(hints: ra.InlayHint[]): InlaysDecorations { |
209 | const { typeHints, paramHints, chainingHints } = this.inlayHintsStyles; | ||
170 | const decorations: InlaysDecorations = { type: [], param: [], chaining: [] }; | 210 | const decorations: InlaysDecorations = { type: [], param: [], chaining: [] }; |
171 | const conv = this.ctx.client.protocol2CodeConverter; | 211 | const conv = this.ctx.client.protocol2CodeConverter; |
172 | 212 | ||
diff --git a/xtask/src/dist.rs b/xtask/src/dist.rs index f2503f807..12a7fea1e 100644 --- a/xtask/src/dist.rs +++ b/xtask/src/dist.rs | |||
@@ -7,26 +7,31 @@ use std::{ | |||
7 | 7 | ||
8 | use anyhow::Result; | 8 | use anyhow::Result; |
9 | use flate2::{write::GzEncoder, Compression}; | 9 | use flate2::{write::GzEncoder, Compression}; |
10 | use xshell::{cmd, cp, mkdir_p, pushd, read_file, rm_rf, write_file}; | 10 | use xshell::{cmd, cp, mkdir_p, pushd, pushenv, read_file, rm_rf, write_file}; |
11 | 11 | ||
12 | use crate::{date_iso, project_root}; | 12 | use crate::{date_iso, flags, project_root}; |
13 | 13 | ||
14 | pub(crate) struct DistCmd { | 14 | impl flags::Dist { |
15 | pub(crate) nightly: bool, | ||
16 | pub(crate) client_version: Option<String>, | ||
17 | } | ||
18 | |||
19 | impl DistCmd { | ||
20 | pub(crate) fn run(self) -> Result<()> { | 15 | pub(crate) fn run(self) -> Result<()> { |
16 | let stable = | ||
17 | std::env::var("GITHUB_REF").unwrap_or_default().as_str() == "refs/heads/release"; | ||
18 | |||
21 | let dist = project_root().join("dist"); | 19 | let dist = project_root().join("dist"); |
22 | rm_rf(&dist)?; | 20 | rm_rf(&dist)?; |
23 | mkdir_p(&dist)?; | 21 | mkdir_p(&dist)?; |
24 | 22 | ||
25 | if let Some(version) = self.client_version { | 23 | if let Some(patch_version) = self.client_patch_version { |
26 | let release_tag = if self.nightly { "nightly".to_string() } else { date_iso()? }; | 24 | let version = if stable { |
25 | format!("0.2.{}", patch_version) | ||
26 | } else { | ||
27 | // A hack to make VS Code prefer nightly over stable. | ||
28 | format!("0.3.{}", patch_version) | ||
29 | }; | ||
30 | let release_tag = if stable { date_iso()? } else { "nightly".to_string() }; | ||
27 | dist_client(&version, &release_tag)?; | 31 | dist_client(&version, &release_tag)?; |
28 | } | 32 | } |
29 | dist_server()?; | 33 | let release_channel = if stable { "stable" } else { "nightly" }; |
34 | dist_server(release_channel)?; | ||
30 | Ok(()) | 35 | Ok(()) |
31 | } | 36 | } |
32 | } | 37 | } |
@@ -39,7 +44,9 @@ fn dist_client(version: &str, release_tag: &str) -> Result<()> { | |||
39 | 44 | ||
40 | patch | 45 | patch |
41 | .replace(r#""version": "0.4.0-dev""#, &format!(r#""version": "{}""#, version)) | 46 | .replace(r#""version": "0.4.0-dev""#, &format!(r#""version": "{}""#, version)) |
42 | .replace(r#""releaseTag": null"#, &format!(r#""releaseTag": "{}""#, release_tag)); | 47 | .replace(r#""releaseTag": null"#, &format!(r#""releaseTag": "{}""#, release_tag)) |
48 | .replace(r#""$generated-start": false,"#, "") | ||
49 | .replace(",\n \"$generated-end\": false", ""); | ||
43 | 50 | ||
44 | if nightly { | 51 | if nightly { |
45 | patch.replace( | 52 | patch.replace( |
@@ -57,7 +64,8 @@ fn dist_client(version: &str, release_tag: &str) -> Result<()> { | |||
57 | Ok(()) | 64 | Ok(()) |
58 | } | 65 | } |
59 | 66 | ||
60 | fn dist_server() -> Result<()> { | 67 | fn dist_server(release_channel: &str) -> Result<()> { |
68 | let _e = pushenv("RUST_ANALYZER_CHANNEL", release_channel); | ||
61 | let target = get_target(); | 69 | let target = get_target(); |
62 | if target.contains("-linux-gnu") || target.contains("-linux-musl") { | 70 | if target.contains("-linux-gnu") || target.contains("-linux-musl") { |
63 | env::set_var("CC", "clang"); | 71 | env::set_var("CC", "clang"); |
diff --git a/xtask/src/flags.rs b/xtask/src/flags.rs index 4cd2b1ddb..f80a5dd16 100644 --- a/xtask/src/flags.rs +++ b/xtask/src/flags.rs | |||
@@ -37,8 +37,7 @@ xflags::xflags! { | |||
37 | optional --dry-run | 37 | optional --dry-run |
38 | } | 38 | } |
39 | cmd dist { | 39 | cmd dist { |
40 | optional --nightly | 40 | optional --client-patch-version version: String |
41 | optional --client version: String | ||
42 | } | 41 | } |
43 | cmd metrics { | 42 | cmd metrics { |
44 | optional --dry-run | 43 | optional --dry-run |
@@ -86,9 +85,6 @@ pub struct Install { | |||
86 | } | 85 | } |
87 | 86 | ||
88 | #[derive(Debug)] | 87 | #[derive(Debug)] |
89 | pub struct Lint; | ||
90 | |||
91 | #[derive(Debug)] | ||
92 | pub struct FuzzTests; | 88 | pub struct FuzzTests; |
93 | 89 | ||
94 | #[derive(Debug)] | 90 | #[derive(Debug)] |
@@ -106,8 +102,7 @@ pub struct Promote { | |||
106 | 102 | ||
107 | #[derive(Debug)] | 103 | #[derive(Debug)] |
108 | pub struct Dist { | 104 | pub struct Dist { |
109 | pub nightly: bool, | 105 | pub client_patch_version: Option<String>, |
110 | pub client: Option<String>, | ||
111 | } | 106 | } |
112 | 107 | ||
113 | #[derive(Debug)] | 108 | #[derive(Debug)] |
diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 960927fc0..ce3353410 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs | |||
@@ -28,8 +28,6 @@ use std::{ | |||
28 | use walkdir::{DirEntry, WalkDir}; | 28 | use walkdir::{DirEntry, WalkDir}; |
29 | use xshell::{cmd, cp, pushd, pushenv}; | 29 | use xshell::{cmd, cp, pushd, pushenv}; |
30 | 30 | ||
31 | use crate::dist::DistCmd; | ||
32 | |||
33 | fn main() -> Result<()> { | 31 | fn main() -> Result<()> { |
34 | let _d = pushd(project_root())?; | 32 | let _d = pushd(project_root())?; |
35 | 33 | ||
@@ -44,9 +42,7 @@ fn main() -> Result<()> { | |||
44 | flags::XtaskCmd::PreCache(cmd) => cmd.run(), | 42 | flags::XtaskCmd::PreCache(cmd) => cmd.run(), |
45 | flags::XtaskCmd::Release(cmd) => cmd.run(), | 43 | flags::XtaskCmd::Release(cmd) => cmd.run(), |
46 | flags::XtaskCmd::Promote(cmd) => cmd.run(), | 44 | flags::XtaskCmd::Promote(cmd) => cmd.run(), |
47 | flags::XtaskCmd::Dist(flags) => { | 45 | flags::XtaskCmd::Dist(cmd) => cmd.run(), |
48 | DistCmd { nightly: flags.nightly, client_version: flags.client }.run() | ||
49 | } | ||
50 | flags::XtaskCmd::Metrics(cmd) => cmd.run(), | 46 | flags::XtaskCmd::Metrics(cmd) => cmd.run(), |
51 | flags::XtaskCmd::Bb(cmd) => { | 47 | flags::XtaskCmd::Bb(cmd) => { |
52 | { | 48 | { |
@@ -112,7 +108,7 @@ fn run_fuzzer() -> Result<()> { | |||
112 | } | 108 | } |
113 | 109 | ||
114 | fn date_iso() -> Result<String> { | 110 | fn date_iso() -> Result<String> { |
115 | let res = cmd!("date --iso --utc").read()?; | 111 | let res = cmd!("date -u +%Y-%m-%d").read()?; |
116 | Ok(res) | 112 | Ok(res) |
117 | } | 113 | } |
118 | 114 | ||
diff --git a/xtask/src/release.rs b/xtask/src/release.rs index dde5d14ee..452f351d0 100644 --- a/xtask/src/release.rs +++ b/xtask/src/release.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use std::fmt::Write; | 1 | mod changelog; |
2 | 2 | ||
3 | use xshell::{cmd, cp, pushd, read_dir, write_file}; | 3 | use xshell::{cmd, cp, pushd, read_dir, write_file}; |
4 | 4 | ||
@@ -10,7 +10,16 @@ impl flags::Release { | |||
10 | cmd!("git switch release").run()?; | 10 | cmd!("git switch release").run()?; |
11 | cmd!("git fetch upstream --tags --force").run()?; | 11 | cmd!("git fetch upstream --tags --force").run()?; |
12 | cmd!("git reset --hard tags/nightly").run()?; | 12 | cmd!("git reset --hard tags/nightly").run()?; |
13 | cmd!("git push").run()?; | 13 | // The `release` branch sometimes has a couple of cherry-picked |
14 | // commits for patch releases. If that's the case, just overwrite | ||
15 | // it. As we are setting `release` branch to an up-to-date `nightly` | ||
16 | // tag, this shouldn't be problematic in general. | ||
17 | // | ||
18 | // Note that, as we tag releases, we don't worry about "losing" | ||
19 | // commits -- they'll be kept alive by the tag. More generally, we | ||
20 | // don't care about historic releases all that much, it's fine even | ||
21 | // to delete old tags. | ||
22 | cmd!("git push --force").run()?; | ||
14 | } | 23 | } |
15 | codegen::docs()?; | 24 | codegen::docs()?; |
16 | 25 | ||
@@ -38,42 +47,7 @@ impl flags::Release { | |||
38 | let tags = cmd!("git tag --list").read()?; | 47 | let tags = cmd!("git tag --list").read()?; |
39 | let prev_tag = tags.lines().filter(|line| is_release_tag(line)).last().unwrap(); | 48 | let prev_tag = tags.lines().filter(|line| is_release_tag(line)).last().unwrap(); |
40 | 49 | ||
41 | let git_log = cmd!("git log {prev_tag}..HEAD --merges --reverse").read()?; | 50 | let contents = changelog::get_changelog(changelog_n, &commit, prev_tag, &today)?; |
42 | let mut git_log_summary = String::new(); | ||
43 | for line in git_log.lines() { | ||
44 | let line = line.trim_start(); | ||
45 | if let Some(p) = line.find(':') { | ||
46 | if let Ok(pr) = line[..p].parse::<u32>() { | ||
47 | writeln!(git_log_summary, "* pr:{}[]{}", pr, &line[p + 1..]).unwrap(); | ||
48 | } | ||
49 | } | ||
50 | } | ||
51 | |||
52 | let contents = format!( | ||
53 | "\ | ||
54 | = Changelog #{} | ||
55 | :sectanchors: | ||
56 | :page-layout: post | ||
57 | |||
58 | Commit: commit:{}[] + | ||
59 | Release: release:{}[] | ||
60 | |||
61 | == Sponsors | ||
62 | |||
63 | **Become a sponsor:** On https://opencollective.com/rust-analyzer/[OpenCollective] or | ||
64 | https://github.com/sponsors/rust-analyzer[GitHub Sponsors]. | ||
65 | |||
66 | == New Features | ||
67 | |||
68 | {} | ||
69 | |||
70 | == Fixes | ||
71 | |||
72 | == Internal Improvements | ||
73 | ", | ||
74 | changelog_n, commit, today, git_log_summary | ||
75 | ); | ||
76 | |||
77 | let path = changelog_dir.join(format!("{}-changelog-{}.adoc", today, changelog_n)); | 51 | let path = changelog_dir.join(format!("{}-changelog-{}.adoc", today, changelog_n)); |
78 | write_file(&path, &contents)?; | 52 | write_file(&path, &contents)?; |
79 | 53 | ||
diff --git a/xtask/src/release/changelog.rs b/xtask/src/release/changelog.rs new file mode 100644 index 000000000..ffcae2cf7 --- /dev/null +++ b/xtask/src/release/changelog.rs | |||
@@ -0,0 +1,159 @@ | |||
1 | use std::fmt::Write; | ||
2 | use std::{env, iter}; | ||
3 | |||
4 | use anyhow::{bail, Result}; | ||
5 | use xshell::cmd; | ||
6 | |||
7 | pub(crate) fn get_changelog( | ||
8 | changelog_n: usize, | ||
9 | commit: &str, | ||
10 | prev_tag: &str, | ||
11 | today: &str, | ||
12 | ) -> Result<String> { | ||
13 | let git_log = cmd!("git log {prev_tag}..HEAD --merges --reverse").read()?; | ||
14 | let mut features = String::new(); | ||
15 | let mut fixes = String::new(); | ||
16 | let mut internal = String::new(); | ||
17 | let mut others = String::new(); | ||
18 | for line in git_log.lines() { | ||
19 | let line = line.trim_start(); | ||
20 | if let Some(p) = line.find(':') { | ||
21 | let pr = &line[..p]; | ||
22 | if let Ok(pr_num) = pr.parse::<u32>() { | ||
23 | let accept = "Accept: application/vnd.github.v3+json"; | ||
24 | let token = match env::var("GITHUB_TOKEN") { | ||
25 | Ok(token) => token, | ||
26 | Err(_) => bail!("Please obtain a personal access token from https://github.com/settings/tokens and set the `GITHUB_TOKEN` environment variable."), | ||
27 | }; | ||
28 | let authorization = format!("Authorization: token {}", token); | ||
29 | let pr_url = "https://api.github.com/repos/rust-analyzer/rust-analyzer/issues"; | ||
30 | |||
31 | // we don't use an HTTPS client or JSON parser to keep the build times low | ||
32 | let pr_json = | ||
33 | cmd!("curl -s -H {accept} -H {authorization} {pr_url}/{pr}").read()?; | ||
34 | let pr_title = cmd!("jq .title").stdin(&pr_json).read()?; | ||
35 | let pr_title = unescape(&pr_title[1..pr_title.len() - 1]); | ||
36 | let pr_comment = cmd!("jq .body").stdin(pr_json).read()?; | ||
37 | |||
38 | let comments_json = | ||
39 | cmd!("curl -s -H {accept} -H {authorization} {pr_url}/{pr}/comments").read()?; | ||
40 | let pr_comments = cmd!("jq .[].body").stdin(comments_json).read()?; | ||
41 | |||
42 | let l = iter::once(pr_comment.as_str()) | ||
43 | .chain(pr_comments.lines()) | ||
44 | .rev() | ||
45 | .find_map(|it| { | ||
46 | let it = unescape(&it[1..it.len() - 1]); | ||
47 | it.lines().find_map(parse_changelog_line) | ||
48 | }) | ||
49 | .into_iter() | ||
50 | .next() | ||
51 | .unwrap_or_else(|| parse_title_line(&pr_title)); | ||
52 | let s = match l.kind { | ||
53 | PrKind::Feature => &mut features, | ||
54 | PrKind::Fix => &mut fixes, | ||
55 | PrKind::Internal => &mut internal, | ||
56 | PrKind::Other => &mut others, | ||
57 | PrKind::Skip => continue, | ||
58 | }; | ||
59 | writeln!(s, "* pr:{}[] {}", pr_num, l.message.as_deref().unwrap_or(&pr_title)) | ||
60 | .unwrap(); | ||
61 | } | ||
62 | } | ||
63 | } | ||
64 | |||
65 | let contents = format!( | ||
66 | "\ | ||
67 | = Changelog #{} | ||
68 | :sectanchors: | ||
69 | :page-layout: post | ||
70 | |||
71 | Commit: commit:{}[] + | ||
72 | Release: release:{}[] | ||
73 | |||
74 | == Sponsors | ||
75 | |||
76 | **Become a sponsor:** On https://opencollective.com/rust-analyzer/[OpenCollective] or | ||
77 | https://github.com/sponsors/rust-analyzer[GitHub Sponsors]. | ||
78 | |||
79 | == New Features | ||
80 | |||
81 | {} | ||
82 | |||
83 | == Fixes | ||
84 | |||
85 | {} | ||
86 | |||
87 | == Internal Improvements | ||
88 | |||
89 | {} | ||
90 | |||
91 | == Others | ||
92 | |||
93 | {} | ||
94 | ", | ||
95 | changelog_n, commit, today, features, fixes, internal, others | ||
96 | ); | ||
97 | Ok(contents) | ||
98 | } | ||
99 | |||
100 | #[derive(Clone, Copy)] | ||
101 | enum PrKind { | ||
102 | Feature, | ||
103 | Fix, | ||
104 | Internal, | ||
105 | Other, | ||
106 | Skip, | ||
107 | } | ||
108 | |||
109 | struct PrInfo { | ||
110 | message: Option<String>, | ||
111 | kind: PrKind, | ||
112 | } | ||
113 | |||
114 | fn unescape(s: &str) -> String { | ||
115 | s.replace(r#"\""#, "").replace(r#"\n"#, "\n").replace(r#"\r"#, "") | ||
116 | } | ||
117 | |||
118 | fn parse_changelog_line(s: &str) -> Option<PrInfo> { | ||
119 | let parts = s.splitn(3, ' ').collect::<Vec<_>>(); | ||
120 | if parts.len() < 2 || parts[0] != "changelog" { | ||
121 | return None; | ||
122 | } | ||
123 | let message = parts.get(2).map(|it| it.to_string()); | ||
124 | let kind = match parts[1].trim_end_matches(':') { | ||
125 | "feature" => PrKind::Feature, | ||
126 | "fix" => PrKind::Fix, | ||
127 | "internal" => PrKind::Internal, | ||
128 | "skip" => PrKind::Skip, | ||
129 | _ => { | ||
130 | let kind = PrKind::Other; | ||
131 | let message = format!("{} {}", parts[1], message.unwrap_or_default()); | ||
132 | return Some(PrInfo { kind, message: Some(message) }); | ||
133 | } | ||
134 | }; | ||
135 | let res = PrInfo { kind, message }; | ||
136 | Some(res) | ||
137 | } | ||
138 | |||
139 | fn parse_title_line(s: &str) -> PrInfo { | ||
140 | let lower = s.to_ascii_lowercase(); | ||
141 | const PREFIXES: [(&str, PrKind); 5] = [ | ||
142 | ("feat: ", PrKind::Feature), | ||
143 | ("feature: ", PrKind::Feature), | ||
144 | ("fix: ", PrKind::Fix), | ||
145 | ("internal: ", PrKind::Internal), | ||
146 | ("minor: ", PrKind::Skip), | ||
147 | ]; | ||
148 | |||
149 | for &(prefix, kind) in &PREFIXES { | ||
150 | if lower.starts_with(prefix) { | ||
151 | let message = match &kind { | ||
152 | PrKind::Skip => None, | ||
153 | _ => Some(s[prefix.len()..].to_string()), | ||
154 | }; | ||
155 | return PrInfo { kind, message }; | ||
156 | } | ||
157 | } | ||
158 | PrInfo { kind: PrKind::Other, message: Some(s.to_string()) } | ||
159 | } | ||