]> git.lizzy.rs Git - rust.git/commitdiff
Merge #6514
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>
Thu, 12 Nov 2020 17:48:25 +0000 (17:48 +0000)
committerGitHub <noreply@github.com>
Thu, 12 Nov 2020 17:48:25 +0000 (17:48 +0000)
6514: Fix extract_struct_from_enum_variant not updating record references r=Veykril a=Veykril

Related to #6510

Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
40 files changed:
Cargo.lock
crates/assists/src/handlers/remove_unused_param.rs
crates/assists/src/utils/insert_use.rs
crates/hir_ty/Cargo.toml
crates/hir_ty/src/tests.rs
crates/ide/src/syntax_highlighting.rs
crates/ide/src/syntax_highlighting/tags.rs
crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html [new file with mode: 0644]
crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
crates/ide/src/syntax_highlighting/test_data/highlight_injection.html
crates/ide/src/syntax_highlighting/tests.rs
crates/rust-analyzer/src/caps.rs
crates/rust-analyzer/src/config.rs
crates/rust-analyzer/src/diagnostics/test_data/clippy_pass_by_ref.txt
crates/rust-analyzer/src/diagnostics/test_data/handles_macro_location.txt
crates/rust-analyzer/src/diagnostics/test_data/macro_compiler_error.txt
crates/rust-analyzer/src/diagnostics/test_data/rustc_incompatible_type_for_trait.txt
crates/rust-analyzer/src/diagnostics/test_data/rustc_mismatched_type.txt
crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable.txt
crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_hint.txt
crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_info.txt
crates/rust-analyzer/src/diagnostics/test_data/rustc_wrong_number_of_parameters.txt
crates/rust-analyzer/src/diagnostics/test_data/snap_multi_line_fix.txt
crates/rust-analyzer/src/diagnostics/to_proto.rs
crates/rust-analyzer/src/handlers.rs
crates/rust-analyzer/src/lsp_ext.rs
crates/rust-analyzer/src/main_loop.rs
crates/rust-analyzer/src/to_proto.rs
crates/stdx/src/lib.rs
crates/syntax/Cargo.toml
crates/syntax/src/algo.rs
crates/syntax/src/ast.rs
crates/syntax/src/ast/token_ext.rs
crates/syntax/src/parsing/text_tree_sink.rs
crates/syntax/test_data/parser/ok/0037_mod.rast
docs/dev/lsp-extensions.md
editors/code/rust.tmGrammar.json
editors/code/src/client.ts
editors/code/src/commands.ts
editors/code/src/lsp_ext.ts

index 1a4a63550d117a5609afea12dfedd988367da9f9..4940110684d021f7a8d00b34345aae961ac307d0 100644 (file)
@@ -139,9 +139,9 @@ dependencies = [
 
 [[package]]
 name = "cc"
-version = "1.0.61"
+version = "1.0.62"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed67cbde08356238e75fc4656be4749481eeffb09e19f320a25237d5221c985d"
+checksum = "f1770ced377336a88a67c473594ccc14eca6f4559217c34f64aac8f83d641b40"
 
 [[package]]
 name = "cfg"
@@ -398,11 +398,11 @@ dependencies = [
 
 [[package]]
 name = "filetime"
-version = "0.2.12"
+version = "0.2.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ed85775dcc68644b5c950ac06a2b23768d3bc9390464151aaf27136998dcf9e"
+checksum = "0c122a393ea57648015bf06fbd3d372378992e86b9ff5a7a497b076a28c79efe"
 dependencies = [
- "cfg-if 0.1.10",
+ "cfg-if 1.0.0",
  "libc",
  "redox_syscall",
  "winapi 0.3.9",
@@ -438,6 +438,16 @@ dependencies = [
  "toolchain",
 ]
 
+[[package]]
+name = "form_urlencoded"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ece68d15c92e84fa4f19d3780f1294e5ca82a78a6d515f1efaabcc144688be00"
+dependencies = [
+ "matches",
+ "percent-encoding",
+]
+
 [[package]]
 name = "fsevent"
 version = "2.0.2"
@@ -612,6 +622,7 @@ dependencies = [
  "hir_expand",
  "itertools",
  "log",
+ "once_cell",
  "profile",
  "rustc-hash",
  "scoped-tls",
@@ -714,9 +725,9 @@ dependencies = [
 
 [[package]]
 name = "inotify-sys"
-version = "0.1.3"
+version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0"
+checksum = "c4563555856585ab3180a5bf0b2f9f8d301a728462afffc8195b3f5394229c55"
 dependencies = [
  "libc",
 ]
@@ -1053,9 +1064,9 @@ checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397"
 
 [[package]]
 name = "once_cell"
-version = "1.4.1"
+version = "1.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "260e51e7efe62b592207e9e13a68e43692a7a279171d6ba57abd208bf23645ad"
+checksum = "f53cef67919d7d247eb9a2f128ca9e522789967ef1eb4ccd8c71a95a8aedf596"
 
 [[package]]
 name = "oorandom"
@@ -1383,9 +1394,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_lexer"
-version = "686.0.0"
+version = "688.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a5b04cd2159495584d976d501c5394498470c2e94e4f0cebb8186562d407a678"
+checksum = "ebbdcc99bd015349093fcbae4780fda21416fec5d8843acfb3d1733e130cd4db"
 dependencies = [
  "unicode-xid",
 ]
@@ -1888,10 +1899,11 @@ checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
 
 [[package]]
 name = "url"
-version = "2.1.1"
+version = "2.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb"
+checksum = "5909f2b0817350449ed73e8bcd81c8c3c8d9a7a5d8acba4b27db277f1868976e"
 dependencies = [
+ "form_urlencoded",
  "idna",
  "matches",
  "percent-encoding",
index 5fccca54b802b65518c19ff24f3531dd9f1bb117..1ff5e92b04f4fbfcf83a3e9d55f595ba9d5dad5e 100644 (file)
@@ -73,7 +73,8 @@ fn process_usage(
     let source_file = ctx.sema.parse(usage.file_range.file_id);
     let call_expr: ast::CallExpr =
         find_node_at_range(source_file.syntax(), usage.file_range.range)?;
-    if call_expr.expr()?.syntax().text_range() != usage.file_range.range {
+    let call_expr_range = call_expr.expr()?.syntax().text_range();
+    if !call_expr_range.contains_range(usage.file_range.range) {
         return None;
     }
     let arg = call_expr.arg_list()?.args().nth(arg_to_remove)?;
@@ -117,6 +118,53 @@ fn b() { foo(9, ) }
         );
     }
 
+    #[test]
+    fn remove_unused_qualified_call() {
+        check_assist(
+            remove_unused_param,
+            r#"
+mod bar { pub fn foo(x: i32, <|>y: i32) { x; } }
+fn b() { bar::foo(9, 2) }
+"#,
+            r#"
+mod bar { pub fn foo(x: i32) { x; } }
+fn b() { bar::foo(9) }
+"#,
+        );
+    }
+
+    #[test]
+    fn remove_unused_turbofished_func() {
+        check_assist(
+            remove_unused_param,
+            r#"
+pub fn foo<T>(x: T, <|>y: i32) { x; }
+fn b() { foo::<i32>(9, 2) }
+"#,
+            r#"
+pub fn foo<T>(x: T) { x; }
+fn b() { foo::<i32>(9) }
+"#,
+        );
+    }
+
+    #[test]
+    fn remove_unused_generic_unused_param_func() {
+        check_assist(
+            remove_unused_param,
+            r#"
+pub fn foo<T>(x: i32, <|>y: T) { x; }
+fn b() { foo::<i32>(9, 2) }
+fn b2() { foo(9, 2) }
+"#,
+            r#"
+pub fn foo<T>(x: i32) { x; }
+fn b() { foo::<i32>(9) }
+fn b2() { foo(9) }
+"#,
+        );
+    }
+
     #[test]
     fn keep_used() {
         mark::check!(keep_used);
@@ -128,4 +176,37 @@ fn main() { foo(9, 2) }
 "#,
         );
     }
+
+    #[test]
+    fn remove_across_files() {
+        check_assist(
+            remove_unused_param,
+            r#"
+//- /main.rs
+fn foo(x: i32, <|>y: i32) { x; }
+
+mod foo;
+
+//- /foo.rs
+use super::foo;
+
+fn bar() {
+    let _ = foo(1, 2);
+}
+"#,
+            r#"
+//- /main.rs
+fn foo(x: i32) { x; }
+
+mod foo;
+
+//- /foo.rs
+use super::foo;
+
+fn bar() {
+    let _ = foo(1);
+}
+"#,
+        )
+    }
 }
index 84a0dffdd446964f42a150f787fd69f2d7ed27cc..af3fc96b6c2fce2b4e89bb624b9e85092256b17f 100644 (file)
@@ -9,7 +9,7 @@
         edit::{AstNodeEdit, IndentLevel},
         make, AstNode, PathSegmentKind, VisibilityOwner,
     },
-    InsertPosition, SyntaxElement, SyntaxNode,
+    AstToken, InsertPosition, NodeOrToken, SyntaxElement, SyntaxNode, SyntaxToken,
 };
 use test_utils::mark;
 
@@ -63,27 +63,30 @@ fn first_insert_pos(&self) -> (InsertPosition<SyntaxElement>, AddBlankLine) {
         }
     }
 
-    fn insert_pos_after_inner_attribute(&self) -> (InsertPosition<SyntaxElement>, AddBlankLine) {
-        // check if the scope has inner attributes, we dont want to insert in front of them
-        match self
-            .as_syntax_node()
-            .children()
-            // no flat_map here cause we want to short circuit the iterator
-            .map(ast::Attr::cast)
-            .take_while(|attr| {
-                attr.as_ref().map(|attr| attr.kind() == ast::AttrKind::Inner).unwrap_or(false)
+    fn insert_pos_after_last_inner_element(&self) -> (InsertPosition<SyntaxElement>, AddBlankLine) {
+        self.as_syntax_node()
+            .children_with_tokens()
+            .filter(|child| match child {
+                NodeOrToken::Node(node) => is_inner_attribute(node.clone()),
+                NodeOrToken::Token(token) => is_inner_comment(token.clone()),
             })
             .last()
-            .flatten()
-        {
-            Some(attr) => {
-                (InsertPosition::After(attr.syntax().clone().into()), AddBlankLine::BeforeTwice)
-            }
-            None => self.first_insert_pos(),
-        }
+            .map(|last_inner_element| {
+                (InsertPosition::After(last_inner_element.into()), AddBlankLine::BeforeTwice)
+            })
+            .unwrap_or_else(|| self.first_insert_pos())
     }
 }
 
+fn is_inner_attribute(node: SyntaxNode) -> bool {
+    ast::Attr::cast(node).map(|attr| attr.kind()) == Some(ast::AttrKind::Inner)
+}
+
+fn is_inner_comment(token: SyntaxToken) -> bool {
+    ast::Comment::cast(token).and_then(|comment| comment.kind().doc)
+        == Some(ast::CommentPlacement::Inner)
+}
+
 /// Insert an import path into the given file/node. A `merge` value of none indicates that no import merging is allowed to occur.
 pub(crate) fn insert_use<'a>(
     scope: &ImportScope,
@@ -558,7 +561,7 @@ fn find_insert_position(
                             (InsertPosition::After(node.into()), AddBlankLine::BeforeTwice)
                         }
                         // there are no imports in this file at all
-                        None => scope.insert_pos_after_inner_attribute(),
+                        None => scope.insert_pos_after_last_inner_element(),
                     },
                 }
             }
