]> git.lizzy.rs Git - rust.git/blobdiff - crates/rust-analyzer/src/conv.rs
Merge #4161
[rust.git] / crates / rust-analyzer / src / conv.rs
index b012f5dd5e94becf0afbcd9be7ff744275025ec3..7be5ebcdb5a0d13599cc5a8d628c48186cc46936 100644 (file)
@@ -3,28 +3,31 @@
 
 use lsp_types::{
     self, CreateFile, DiagnosticSeverity, DocumentChangeOperation, DocumentChanges, Documentation,
-    Location, LocationLink, MarkupContent, MarkupKind, Position, Range, RenameFile, ResourceOp,
-    SemanticTokenModifier, SemanticTokenType, SymbolKind, TextDocumentEdit, TextDocumentIdentifier,
-    TextDocumentItem, TextDocumentPositionParams, Url, VersionedTextDocumentIdentifier,
-    WorkspaceEdit,
+    Location, LocationLink, MarkupContent, MarkupKind, ParameterInformation, ParameterLabel,
+    Position, Range, RenameFile, ResourceOp, SemanticTokenModifier, SemanticTokenType,
+    SignatureInformation, SymbolKind, TextDocumentEdit, TextDocumentIdentifier, TextDocumentItem,
+    TextDocumentPositionParams, Url, VersionedTextDocumentIdentifier, WorkspaceEdit,
 };
 use ra_ide::{
     translate_offset_with_edit, CompletionItem, CompletionItemKind, FileId, FilePosition,
     FileRange, FileSystemEdit, Fold, FoldKind, Highlight, HighlightModifier, HighlightTag,
-    InsertTextFormat, LineCol, LineIndex, NavigationTarget, RangeInfo, ReferenceAccess, Severity,
-    SourceChange, SourceFileEdit,
+    InlayHint, InlayKind, InsertTextFormat, LineCol, LineIndex, NavigationTarget, RangeInfo,
+    ReferenceAccess, Severity, SourceChange, SourceFileEdit,
 };
-use ra_syntax::{SyntaxKind, TextRange, TextUnit};
+use ra_syntax::{SyntaxKind, TextRange, TextSize};
 use ra_text_edit::{AtomTextEdit, TextEdit};
 use ra_vfs::LineEndings;
 
 use crate::{
     req,
-    semantic_tokens::{self, ModifierSet, BUILTIN, CONSTANT, CONTROL, MUTABLE, UNSAFE},
+    semantic_tokens::{self, ModifierSet, CONSTANT, CONTROL_FLOW, MUTABLE, UNSAFE},
     world::WorldSnapshot,
     Result,
 };
-use semantic_tokens::ATTRIBUTE;
+use semantic_tokens::{
+    ATTRIBUTE, BUILTIN_TYPE, ENUM_MEMBER, FORMAT_SPECIFIER, LIFETIME, TYPE_ALIAS, UNION,
+    UNRESOLVED_REFERENCE,
+};
 
 pub trait Conv {
     type Output;
@@ -57,7 +60,7 @@ fn conv(self) -> <Self as Conv>::Output {
             SyntaxKind::RECORD_FIELD_DEF => SymbolKind::Field,
             SyntaxKind::STATIC_DEF => SymbolKind::Constant,
             SyntaxKind::CONST_DEF => SymbolKind::Constant,
-            SyntaxKind::IMPL_BLOCK => SymbolKind::Object,
+            SyntaxKind::IMPL_DEF => SymbolKind::Object,
             _ => SymbolKind::Variable,
         }
     }
@@ -98,6 +101,7 @@ fn conv(self) -> <Self as Conv>::Output {
             CompletionItemKind::Method => Method,
             CompletionItemKind::TypeParam => TypeParameter,
             CompletionItemKind::Macro => Method,
+            CompletionItemKind::Attribute => EnumMember,
         }
     }
 }
@@ -121,22 +125,22 @@ fn conv_with(self, ctx: (&LineIndex, LineEndings)) -> ::lsp_types::CompletionIte
         // LSP does not allow arbitrary edits in completion, so we have to do a
         // non-trivial mapping here.
         for atom_edit in self.text_edit().as_atoms() {
-            if self.source_range().is_subrange(&atom_edit.delete) {
+            if atom_edit.delete.contains_range(self.source_range()) {
                 text_edit = Some(if atom_edit.delete == self.source_range() {
-                    atom_edit.conv_with(ctx)
+                    atom_edit.conv_with((ctx.0, ctx.1))
                 } else {
                     assert!(self.source_range().end() == atom_edit.delete.end());
                     let range1 =
-                        TextRange::from_to(atom_edit.delete.start(), self.source_range().start());
+                        TextRange::new(atom_edit.delete.start(), self.source_range().start());
                     let range2 = self.source_range();
                     let edit1 = AtomTextEdit::replace(range1, String::new());
                     let edit2 = AtomTextEdit::replace(range2, atom_edit.insert.clone());
-                    additional_text_edits.push(edit1.conv_with(ctx));
-                    edit2.conv_with(ctx)
+                    additional_text_edits.push(edit1.conv_with((ctx.0, ctx.1)));
+                    edit2.conv_with((ctx.0, ctx.1))
                 })
             } else {
-                assert!(self.source_range().intersection(&atom_edit.delete).is_none());
-                additional_text_edits.push(atom_edit.conv_with(ctx));
+                assert!(self.source_range().intersect(atom_edit.delete).is_none());
+                additional_text_edits.push(atom_edit.conv_with((ctx.0, ctx.1)));
             }
         }
         let text_edit = text_edit.unwrap();
@@ -146,13 +150,27 @@ fn conv_with(self, ctx: (&LineIndex, LineEndings)) -> ::lsp_types::CompletionIte
             detail: self.detail().map(|it| it.to_string()),
             filter_text: Some(self.lookup().to_string()),
             kind: self.kind().map(|it| it.conv()),
-            text_edit: Some(text_edit),
+            text_edit: Some(text_edit.into()),
             additional_text_edits: Some(additional_text_edits),
             documentation: self.documentation().map(|it| it.conv()),
             deprecated: Some(self.deprecated()),
+            command: if self.trigger_call_info() {
+                let cmd = lsp_types::Command {
+                    title: "triggerParameterHints".into(),
+                    command: "editor.action.triggerParameterHints".into(),
+                    arguments: None,
+                };
+                Some(cmd)
+            } else {
+                None
+            },
             ..Default::default()
         };
 
+        if self.score().is_some() {
+            res.preselect = Some(true)
+        }
+
         if self.deprecated() {
             res.tags = Some(vec![lsp_types::CompletionItemTag::Deprecated])
         }