@@ -830,12 +833,67 @@ fn insert_after_inner_attr2() {
             "foo::bar",
             r"#![allow(unused_imports)]
 
+#![no_std]
 fn main() {}",
             r"#![allow(unused_imports)]
 
-use foo::bar;
+#![no_std]
 
+use foo::bar;
 fn main() {}",
+        );
+    }
+
+    #[test]
+    fn inserts_after_single_line_inner_comments() {
+        check_none(
+            "foo::bar::Baz",
+            "//! Single line inner comments do not allow any code before them.",
+            r#"//! Single line inner comments do not allow any code before them.
+
+use foo::bar::Baz;"#,
+        );
+    }
+
+    #[test]
+    fn inserts_after_multiline_inner_comments() {
+        check_none(
+            "foo::bar::Baz",
+            r#"/*! Multiline inner comments do not allow any code before them. */
+
+/*! Still an inner comment, cannot place any code before. */
+fn main() {}"#,
+            r#"/*! Multiline inner comments do not allow any code before them. */
+
+/*! Still an inner comment, cannot place any code before. */
+
+use foo::bar::Baz;
+fn main() {}"#,
+        )
+    }
+
+    #[test]
+    fn inserts_after_all_inner_items() {
+        check_none(
+            "foo::bar::Baz",
+            r#"#![allow(unused_imports)]
+/*! Multiline line comment 2 */
+
+
+//! Single line comment 1
+#![no_std]
+//! Single line comment 2
+fn main() {}"#,
+            r#"#![allow(unused_imports)]
+/*! Multiline line comment 2 */
+
+
+//! Single line comment 1
+#![no_std]
+//! Single line comment 2
+
+use foo::bar::Baz;
+fn main() {}"#,
         )
     }
 
index fdc65a5c3243b11f02127f3d8ab905196c3e55e4..cf5c38a23578cca3c262d0556cef52a83018cea1 100644 (file)
@@ -35,3 +35,4 @@ expect-test = "1.0"
 tracing = "0.1"
 tracing-subscriber = { version = "0.2", default-features = false, features = ["env-filter", "registry"] }
 tracing-tree = { version = "0.1.4" }
+once_cell = { version = "1.5.0", features = ["unstable"] }
index 104ef334c6897deb729185e81dd3e85f18963d0b..0a400cb705080e688e5805a695c74107e52f43f4 100644 (file)
@@ -22,7 +22,8 @@
     AssocItemId, DefWithBodyId, LocalModuleId, Lookup, ModuleDefId,
 };
 use hir_expand::{db::AstDatabase, InFile};