@@ -167,15 +185,15 @@ fn conv_with(self, ctx: (&LineIndex, LineEndings)) -> ::lsp_types::CompletionIte
 }
 
 impl ConvWith<&LineIndex> for Position {
-    type Output = TextUnit;
+    type Output = TextSize;
 
-    fn conv_with(self, line_index: &LineIndex) -> TextUnit {
+    fn conv_with(self, line_index: &LineIndex) -> TextSize {
         let line_col = LineCol { line: self.line as u32, col_utf16: self.character as u32 };
         line_index.offset(line_col)
     }
 }
 
-impl ConvWith<&LineIndex> for TextUnit {
+impl ConvWith<&LineIndex> for TextSize {
     type Output = Position;
 
     fn conv_with(self, line_index: &LineIndex) -> Position {
@@ -196,7 +214,7 @@ impl ConvWith<&LineIndex> for Range {
     type Output = TextRange;
 
     fn conv_with(self, line_index: &LineIndex) -> TextRange {
-        TextRange::from_to(self.start.conv_with(line_index), self.end.conv_with(line_index))
+        TextRange::new(self.start.conv_with(line_index), self.end.conv_with(line_index))
     }
 }
 
@@ -210,17 +228,20 @@ fn conv(self) -> Documentation {
     }
 }
 
-impl Conv for ra_ide::FunctionSignature {
+impl ConvWith<bool> for ra_ide::FunctionSignature {
     type Output = lsp_types::SignatureInformation;
-    fn conv(self) -> Self::Output {
-        use lsp_types::{ParameterInformation, ParameterLabel, SignatureInformation};
-
-        let label = self.to_string();
-
-        let documentation = self.doc.map(|it| it.conv());
+    fn conv_with(self, concise: bool) -> Self::Output {
+        let (label, documentation, params) = if concise {
+            let mut params = self.parameters;
+            if self.has_self_param {
+                params.remove(0);
+            }
+            (params.join(", "), None, params)
+        } else {
+            (self.to_string(), self.doc.map(|it| it.conv()), self.parameters)
+        };
 
-        let parameters: Vec<ParameterInformation> = self
-            .parameters
+        let parameters: Vec<ParameterInformation> = params
             .into_iter()
             .map(|param| ParameterInformation {
                 label: ParameterLabel::Simple(param),
@@ -280,7 +301,7 @@ fn conv_with(self, ctx: &FoldConvCtx) -> lsp_types::FoldingRange {
             // range.end.line from the folding region if there is more text after range.end
             // on the same line.
             let has_more_text_on_end_line = ctx.text
-                [TextRange::from_to(self.range.end(), TextUnit::of_str(ctx.text))]
+                [TextRange::new(self.range.end(), TextSize::of(ctx.text))]
             .chars()
             .take_while(|it| *it != '\n')
             .any(|it| !it.is_whitespace());
@@ -310,47 +331,66 @@ fn conv_with(self, ctx: &FoldConvCtx) -> lsp_types::FoldingRange {
     }
 }
 
+impl ConvWith<&LineIndex> for InlayHint {
+    type Output = req::InlayHint;
+    fn conv_with(self, line_index: &LineIndex) -> Self::Output {
+        req::InlayHint {
+            label: self.label.to_string(),
+            range: self.range.conv_with(line_index),
+            kind: match self.kind {
+                InlayKind::ParameterHint => req::InlayKind::ParameterHint,
+                InlayKind::TypeHint => req::InlayKind::TypeHint,
+                InlayKind::ChainingHint => req::InlayKind::ChainingHint,
+            },
+        }
+    }
+}
+
 impl Conv for Highlight {
     type Output = (u32, u32);
 
     fn conv(self) -> Self::Output {
         let mut mods = ModifierSet::default();
         let type_ = match self.tag {
+            HighlightTag::Struct => SemanticTokenType::STRUCT,
+            HighlightTag::Enum => SemanticTokenType::ENUM,
+            HighlightTag::Union => UNION,
+            HighlightTag::TypeAlias => TYPE_ALIAS,
+            HighlightTag::Trait => SemanticTokenType::INTERFACE,
+            HighlightTag::BuiltinType => BUILTIN_TYPE,
+            HighlightTag::SelfType => SemanticTokenType::TYPE,
             HighlightTag::Field => SemanticTokenType::MEMBER,
             HighlightTag::Function => SemanticTokenType::FUNCTION,
             HighlightTag::Module => SemanticTokenType::NAMESPACE,
             HighlightTag::Constant => {
+                mods |= CONSTANT;
                 mods |= SemanticTokenModifier::STATIC;
-                mods |= SemanticTokenModifier::READONLY;
-                CONSTANT
+                SemanticTokenType::VARIABLE
             }
-            HighlightTag::Macro => SemanticTokenType::MACRO,
-            HighlightTag::Variable => SemanticTokenType::VARIABLE,
-            HighlightTag::Type => SemanticTokenType::TYPE,
-            HighlightTag::TypeSelf => {
-                mods |= SemanticTokenModifier::REFERENCE;
-                SemanticTokenType::TYPE
+            HighlightTag::Static => {
+                mods |= SemanticTokenModifier::STATIC;
+                SemanticTokenType::VARIABLE
             }
+            HighlightTag::EnumVariant => ENUM_MEMBER,
+            HighlightTag::Macro => SemanticTokenType::MACRO,
+            HighlightTag::Local => SemanticTokenType::VARIABLE,
             HighlightTag::TypeParam => SemanticTokenType::TYPE_PARAMETER,
-            HighlightTag::TypeLifetime => {
-                mods |= SemanticTokenModifier::REFERENCE;
-                SemanticTokenType::LABEL
-            }
-            HighlightTag::LiteralByte => SemanticTokenType::NUMBER,
-            HighlightTag::LiteralNumeric => SemanticTokenType::NUMBER,
-            HighlightTag::LiteralChar => SemanticTokenType::NUMBER,
+            HighlightTag::Lifetime => LIFETIME,
+            HighlightTag::ByteLiteral | HighlightTag::NumericLiteral => SemanticTokenType::NUMBER,
+            HighlightTag::CharLiteral | HighlightTag::StringLiteral => SemanticTokenType::STRING,
             HighlightTag::Comment => SemanticTokenType::COMMENT,
-            HighlightTag::LiteralString => SemanticTokenType::STRING,
             HighlightTag::Attribute => ATTRIBUTE,
             HighlightTag::Keyword => SemanticTokenType::KEYWORD,
+            HighlightTag::UnresolvedReference => UNRESOLVED_REFERENCE,
+            HighlightTag::FormatSpecifier => FORMAT_SPECIFIER,
         };
 
         for modifier in self.modifiers.iter() {
             let modifier = match modifier {
+                HighlightModifier::Definition => SemanticTokenModifier::DECLARATION,
+                HighlightModifier::ControlFlow => CONTROL_FLOW,
                 HighlightModifier::Mutable => MUTABLE,
                 HighlightModifier::Unsafe => UNSAFE,
-                HighlightModifier::Control => CONTROL,
-                HighlightModifier::Builtin => BUILTIN,
             };
             mods |= modifier;
         }
@@ -549,7 +589,7 @@ fn try_conv_with(self, world: &WorldSnapshot) -> Result<req::GotoTypeDefinitionR
             .into_iter()
             .map(|nav| (file_id, RangeInfo::new(range, nav)))
             .try_conv_with_to_vec(world)?;
-        if world.options.supports_location_link {
+        if world.config.client_caps.location_link {
             Ok(links.into())
         } else {
             let locations: Vec<Location> = links