-use stdx::{format_to, RacyFlag};
+use once_cell::race::OnceBool;
+use stdx::format_to;
 use syntax::{
     algo,
     ast::{self, AstNode},
@@ -40,8 +41,8 @@
 // `env UPDATE_EXPECT=1 cargo test -p hir_ty` to update the snapshots.
 
 fn setup_tracing() -> Option<tracing::subscriber::DefaultGuard> {
-    static ENABLE: RacyFlag = RacyFlag::new();
-    if !ENABLE.get(|| env::var("CHALK_DEBUG").is_ok()) {
+    static ENABLE: OnceBool = OnceBool::new();
+    if !ENABLE.get_or_init(|| env::var("CHALK_DEBUG").is_ok()) {
         return None;
     }
 
index 37ab7a8f67093dfd36000e8983b0a69cee20c79e..1ed77b40b0d14ebf7724514828c5e1d9ee13e7bf 100644 (file)
@@ -6,7 +6,7 @@
 #[cfg(test)]
 mod tests;
 
-use hir::{Local, Name, Semantics, VariantDef};
+use hir::{AsAssocItem, Local, Name, Semantics, VariantDef};
 use ide_db::{
     defs::{Definition, NameClass, NameRefClass},
     RootDatabase,
@@ -746,6 +746,9 @@ fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight {
                 if func.is_unsafe(db) {
                     h |= HighlightModifier::Unsafe;
                 }
+                if func.as_assoc_item(db).is_some() && func.self_param(db).is_none() {
+                    h |= HighlightModifier::Static;
+                }
                 return h;
             }
             hir::ModuleDef::Adt(hir::Adt::Struct(_)) => HighlightTag::Struct,
index e8f78ad525c39e9dae4e8b606b82814a5cb3dfc9..65e0671a5a970a363869bb46bdc2828c4100bb27 100644 (file)
@@ -65,6 +65,8 @@ pub enum HighlightModifier {
     Consuming,
     Unsafe,
     Callable,
+    /// Used for associated functions
+    Static,
 }
 
 impl HighlightTag {
@@ -124,6 +126,7 @@ impl HighlightModifier {
         HighlightModifier::Consuming,
         HighlightModifier::Unsafe,
         HighlightModifier::Callable,
+        HighlightModifier::Static,
     ];
 
     fn as_str(self) -> &'static str {
@@ -137,6 +140,7 @@ fn as_str(self) -> &'static str {
             HighlightModifier::Consuming => "consuming",
             HighlightModifier::Unsafe => "unsafe",
             HighlightModifier::Callable => "callable",
+            HighlightModifier::Static => "static",
         }
     }
 
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
new file mode 100644 (file)
index 0000000..cd80d72
--- /dev/null
@@ -0,0 +1,56 @@
+
+<style>
+body                { margin: 0; }
+pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; }
+
+.lifetime           { color: #DFAF8F; font-style: italic; }
+.comment            { color: #7F9F7F; }
+.documentation      { color: #629755; }
+.injected           { opacity: 0.65 ; }
+.struct, .enum      { color: #7CB8BB; }
+.enum_variant       { color: #BDE0F3; }
+.string_literal     { color: #CC9393; }
+.field              { color: #94BFF3; }
+.function           { color: #93E0E3; }
+.function.unsafe    { color: #BC8383; }
+.operator.unsafe    { color: #BC8383; }
+.parameter          { color: #94BFF3; }
+.text               { color: #DCDCCC; }
+.type               { color: #7CB8BB; }
+.builtin_type       { color: #8CD0D3; }
+.type_param         { color: #DFAF8F; }
+.attribute          { color: #94BFF3; }
+.numeric_literal    { color: #BFEBBF; }
+.bool_literal       { color: #BFE6EB; }
+.macro              { color: #94BFF3; }
+.module             { color: #AFD8AF; }
+.value_param        { color: #DCDCCC; }
+.variable           { color: #DCDCCC; }
+.format_specifier   { color: #CC696B; }
+.mutable            { text-decoration: underline; }
+.escape_sequence    { color: #94BFF3; }
+.keyword            { color: #F0DFAF; font-weight: bold; }
+.keyword.unsafe     { color: #BC8383; font-weight: bold; }
+.control            { font-style: italic; }
+
+.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
+</style>
+<pre><code><span class="keyword">fn</span> <span class="function declaration">not_static</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span>
+
+<span class="keyword">struct</span> <span class="struct declaration">foo</span> <span class="punctuation">{</span><span class="punctuation">}</span>
+
+<span class="keyword">impl</span> <span class="struct">foo</span> <span class="punctuation">{</span>
+    <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration static">is_static</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span>
+    <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration">is_not_static</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span>
+<span class="punctuation">}</span>
+
+<span class="keyword">trait</span> <span class="trait declaration">t</span> <span class="punctuation">{</span>
+    <span class="keyword">fn</span> <span class="function declaration static">t_is_static</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span>
+    <span class="keyword">fn</span> <span class="function declaration">t_is_not_static</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span>
+<span class="punctuation">}</span>
+
+<span class="keyword">impl</span> <span class="trait">t</span> <span class="keyword">for</span> <span class="struct">foo</span> <span class="punctuation">{</span>
+    <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration static">is_static</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span>
+    <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration">is_not_static</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span>
+<span class="punctuation">}</span>
+        </code></pre>
\ No newline at end of file
index f44fe457d40f5c0388677d0d3722369d08ec2d82..6be88f856b818937d51d5d74aed96df3a2041b92 100644 (file)
@@ -53,7 +53,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="comment documentation">/// #</span><span class="generic injected"> </span><span class="attribute injected">#</span><span class="attribute injected">!</span><span class="attribute injected">[</span><span class="function attribute injected">allow</span><span class="punctuation injected">(</span><span class="attribute injected">unused_mut</span><span class="punctuation injected">)</span><span class="attribute injected">]</span>
     <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="generic injected"> </span><span class="keyword injected">mut</span><span class="generic injected"> </span><span class="variable declaration injected mutable">foo</span><span class="punctuation injected">:</span><span class="generic injected"> </span><span class="struct injected">Foo</span><span class="generic injected"> </span><span class="operator injected">=</span><span class="generic injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="function injected">new</span><span class="punctuation injected">(</span><span class="punctuation injected">)</span><span class="punctuation injected">;</span><span class="punctuation injected">
 </span>    <span class="comment documentation">/// ```</span>
-    <span class="keyword">pub</span> <span class="keyword">const</span> <span class="keyword">fn</span> <span class="function declaration">new</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="struct">Foo</span> <span class="punctuation">{</span>
+    <span class="keyword">pub</span> <span class="keyword">const</span> <span class="keyword">fn</span> <span class="function declaration static">new</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="struct">Foo</span> <span class="punctuation">{</span>
         <span class="struct">Foo</span> <span class="punctuation">{</span> <span class="field">bar</span><span class="punctuation">:</span> <span class="bool_literal">true</span> <span class="punctuation">}</span>
     <span class="punctuation">}</span>
 
index 18addd00d283c68b13aa8dbd99b5b964c3e1d0c1..57c178916f6afa7d7fc1de5f0e816dd8ae2c412e 100644 (file)
@@ -40,7 +40,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="keyword">fn</span> <span class="function declaration">main</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span>
     <span class="function">fixture</span><span class="punctuation">(</span><span class="string_literal">r#"</span>
         <span class="keyword">trait</span> <span class="trait declaration">Foo</span> <span class="punctuation">{</span>
-            <span class="keyword">fn</span> <span class="function declaration">foo</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span>
+            <span class="keyword">fn</span> <span class="function declaration static">foo</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span>
                 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"2 + 2 = {}"</span><span class="punctuation">,</span> <span class="numeric_literal">4</span><span class="punctuation">)</span><span class="punctuation">;</span>
             <span class="punctuation">}</span>
         <span class="punctuation">}</span><span class="string_literal">"#</span>
index 2b667b0d4a79b60c999e2c2068a6a72ae840b994..5c22e2fce36071372e00ba8737fd8a25acf6657d 100644 (file)
@@ -513,6 +513,34 @@ pub struct A
     );
 }
 
+#[test]
+fn test_associated_function() {
+    check_highlighting(
+        r#"
+fn not_static() {}
+
+struct foo {}
+
+impl foo {
+    pub fn is_static() {}
+    pub fn is_not_static(&self) {}
+}
+
+trait t {
+    fn t_is_static() {}
+    fn t_is_not_static(&self) {}
+}
+
+impl t for foo {
+    pub fn is_static() {}
+    pub fn is_not_static(&self) {}
+}
+        "#,
+        expect_file!["./test_data/highlight_assoc_functions.html"],
+        false,
+    )
+}
+
 /// Highlights the code given by the `ra_fixture` argument, renders the
 /// result as HTML, and compares it with the HTML file given as `snapshot`.
 /// Note that the `snapshot` file is overwritten by the rendered HTML.
index ff1ae9575ffae6fcf95811420b78b7de23577d84..9a887005342ea5df5b4be54a16545aa359f8108a 100644 (file)
@@ -16,8 +16,6 @@
 use crate::semantic_tokens;
 
 pub fn server_capabilities(client_caps: &ClientCapabilities) -> ServerCapabilities {
-    let code_action_provider = code_action_capabilities(client_caps);
-
     ServerCapabilities {
         text_document_sync: Some(TextDocumentSyncCapability::Options(TextDocumentSyncOptions {
             open_close: Some(true),
@@ -49,7 +47,7 @@ pub fn server_capabilities(client_caps: &ClientCapabilities) -> ServerCapabiliti
         document_highlight_provider: Some(OneOf::Left(true)),
         document_symbol_provider: Some(OneOf::Left(true)),
         workspace_symbol_provider: Some(OneOf::Left(true)),
-        code_action_provider: Some(code_action_provider),
+        code_action_provider: Some(code_action_capabilities(client_caps)),
         code_lens_provider: Some(CodeLensOptions { resolve_provider: Some(true) }),
         document_formatting_provider: Some(OneOf::Left(true)),
         document_range_formatting_provider: None,
@@ -113,7 +111,7 @@ fn code_action_capabilities(client_caps: &ClientCapabilities) -> CodeActionProvi
                     CodeActionKind::REFACTOR_INLINE,
                     CodeActionKind::REFACTOR_REWRITE,
                 ]),
-                resolve_provider: None,
+                resolve_provider: Some(true),
                 work_done_progress_options: Default::default(),
             })
         })
index 2ed6a0d82e2127b4f6b9f60ba1c2487061013624..b4c738272b66da6b8ab90eb8214302c1ab07df7a 100644 (file)
@@ -144,7 +144,7 @@ pub struct ClientCapsConfig {
     pub code_action_literals: bool,
     pub work_done_progress: bool,
     pub code_action_group: bool,
-    pub resolve_code_action: bool,
+    pub code_action_resolve: bool,
     pub hover_actions: bool,
     pub status_notification: bool,
     pub signature_help_label_offsets: bool,
@@ -383,6 +383,17 @@ pub fn update_caps(&mut self, caps: &ClientCapabilities) {
                     }
                 }
             }
+
+            if let Some(code_action) = &doc_caps.code_action {
+                match (code_action.data_support, &code_action.resolve_support) {
+                    (Some(true), Some(resolve_support)) => {
+                        if resolve_support.properties.iter().any(|it| it == "edit") {
+                            self.client_caps.code_action_resolve = true;
+                        }
+                    }
+                    _ => (),
+                }
+            }
         }
 
         if let Some(window_caps) = caps.window.as_ref() {
@@ -400,7 +411,6 @@ pub fn update_caps(&mut self, caps: &ClientCapabilities) {
             self.assist.allow_snippets(snippet_text_edit);
 
             self.client_caps.code_action_group = get_bool("codeActionGroup");
-            self.client_caps.resolve_code_action = get_bool("resolveCodeAction");
             self.client_caps.hover_actions = get_bool("hoverActions");
             self.client_caps.status_notification = get_bool("statusNotification");
         }
index 58d47d32a422d362f745e83430d8724bf8eb3483..5b2e5187ac816f62c4cb7f5ac21ba4292fde4733 100644 (file)
@@ -1,6 +1,13 @@
 [
     MappedRustDiagnostic {
-        url: "file:///test/compiler/mir/tagset.rs",
+        url: Url {
+            scheme: "file",
+            host: None,
+            port: None,
+            path: "/test/compiler/mir/tagset.rs",
+            query: None,
+            fragment: None,
+        },
         diagnostic: Diagnostic {
             range: Range {
                 start: Position {
                 [
                     DiagnosticRelatedInformation {
                         location: Location {
-                            uri: "file:///test/compiler/lib.rs",
+                            uri: Url {
+                                scheme: "file",
+                                host: None,
+                                port: None,
+                                path: "/test/compiler/lib.rs",
+                                query: None,
+                                fragment: None,
+                            },
                             range: Range {
                                 start: Position {
                                     line: 0,
                     },
                     DiagnosticRelatedInformation {
                         location: Location {
-                            uri: "file:///test/compiler/mir/tagset.rs",
+                            uri: Url {
+                                scheme: "file",
+                                host: None,
+                                port: None,
+                                path: "/test/compiler/mir/tagset.rs",
+                                query: None,
+                                fragment: None,
+                            },
                             range: Range {
                                 start: Position {
                                     line: 41,
index 6aa26bf63ab20a250e0ef72862abc1beeb7d8035..116f0ff73426c2ad8c31ad2cb868fc7c7698e9e1 100644 (file)
@@ -1,6 +1,13 @@
 [
     MappedRustDiagnostic {
-        url: "file:///test/src/main.rs",
+        url: Url {
+            scheme: "file",
+            host: None,
+            port: None,
+            path: "/test/src/main.rs",
+            query: None,
+            fragment: None,
+        },
         diagnostic: Diagnostic {
             range: Range {
                 start: Position {
index 7aaffaba251d104c396eae6731a8a506f9bf8c91..bbec6a7964ab3509ab989f34b313fdf4a4268692 100644 (file)
@@ -1,6 +1,13 @@
 [
     MappedRustDiagnostic {
-        url: "file:///test/crates/hir_def/src/data.rs",
+        url: Url {
+            scheme: "file",
+            host: None,
+            port: None,
+            path: "/test/crates/hir_def/src/data.rs",
+            query: None,
+            fragment: None,
+        },
         diagnostic: Diagnostic {
             range: Range {
                 start: Position {
                 [
                     DiagnosticRelatedInformation {
                         location: Location {
-                            uri: "file:///test/crates/hir_def/src/path.rs",
+                            uri: Url {
+                                scheme: "file",
+                                host: None,
+                                port: None,
+                                path: "/test/crates/hir_def/src/path.rs",
+                                query: None,
+                                fragment: None,
+                            },
                             range: Range {
                                 start: Position {
                                     line: 264,
         fixes: [],
     },
     MappedRustDiagnostic {
-        url: "file:///test/crates/hir_def/src/path.rs",
+        url: Url {
+            scheme: "file",
+            host: None,
+            port: None,
+            path: "/test/crates/hir_def/src/path.rs",
+            query: None,
+            fragment: None,
+        },
         diagnostic: Diagnostic {
             range: Range {
                 start: Position {
                 [
                     DiagnosticRelatedInformation {
                         location: Location {
-                            uri: "file:///test/crates/hir_def/src/data.rs",
+                            uri: Url {
+                                scheme: "file",
+                                host: None,
+                                port: None,
+                                path: "/test/crates/hir_def/src/data.rs",
+                                query: None,
+                                fragment: None,
+                            },
                             range: Range {
                                 start: Position {
                                     line: 79,
index 58421342001671138f655cb882f043846853847d..2cbf657e59fed7c2ee0561b12a92ea821c1cc45d 100644 (file)
@@ -1,6 +1,13 @@
 [
     MappedRustDiagnostic {
-        url: "file:///test/compiler/ty/list_iter.rs",
+        url: Url {
+            scheme: "file",
+            host: None,
+            port: None,
+            path: "/test/compiler/ty/list_iter.rs",
+            query: None,
+            fragment: None,
+        },
         diagnostic: Diagnostic {
             range: Range {
                 start: Position {
index 2610e4e209ad3c57ac4dbb83294f8193e1a874e2..1142dc2ac6752df19dc0534eeb8f1fa18e97670e 100644 (file)
@@ -1,6 +1,13 @@
 [
     MappedRustDiagnostic {
-        url: "file:///test/runtime/compiler_support.rs",
+        url: Url {
+            scheme: "file",
+            host: None,
+            port: None,
+            path: "/test/runtime/compiler_support.rs",
+            query: None,
+            fragment: None,
+        },
         diagnostic: Diagnostic {
             range: Range {
                 start: Position {
index 8dc53391e941d0b4f209cc8d32aaa9066a5295f3..c709de95ffb18054b1068dca1563e6041d28a439 100644 (file)
@@ -1,6 +1,13 @@
 [
     MappedRustDiagnostic {
-        url: "file:///test/driver/subcommand/repl.rs",
+        url: Url {
+            scheme: "file",
+            host: None,
+            port: None,
+            path: "/test/driver/subcommand/repl.rs",
+            query: None,
+            fragment: None,
+        },
         diagnostic: Diagnostic {
             range: Range {
                 start: Position {
@@ -36,7 +43,6 @@
         fixes: [
             CodeAction {
                 title: "consider prefixing with an underscore",
-                id: None,
                 group: None,
                 kind: Some(
                     CodeActionKind(
                     SnippetWorkspaceEdit {
                         changes: Some(
                             {
-                                "file:///test/driver/subcommand/repl.rs": [
+                                Url {
+                                    scheme: "file",
+                                    host: None,
+                                    port: None,
+                                    path: "/test/driver/subcommand/repl.rs",
+                                    query: None,
+                                    fragment: None,
+                                }: [
                                     TextEdit {
                                         range: Range {
                                             start: Position {
@@ -70,6 +83,7 @@
                 is_preferred: Some(
                     true,
                 ),
+                data: None,
             },
         ],
     },
index c8703194c838e613a93aeefaefeed8dd84d78e7f..632f438d7ad0b59884886bfd06882547bfc611f7 100644 (file)
@@ -1,6 +1,13 @@
 [
     MappedRustDiagnostic {
-        url: "file:///test/driver/subcommand/repl.rs",
+        url: Url {
+            scheme: "file",
+            host: None,
+            port: None,
+            path: "/test/driver/subcommand/repl.rs",
+            query: None,
+            fragment: None,
+        },
         diagnostic: Diagnostic {
             range: Range {
                 start: Position {
@@ -36,7 +43,6 @@
         fixes: [
             CodeAction {
                 title: "consider prefixing with an underscore",
-                id: None,
                 group: None,
                 kind: Some(
                     CodeActionKind(
                     SnippetWorkspaceEdit {
                         changes: Some(
                             {
-                                "file:///test/driver/subcommand/repl.rs": [
+                                Url {
+                                    scheme: "file",
+                                    host: None,
+                                    port: None,
+                                    path: "/test/driver/subcommand/repl.rs",
+                                    query: None,
+                                    fragment: None,
+                                }: [
                                     TextEdit {
                                         range: Range {
                                             start: Position {
@@ -70,6 +83,7 @@
                 is_preferred: Some(
                     true,
                 ),
+                data: None,
             },
         ],
     },
index dc93227adf445af6ccaf595318d3d83a6b1f1e81..c0b79428d89b7bf342ab8cdf6ca31d4aef6049b0 100644 (file)
@@ -1,6 +1,13 @@
 [
     MappedRustDiagnostic {
-        url: "file:///test/driver/subcommand/repl.rs",
+        url: Url {
+            scheme: "file",
+            host: None,
+            port: None,
+            path: "/test/driver/subcommand/repl.rs",
+            query: None,
+            fragment: None,
+        },
         diagnostic: Diagnostic {
             range: Range {
                 start: Position {
@@ -36,7 +43,6 @@
         fixes: [
             CodeAction {
                 title: "consider prefixing with an underscore",
-                id: None,
                 group: None,
                 kind: Some(
                     CodeActionKind(
                     SnippetWorkspaceEdit {
                         changes: Some(
                             {
-                                "file:///test/driver/subcommand/repl.rs": [
+                                Url {
+                                    scheme: "file",
+                                    host: None,
+                                    port: None,
+                                    path: "/test/driver/subcommand/repl.rs",
+                                    query: None,
+                                    fragment: None,
+                                }: [
                                     TextEdit {
                                         range: Range {
                                             start: Position {
@@ -70,6 +83,7 @@
                 is_preferred: Some(
                     true,
                 ),
+                data: None,
             },
         ],
     },
index ba1b98b335e185c877f84b0c262d715971471c17..782c72dbdc5163936a1f210c6aaed864fd1bd4a4 100644 (file)
@@ -1,6 +1,13 @@
 [
     MappedRustDiagnostic {
-        url: "file:///test/compiler/ty/select.rs",
+        url: Url {
+            scheme: "file",
+            host: None,
+            port: None,
+            path: "/test/compiler/ty/select.rs",
+            query: None,
+            fragment: None,
+        },
         diagnostic: Diagnostic {
             range: Range {
                 start: Position {
                 [
                     DiagnosticRelatedInformation {
                         location: Location {
-                            uri: "file:///test/compiler/ty/select.rs",
+                            uri: Url {
+                                scheme: "file",
+                                host: None,
+                                port: None,
+                                path: "/test/compiler/ty/select.rs",
+                                query: None,
+                                fragment: None,
+                            },
                             range: Range {
                                 start: Position {
                                     line: 218,
index 81f752672f03b59d94647755f699b567e8e6f302..d3f27ab6a5467ad31f71ab0e092c862944134084 100644 (file)
@@ -1,6 +1,13 @@
 [
     MappedRustDiagnostic {
-        url: "file:///test/src/main.rs",
+        url: Url {
+            scheme: "file",
+            host: None,
+            port: None,
+            path: "/test/src/main.rs",
+            query: None,
+            fragment: None,
+        },
         diagnostic: Diagnostic {
             range: Range {
                 start: Position {
                 [
                     DiagnosticRelatedInformation {
                         location: Location {
-                            uri: "file:///test/src/main.rs",
+                            uri: Url {
+                                scheme: "file",
+                                host: None,
+                                port: None,
+                                path: "/test/src/main.rs",
+                                query: None,
+                                fragment: None,
+                            },
                             range: Range {
                                 start: Position {
                                     line: 2,
@@ -51,7 +65,6 @@
         fixes: [
             CodeAction {
                 title: "return the expression directly",
-                id: None,
                 group: None,
                 kind: Some(
                     CodeActionKind(
                     SnippetWorkspaceEdit {
                         changes: Some(
                             {
-                                "file:///test/src/main.rs": [
+                                Url {
+                                    scheme: "file",
+                                    host: None,
+                                    port: None,
+                                    path: "/test/src/main.rs",
+                                    query: None,
+                                    fragment: None,
+                                }: [
                                     TextEdit {
                                         range: Range {
                                             start: Position {
                 is_preferred: Some(
                     true,
                 ),
+                data: None,
             },
         ],
     },
index b949577c13d63d99a69e9d36a34d12d9353f0b05..15145415b35c00d478faa2eb405087dfae597d39 100644 (file)
@@ -110,7 +110,6 @@ fn map_rust_child_diagnostic(
     } else {
         MappedRustChildDiagnostic::SuggestedFix(lsp_ext::CodeAction {
             title: rd.message.clone(),
-            id: None,
             group: None,
             kind: Some(lsp_types::CodeActionKind::QUICKFIX),
             edit: Some(lsp_ext::SnippetWorkspaceEdit {
@@ -119,6 +118,7 @@ fn map_rust_child_diagnostic(
                 document_changes: None,
             }),
             is_preferred: Some(true),
+            data: None,
         })
     }
 }
index 049c583a42cb6ec5a40e2a62572725074d8f96dd..95659b0db9d3f1fadeb6ac652321f6ad02ee1834 100644 (file)
@@ -806,11 +806,11 @@ fn handle_fixes(
         let edit = to_proto::snippet_workspace_edit(&snap, fix.source_change)?;
         let action = lsp_ext::CodeAction {
             title: fix.label.to_string(),
-            id: None,
             group: None,
             kind: Some(CodeActionKind::QUICKFIX),
             edit: Some(edit),
             is_preferred: Some(false),
+            data: None,
         };
         res.push(action);
     }
@@ -852,11 +852,11 @@ pub(crate) fn handle_code_action(
 
     handle_fixes(&snap, &params, &mut res)?;
 
-    if snap.config.client_caps.resolve_code_action {
+    if snap.config.client_caps.code_action_resolve {
         for (index, assist) in
             snap.analysis.unresolved_assists(&snap.config.assist, frange)?.into_iter().enumerate()
         {
-            res.push(to_proto::unresolved_code_action(&snap, assist, index)?);
+            res.push(to_proto::unresolved_code_action(&snap, params.clone(), assist, index)?);
         }
     } else {
         for assist in snap.analysis.resolved_assists(&snap.config.assist, frange)?.into_iter() {
@@ -867,11 +867,16 @@ pub(crate) fn handle_code_action(
     Ok(Some(res))
 }
 
-pub(crate) fn handle_resolve_code_action(
+pub(crate) fn handle_code_action_resolve(
     mut snap: GlobalStateSnapshot,
-    params: lsp_ext::ResolveCodeActionParams,
-) -> Result<Option<lsp_ext::SnippetWorkspaceEdit>> {
-    let _p = profile::span("handle_resolve_code_action");
+    mut code_action: lsp_ext::CodeAction,
+) -> Result<lsp_ext::CodeAction> {
+    let _p = profile::span("handle_code_action_resolve");
+    let params = match code_action.data.take() {
+        Some(it) => it,
+        None => Err("can't resolve code action without data")?,
+    };
+
     let file_id = from_proto::file_id(&snap, &params.code_action_params.text_document.uri)?;
     let line_index = snap.analysis.file_line_index(file_id)?;
     let range = from_proto::text_range(&line_index, params.code_action_params.range);
@@ -888,7 +893,9 @@ pub(crate) fn handle_resolve_code_action(
     let index = index.parse::<usize>().unwrap();
     let assist = &assists[index];
     assert!(assist.assist.id.0 == id);
-    Ok(to_proto::resolved_code_action(&snap, assist.clone())?.edit)
+    let edit = to_proto::resolved_code_action(&snap, assist.clone())?.edit;
+    code_action.edit = edit;
+    Ok(code_action)
 }
 
 pub(crate) fn handle_code_lens(
index f31f8d9001b7b8b4fa0a372d253b2c0ddcf44fdf..a7c3028e499350375051312c144e4cf15636cbe2 100644 (file)
@@ -113,22 +113,6 @@ pub struct JoinLinesParams {
     pub ranges: Vec<Range>,
 }
 
-pub enum ResolveCodeActionRequest {}
-
-impl Request for ResolveCodeActionRequest {
-    type Params = ResolveCodeActionParams;
-    type Result = Option<SnippetWorkspaceEdit>;
-    const METHOD: &'static str = "experimental/resolveCodeAction";
-}
-
-/// Params for the ResolveCodeActionRequest
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct ResolveCodeActionParams {
-    pub code_action_params: lsp_types::CodeActionParams,
-    pub id: String,
-}
-
 pub enum OnEnter {}
 
 impl Request for OnEnter {
@@ -265,13 +249,18 @@ impl Request for CodeActionRequest {
     const METHOD: &'static str = "textDocument/codeAction";
 }
 
+pub enum CodeActionResolveRequest {}
+impl Request for CodeActionResolveRequest {
+    type Params = CodeAction;
+    type Result = CodeAction;
+    const METHOD: &'static str = "codeAction/resolve";
+}
+
 #[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
 #[serde(rename_all = "camelCase")]
 pub struct CodeAction {
     pub title: String,
     #[serde(skip_serializing_if = "Option::is_none")]
-    pub id: Option<String>,
-    #[serde(skip_serializing_if = "Option::is_none")]
     pub group: Option<String>,
     #[serde(skip_serializing_if = "Option::is_none")]
     pub kind: Option<CodeActionKind>,
@@ -282,6 +271,16 @@ pub struct CodeAction {
     pub edit: Option<SnippetWorkspaceEdit>,
     #[serde(skip_serializing_if = "Option::is_none")]
     pub is_preferred: Option<bool>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub data: Option<CodeActionData>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct CodeActionData {
+    pub code_action_params: lsp_types::CodeActionParams,
+    pub id: String,
 }
 
 #[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
index d504572a83eeef7e8f1b80a110c2ca45533ec931..6e6cac42e03e0443eb7e6822215bf218e89757a5 100644 (file)
@@ -435,7 +435,7 @@ fn on_request(&mut self, request_received: Instant, req: Request) -> Result<()>
             .on::<lsp_ext::Runnables>(handlers::handle_runnables)
             .on::<lsp_ext::InlayHints>(handlers::handle_inlay_hints)
             .on::<lsp_ext::CodeActionRequest>(handlers::handle_code_action)
-            .on::<lsp_ext::ResolveCodeActionRequest>(handlers::handle_resolve_code_action)
+            .on::<lsp_ext::CodeActionResolveRequest>(handlers::handle_code_action_resolve)
             .on::<lsp_ext::HoverRequest>(handlers::handle_hover)
             .on::<lsp_ext::ExternalDocs>(handlers::handle_open_docs)
             .on::<lsp_types::request::OnTypeFormatting>(handlers::handle_on_type_formatting)
index 92b7c7b681073f4bd4c20df61022eb7c536c770b..4bdf4bf0fad79f212a9c01f4a52e76b1600b507f 100644 (file)
@@ -426,6 +426,7 @@ fn semantic_token_type_and_modifiers(
             HighlightModifier::Consuming => semantic_tokens::CONSUMING,
             HighlightModifier::Unsafe => semantic_tokens::UNSAFE,
             HighlightModifier::Callable => semantic_tokens::CALLABLE,
+            HighlightModifier::Static => lsp_types::SemanticTokenModifier::STATIC,
         };
         mods |= modifier;
     }
@@ -734,16 +735,20 @@ pub(crate) fn code_action_kind(kind: AssistKind) -> lsp_types::CodeActionKind {
 
 pub(crate) fn unresolved_code_action(
     snap: &GlobalStateSnapshot,
+    code_action_params: lsp_types::CodeActionParams,
     assist: Assist,
     index: usize,
 ) -> Result<lsp_ext::CodeAction> {
     let res = lsp_ext::CodeAction {
         title: assist.label.to_string(),
-        id: Some(format!("{}:{}", assist.id.0, index.to_string())),
         group: assist.group.filter(|_| snap.config.client_caps.code_action_group).map(|gr| gr.0),
         kind: Some(code_action_kind(assist.id.1)),
         edit: None,
         is_preferred: None,
+        data: Some(lsp_ext::CodeActionData {
+            id: format!("{}:{}", assist.id.0, index.to_string()),
+            code_action_params,
+        }),
     };
     Ok(res)
 }
@@ -753,13 +758,19 @@ pub(crate) fn resolved_code_action(
     assist: ResolvedAssist,
 ) -> Result<lsp_ext::CodeAction> {
     let change = assist.source_change;
-    unresolved_code_action(snap, assist.assist, 0).and_then(|it| {
-        Ok(lsp_ext::CodeAction {
-            id: None,
-            edit: Some(snippet_workspace_edit(snap, change)?),
-            ..it
-        })
-    })
+    let res = lsp_ext::CodeAction {
+        edit: Some(snippet_workspace_edit(snap, change)?),
+        title: assist.assist.label.to_string(),
+        group: assist
+            .assist
+            .group
+            .filter(|_| snap.config.client_caps.code_action_group)
+            .map(|gr| gr.0),
+        kind: Some(code_action_kind(assist.assist.id.1)),
+        is_preferred: None,
+        data: None,
+    };
+    Ok(res)
 }
 
 pub(crate) fn runnable(
index 59d89f47d1c2d9946f2bdd90030883be5e7934ab..374ed59105dbe524f574b96365a8277291045bb6 100644 (file)
@@ -1,8 +1,5 @@
 //! Missing batteries for standard libraries.
-use std::{
-    sync::atomic::{AtomicUsize, Ordering},
-    time::Instant,
-};
+use std::time::Instant;
 
 mod macros;
 pub mod panic_context;
@@ -150,31 +147,6 @@ pub fn partition_point<T, P>(slice: &[T], mut pred: P) -> usize
     left
 }
 
-pub struct RacyFlag(AtomicUsize);
-
-impl RacyFlag {
-    pub const fn new() -> RacyFlag {
-        RacyFlag(AtomicUsize::new(!0))
-    }
-
-    pub fn get(&self, init: impl FnMut() -> bool) -> bool {
-        let mut init = Some(init);
-        self.get_impl(&mut || init.take().map_or(false, |mut f| f()))
-    }
-
-    fn get_impl(&self, init: &mut dyn FnMut() -> bool) -> bool {
-        match self.0.load(Ordering::Relaxed) {
-            0 => false,
-            1 => true,
-            _ => {
-                let res = init();
-                self.0.store(if res { 1 } else { 0 }, Ordering::Relaxed);
-                res
-            }
-        }
-    }
-}
-
 #[cfg(test)]
 mod tests {
     use super::*;
index 61d2acb49cb4ee6e80dd22e399ad1bc1e28f69e7..1fe907753d9861499430dc452e0f3df1525f0b48 100644 (file)
@@ -13,7 +13,7 @@ doctest = false
 [dependencies]
 itertools = "0.9.0"
 rowan = "0.10.0"
-rustc_lexer = { version = "686.0.0", package = "rustc-ap-rustc_lexer" }
+rustc_lexer = { version = "688.0.0", package = "rustc-ap-rustc_lexer" }
 rustc-hash = "1.1.0"
 arrayvec = "0.5.1"
 once_cell = "1.3.1"
index 30adb72176f5462a72fac5be4535dadec3bc032a..320c430c94ecb9b6f6e6b4384f3a62e03d74bd3f 100644 (file)
@@ -111,18 +111,28 @@ pub enum InsertPosition<T> {
 
 type FxIndexMap<K, V> = IndexMap<K, V, BuildHasherDefault<rustc_hash::FxHasher>>;
 
+#[derive(Debug, Hash, PartialEq, Eq)]
+enum TreeDiffInsertPos {
+    After(SyntaxElement),
+    AsFirstChild(SyntaxElement),
+}
+
 #[derive(Debug)]
 pub struct TreeDiff {
     replacements: FxHashMap<SyntaxElement, SyntaxElement>,
     deletions: Vec<SyntaxElement>,
     // the vec as well as the indexmap are both here to preserve order
-    insertions: FxIndexMap<SyntaxElement, Vec<SyntaxElement>>,
+    insertions: FxIndexMap<TreeDiffInsertPos, Vec<SyntaxElement>>,
 }
 
 impl TreeDiff {
     pub fn into_text_edit(&self, builder: &mut TextEditBuilder) {
         for (anchor, to) in self.insertions.iter() {
-            to.iter().for_each(|to| builder.insert(anchor.text_range().end(), to.to_string()));
+            let offset = match anchor {
+                TreeDiffInsertPos::After(it) => it.text_range().end(),
+                TreeDiffInsertPos::AsFirstChild(it) => it.text_range().start(),
+            };
+            to.iter().for_each(|to| builder.insert(offset, to.to_string()));
         }
         for (from, to) in self.replacements.iter() {
             builder.replace(from.text_range(), to.to_string())
@@ -188,19 +198,20 @@ fn go(diff: &mut TreeDiff, lhs: SyntaxElement, rhs: SyntaxElement) {
             let lhs_child = lhs_children.next();
             match (lhs_child.clone(), rhs_children.next()) {
                 (None, None) => break,
-                (None, Some(element)) => match last_lhs.clone() {
-                    Some(prev) => {
-                        mark::hit!(diff_insert);
-                        diff.insertions.entry(prev).or_insert_with(Vec::new).push(element);
-                    }
-                    // first iteration, this means we got no anchor element to insert after
-                    // therefor replace the parent node instead
-                    None => {
-                        mark::hit!(diff_replace_parent);
-                        diff.replacements.insert(lhs.clone().into(), rhs.clone().into());
-                        break;
-                    }
-                },
+                (None, Some(element)) => {
+                    let insert_pos = match last_lhs.clone() {
+                        Some(prev) => {
+                            mark::hit!(diff_insert);
+                            TreeDiffInsertPos::After(prev)
+                        }
+                        // first iteration, insert into out parent as the first child
+                        None => {
+                            mark::hit!(diff_insert_as_first_child);
+                            TreeDiffInsertPos::AsFirstChild(lhs.clone().into())
+                        }
+                    };
+                    diff.insertions.entry(insert_pos).or_insert_with(Vec::new).push(element);
+                }
                 (Some(element), None) => {
                     mark::hit!(diff_delete);
                     diff.deletions.push(element);
@@ -224,8 +235,15 @@ fn go(diff: &mut TreeDiff, lhs: SyntaxElement, rhs: SyntaxElement) {
                         }
                     }
                     let drain = look_ahead_scratch.drain(..);
-                    if let Some(prev) = last_lhs.clone().filter(|_| insert) {
-                        diff.insertions.entry(prev).or_insert_with(Vec::new).extend(drain);
+                    if insert {
+                        let insert_pos = if let Some(prev) = last_lhs.clone().filter(|_| insert) {
+                            TreeDiffInsertPos::After(prev)
+                        } else {
+                            mark::hit!(insert_first_child);
+                            TreeDiffInsertPos::AsFirstChild(lhs.clone().into())
+                        };
+
+                        diff.insertions.entry(insert_pos).or_insert_with(Vec::new).extend(drain);
                         rhs_children = rhs_children_clone;
                     } else {
                         go(diff, lhs_ele, rhs_ele)
@@ -632,18 +650,19 @@ fn replace_node_token() {
 
     #[test]
     fn replace_parent() {
-        mark::check!(diff_replace_parent);
+        mark::check!(diff_insert_as_first_child);
         check_diff(
             r#""#,
             r#"use foo::bar;"#,
             expect![[r#"
                 insertions:
 
-
+                Line 0: AsFirstChild(Node(SOURCE_FILE@0..0))
+                -> use foo::bar;
 
                 replacements:
 
-                Line 0: Node(SOURCE_FILE@0..0) -> use foo::bar;
+
 
                 deletions:
 
@@ -666,7 +685,7 @@ fn insert_last() {
             expect![[r#"
                 insertions:
 
-                Line 2: Node(USE@10..18)
+                Line 2: After(Node(USE@10..18))
                 -> "\n"
                 -> use baz;
 
@@ -694,7 +713,7 @@ fn insert_middle() {
             expect![[r#"
                 insertions:
 
-                Line 2: Token(WHITESPACE@9..10 "\n")
+                Line 2: After(Token(WHITESPACE@9..10 "\n"))
                 -> use bar;
                 -> "\n"
 
@@ -722,7 +741,7 @@ fn insert_first() {
             expect![[r#"
                 insertions:
 
-                Line 0: Token(WHITESPACE@0..1 "\n")
+                Line 0: After(Token(WHITESPACE@0..1 "\n"))
                 -> use foo;
                 -> "\n"
 
@@ -737,6 +756,36 @@ fn insert_first() {
         )
     }
 
+    #[test]
+    fn first_child_insertion() {
+        mark::check!(insert_first_child);
+        check_diff(
+            r#"fn main() {
+        stdi
+    }"#,
+            r#"use foo::bar;
+
+    fn main() {
+        stdi
+    }"#,
+            expect![[r#"
+                insertions:
+
+                Line 0: AsFirstChild(Node(SOURCE_FILE@0..30))
+                -> use foo::bar;
+                -> "\n\n    "
+
+                replacements:
+
+
+
+                deletions:
+
+
+            "#]],
+        );
+    }
+
     #[test]
     fn delete_last() {
         mark::check!(diff_delete);
@@ -779,7 +828,7 @@ fn delete_middle() {
             expect![[r#"
                 insertions:
 
-                Line 1: Node(USE@1..35)
+                Line 1: After(Node(USE@1..35))
                 -> "\n\n"
                 -> use crate::AstNode;
 
@@ -845,10 +894,10 @@ fn merge_use() {
             expect![[r#"
                 insertions:
 
-                Line 2: Node(PATH_SEGMENT@5..8)
+                Line 2: After(Node(PATH_SEGMENT@5..8))
                 -> ::
                 -> fmt
-                Line 6: Token(WHITESPACE@86..87 "\n")
+                Line 6: After(Token(WHITESPACE@86..87 "\n"))
                 -> use std::hash::BuildHasherDefault;
                 -> "\n"
                 -> use std::ops::{self, RangeInclusive};
@@ -892,14 +941,14 @@ fn main() {
             expect![[r#"
                 insertions:
 
-                Line 3: Node(BLOCK_EXPR@40..63)
+                Line 3: After(Node(BLOCK_EXPR@40..63))
                 -> " "
                 -> match Err(92) {
                         Ok(it) => it,
                         _ => return,
                     }
                 -> ;
-                Line 3: Node(IF_EXPR@17..63)
+                Line 3: After(Node(IF_EXPR@17..63))
                 -> "\n    "
                 -> foo(x);
 
@@ -934,14 +983,18 @@ fn check_diff(from: &str, to: &str, expected_diff: Expect) {
             _ => format!("{}", syn),
         };
 
-        let insertions = diff.insertions.iter().format_with("\n", |(k, v), f| {
-            f(&format!(
-                "Line {}: {:?}\n-> {}",
-                line_number(k),
-                k,
-                v.iter().format_with("\n-> ", |v, f| f(&fmt_syntax(v)))
-            ))
-        });
+        let insertions =
+            diff.insertions.iter().format_with("\n", |(k, v), f| -> Result<(), std::fmt::Error> {
+                f(&format!(
+                    "Line {}: {:?}\n-> {}",
+                    line_number(match k {
+                        super::TreeDiffInsertPos::After(syn) => syn,
+                        super::TreeDiffInsertPos::AsFirstChild(syn) => syn,
+                    }),
+                    k,
+                    v.iter().format_with("\n-> ", |v, f| f(&fmt_syntax(v)))
+                ))
+            });
 
         let replacements = diff
             .replacements
index 8a0e3d27b21ab6647ed0229cbafccf0c9717c05a..7844f9ed63540a543a7740ce4253e0739128685e 100644 (file)
@@ -115,10 +115,10 @@ mod foo {}
 }
 
 #[test]
-fn test_doc_comment_of_items() {
+fn test_outer_doc_comment_of_items() {
     let file = SourceFile::parse(
         r#"
-        //! doc
+        /// doc
         // non-doc
         mod foo {}
         "#,
@@ -129,6 +129,21 @@ mod foo {}
     assert_eq!("doc", module.doc_comment_text().unwrap());
 }
 
+#[test]
+fn test_inner_doc_comment_of_items() {
+    let file = SourceFile::parse(
+        r#"
+        //! doc
+        // non-doc
+        mod foo {}
+        "#,
+    )
+    .ok()
+    .unwrap();
+    let module = file.syntax().descendants().find_map(Module::cast).unwrap();
+    assert!(module.doc_comment_text().is_none());
+}
+
 #[test]
 fn test_doc_comment_of_statics() {
     let file = SourceFile::parse(
index e4e512f2e057420579e87048ad0938afc491a8b2..2661c753e22c2ef5255029ae0310686a76c3f6c6 100644 (file)
 
 impl ast::Comment {
     pub fn kind(&self) -> CommentKind {
-        kind_by_prefix(self.text())
+        CommentKind::from_text(self.text())
     }
 
     pub fn prefix(&self) -> &'static str {
-        for (prefix, k) in COMMENT_PREFIX_TO_KIND.iter() {
-            if *k == self.kind() && self.text().starts_with(prefix) {
-                return prefix;
-            }
-        }
-        unreachable!()
+        let &(prefix, _kind) = CommentKind::BY_PREFIX
+            .iter()
+            .find(|&(prefix, kind)| self.kind() == *kind && self.text().starts_with(prefix))
+            .unwrap();
+        prefix
     }
 }
 
@@ -55,29 +54,25 @@ pub enum CommentPlacement {
     Outer,
 }
 
-const COMMENT_PREFIX_TO_KIND: &[(&str, CommentKind)] = {
-    use {CommentPlacement::*, CommentShape::*};
-    &[
-        ("////", CommentKind { shape: Line, doc: None }),
-        ("///", CommentKind { shape: Line, doc: Some(Outer) }),
-        ("//!", CommentKind { shape: Line, doc: Some(Inner) }),
-        ("/**", CommentKind { shape: Block, doc: Some(Outer) }),
-        ("/*!", CommentKind { shape: Block, doc: Some(Inner) }),
-        ("//", CommentKind { shape: Line, doc: None }),
-        ("/*", CommentKind { shape: Block, doc: None }),
-    ]
-};
+impl CommentKind {
+    const BY_PREFIX: [(&'static str, CommentKind); 8] = [
+        ("/**/", CommentKind { shape: CommentShape::Block, doc: None }),
+        ("////", CommentKind { shape: CommentShape::Line, doc: None }),
+        ("///", CommentKind { shape: CommentShape::Line, doc: Some(CommentPlacement::Outer) }),
+        ("//!", CommentKind { shape: CommentShape::Line, doc: Some(CommentPlacement::Inner) }),
+        ("/**", CommentKind { shape: CommentShape::Block, doc: Some(CommentPlacement::Outer) }),
+        ("/*!", CommentKind { shape: CommentShape::Block, doc: Some(CommentPlacement::Inner) }),
+        ("//", CommentKind { shape: CommentShape::Line, doc: None }),
+        ("/*", CommentKind { shape: CommentShape::Block, doc: None }),
+    ];
 
-fn kind_by_prefix(text: &str) -> CommentKind {
-    if text == "/**/" {
-        return CommentKind { shape: CommentShape::Block, doc: None };
-    }
-    for (prefix, kind) in COMMENT_PREFIX_TO_KIND.iter() {
-        if text.starts_with(prefix) {
-            return *kind;
-        }
+    pub(crate) fn from_text(text: &str) -> CommentKind {
+        let &(_prefix, kind) = CommentKind::BY_PREFIX
+            .iter()
+            .find(|&(prefix, _kind)| text.starts_with(prefix))
+            .unwrap();
+        kind
     }
-    panic!("bad comment text: {:?}", text)
 }
 
 impl ast::Whitespace {
index c1b5f246d11a05c0215c4e1930e4309a08478de3..997bc5d288bcabd07e81ebd0e325245f2a9607ef 100644 (file)
@@ -5,6 +5,7 @@
 use parser::{ParseError, TreeSink};
 
 use crate::{
+    ast,
     parsing::Token,
     syntax_node::GreenNode,
     SmolStr, SyntaxError,
@@ -153,24 +154,22 @@ fn n_attached_trivias<'a>(
 
             while let Some((i, (kind, text))) = trivias.next() {
                 match kind {
-                    WHITESPACE => {
-                        if text.contains("\n\n") {
-                            // we check whether the next token is a doc-comment
-                            // and skip the whitespace in this case
-                            if let Some((peek_kind, peek_text)) =
-                                trivias.peek().map(|(_, pair)| pair)
-                            {
-                                if *peek_kind == COMMENT
-                                    && peek_text.starts_with("///")
-                                    && !peek_text.starts_with("////")
-                                {
-                                    continue;
-                                }
+                    WHITESPACE if text.contains("\n\n") => {
+                        // we check whether the next token is a doc-comment
+                        // and skip the whitespace in this case
+                        if let Some((COMMENT, peek_text)) = trivias.peek().map(|(_, pair)| pair) {
+                            let comment_kind = ast::CommentKind::from_text(peek_text);
+                            if comment_kind.doc == Some(ast::CommentPlacement::Outer) {
+                                continue;
                             }
-                            break;
                         }
+                        break;
                     }
                     COMMENT => {
+                        let comment_kind = ast::CommentKind::from_text(text);
+                        if comment_kind.doc == Some(ast::CommentPlacement::Inner) {
+                            break;
+                        }
                         res = i + 1;
                     }
                     _ => (),
index 1d5d94bdea8685ffbdd7c4638a8cd6c2e682034e..35577272e5621ceeb0a8200a0f4cc46df4ed3147 100644 (file)
@@ -1,9 +1,9 @@
 SOURCE_FILE@0..93
   COMMENT@0..60 "// https://github.com ..."
   WHITESPACE@60..62 "\n\n"
-  MODULE@62..93
-    COMMENT@62..70 "//! docs"
-    WHITESPACE@70..71 "\n"
+  COMMENT@62..70 "//! docs"
+  WHITESPACE@70..71 "\n"
+  MODULE@71..93
     COMMENT@71..82 "// non-docs"
     WHITESPACE@82..83 "\n"
     MOD_KW@83..86 "mod"
index 780f5cb91fb494cc26b73920c2a6e5819c3771e5..77d4e0ec996ac126d12f93bb434b3fa38064ec72 100644 (file)
@@ -1,5 +1,5 @@
 <!---
-lsp_ext.rs hash: 286f8bbac885531a
+lsp_ext.rs hash: 4f86fb54e4b2870e
 
 If you need to change the above hash to make the test pass, please check if you
 need to adjust this doc as well and ping this issue:
@@ -109,30 +109,6 @@ Invoking code action at this position will yield two code actions for importing
 * Is a fixed two-level structure enough?
 * Should we devise a general way to encode custom interaction protocols for GUI refactorings?
 
-## Lazy assists with `ResolveCodeAction`
-
-**Issue:** https://github.com/microsoft/language-server-protocol/issues/787
-
-**Client Capability** `{ "resolveCodeAction": boolean }`
-
-If this capability is set, the assists will be computed lazily. Thus `CodeAction` returned from the server will only contain `id` but not `edit` or `command` fields. The only exclusion from the rule is the diagnostic edits.
-
-After the client got the id, it should then call `experimental/resolveCodeAction` command on the server and provide the following payload:
-
-```typescript
-interface ResolveCodeActionParams {
-    id: string;
-    codeActionParams: lc.CodeActionParams;
-}
-```
-
-As a result of the command call the client will get the respective workspace edit (`lc.WorkspaceEdit`).
-
-### Unresolved Questions
-
-* Apply smarter filtering for ids?
-* Upon `resolveCodeAction` command only call the assits which should be resolved and not all of them?
-
 ## Parent Module
 
 **Issue:** https://github.com/microsoft/language-server-protocol/issues/1002
index b3a10795eb004f15de5eb2582d426f1272c2b1ee..cd4775d2737f269a3cb872859af6cee6234edfc5 100644 (file)
         "block-comments": {
             "patterns": [
                 {
-                    "comment": "block comments",
+                    "comment": "empty block comments",
                     "name": "comment.block.rust",
-                    "begin": "/\\*(?!\\*)",
+                    "match": "/\\*\\*/"
+                },
+                {
+                    "comment": "block documentation comments",
+                    "name": "comment.block.documentation.rust",
+                    "begin": "/\\*\\*",
                     "end": "\\*/",
                     "patterns": [
                         {
                     ]
                 },
                 {
-                    "comment": "block documentation comments",
-                    "name": "comment.block.documentation.rust",
-                    "begin": "/\\*\\*",
+                    "comment": "block comments",
+                    "name": "comment.block.rust",
+                    "begin": "/\\*(?!\\*)",
                     "end": "\\*/",
                     "patterns": [
                         {
index d032b45b71ae4c93e502d8043f105fd19eaa971e..c9d032ead38645ea414d5b99a6d653ffd4f47989 100644 (file)
@@ -4,6 +4,7 @@ import * as ra from '../src/lsp_ext';
 import * as Is from 'vscode-languageclient/lib/common/utils/is';
 import { DocumentSemanticsTokensSignature, DocumentSemanticsTokensEditsSignature, DocumentRangeSemanticTokensSignature } from 'vscode-languageclient/lib/common/semanticTokens';
 import { assert } from './util';
+import { WorkspaceEdit } from 'vscode';
 
 function renderCommand(cmd: ra.CommandLink) {
     return `[${cmd.title}](command:${cmd.command}?${encodeURIComponent(JSON.stringify(cmd.arguments))} '${cmd.tooltip!}')`;
@@ -75,8 +76,8 @@ export function createClient(serverPath: string, cwd: string): lc.LanguageClient
                         return Promise.resolve(null);
                     });
             },
-            // Using custom handling of CodeActions where each code action is resolved lazily
-            // That's why we are not waiting for any command or edits
+            // Using custom handling of CodeActions to support action groups and snippet edits.
+            // Note that this means we have to re-implement lazy edit resolving ourselves as well.
             async provideCodeActions(document: vscode.TextDocument, range: vscode.Range, context: vscode.CodeActionContext, token: vscode.CancellationToken, _next: lc.ProvideCodeActionsSignature) {
                 const params: lc.CodeActionParams = {
                     textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document),
@@ -99,16 +100,15 @@ export function createClient(serverPath: string, cwd: string): lc.LanguageClient
                         const kind = client.protocol2CodeConverter.asCodeActionKind((item as any).kind);
                         const action = new vscode.CodeAction(item.title, kind);
                         const group = (item as any).group;
-                        const id = (item as any).id;
-                        const resolveParams: ra.ResolveCodeActionParams = {
-                            id: id,
-                            codeActionParams: params
-                        };
                         action.command = {
                             command: "rust-analyzer.resolveCodeAction",
                             title: item.title,
-                            arguments: [resolveParams],
+                            arguments: [item],
                         };
+
+                        // Set a dummy edit, so that VS Code doesn't try to resolve this.
+                        action.edit = new WorkspaceEdit();
+
                         if (group) {
                             let entry = groups.get(group);
                             if (!entry) {
@@ -134,6 +134,10 @@ export function createClient(serverPath: string, cwd: string): lc.LanguageClient
                                     return { label: item.title, arguments: item.command!!.arguments!![0] };
                                 })],
                             };
+
+                            // Set a dummy edit, so that VS Code doesn't try to resolve this.
+                            action.edit = new WorkspaceEdit();
+
                             result[index] = action;
                         }
                     }
@@ -164,7 +168,6 @@ class ExperimentalFeatures implements lc.StaticFeature {
         const caps: any = capabilities.experimental ?? {};
         caps.snippetTextEdit = true;
         caps.codeActionGroup = true;
-        caps.resolveCodeAction = true;
         caps.hoverActions = true;
         caps.statusNotification = true;
         capabilities.experimental = caps;
index 22509e874038068c2ba7301ed47e3ad008d29ac0..cf34622c34179b65cc6610da0bfa3b99215d36eb 100644 (file)
@@ -395,7 +395,7 @@ export function showReferences(ctx: Ctx): Cmd {
 }
 
 export function applyActionGroup(_ctx: Ctx): Cmd {
-    return async (actions: { label: string; arguments: ra.ResolveCodeActionParams }[]) => {
+    return async (actions: { label: string; arguments: lc.CodeAction }[]) => {
         const selectedAction = await vscode.window.showQuickPick(actions);
         if (!selectedAction) return;
         vscode.commands.executeCommand(
@@ -442,12 +442,13 @@ export function openDocs(ctx: Ctx): Cmd {
 
 export function resolveCodeAction(ctx: Ctx): Cmd {
     const client = ctx.client;
-    return async (params: ra.ResolveCodeActionParams) => {
-        const item: lc.WorkspaceEdit = await client.sendRequest(ra.resolveCodeAction, params);
-        if (!item) {
+    return async (params: lc.CodeAction) => {
+        params.command = undefined;
+        const item = await client.sendRequest(lc.CodeActionResolveRequest.type, params);
+        if (!item.edit) {
             return;
         }
-        const edit = client.protocol2CodeConverter.asWorkspaceEdit(item);
+        const edit = client.protocol2CodeConverter.asWorkspaceEdit(item.edit);
         await applySnippetWorkspaceEdit(edit);
     };
 }
index fc8e120b3fc6d8854f0e7bd68607e9aae77fe91f..d320c3cd7182ab14a9f0f380ab1dfe46b55dfc4b 100644 (file)
@@ -43,12 +43,6 @@ export const matchingBrace = new lc.RequestType<MatchingBraceParams, lc.Position
 
 export const parentModule = new lc.RequestType<lc.TextDocumentPositionParams, lc.LocationLink[], void>("experimental/parentModule");
 
-export interface ResolveCodeActionParams {
-    id: string;
-    codeActionParams: lc.CodeActionParams;
-}
-export const resolveCodeAction = new lc.RequestType<ResolveCodeActionParams, lc.WorkspaceEdit, unknown>('experimental/resolveCodeAction');
-
 export interface JoinLinesParams {
     textDocument: lc.TextDocumentIdentifier;
     ranges: lc.Range[];