diff --git a/lsp4s/src/main/scala/org/langmeta/lsp/Enums.scala b/lsp4s/src/main/scala/org/langmeta/lsp/Enums.scala index b0355bda4a8..8d4414c716c 100644 --- a/lsp4s/src/main/scala/org/langmeta/lsp/Enums.scala +++ b/lsp4s/src/main/scala/org/langmeta/lsp/Enums.scala @@ -39,6 +39,13 @@ case object CompletionItemKind case object Color extends CompletionItemKind(16) case object File extends CompletionItemKind(17) case object Reference extends CompletionItemKind(18) + case object Folder extends CompletionItemKind(19) + case object EnumMember extends CompletionItemKind(20) + case object Constant extends CompletionItemKind(21) + case object Struct extends CompletionItemKind(22) + case object Event extends CompletionItemKind(23) + case object Operator extends CompletionItemKind(24) + case object TypeParameter extends CompletionItemKind(25) val values = findValues } @@ -85,6 +92,14 @@ case object SymbolKind case object Number extends SymbolKind(16) case object Boolean extends SymbolKind(17) case object Array extends SymbolKind(18) + case object Object extends SymbolKind(19) + case object Key extends SymbolKind(20) + case object Null extends SymbolKind(21) + case object EnumMember extends SymbolKind(22) + case object Struct extends SymbolKind(23) + case object Event extends SymbolKind(24) + case object Operator extends SymbolKind(25) + case object TypeParameter extends SymbolKind(26) val values = findValues } diff --git a/metals/src/main/scala/org/langmeta/semanticdb/SemanticdbEnrichments.scala b/metals/src/main/scala/org/langmeta/semanticdb/SemanticdbEnrichments.scala index cdc49f63fd0..9222dbda3cd 100644 --- a/metals/src/main/scala/org/langmeta/semanticdb/SemanticdbEnrichments.scala +++ b/metals/src/main/scala/org/langmeta/semanticdb/SemanticdbEnrichments.scala @@ -9,6 +9,8 @@ object SemanticdbEnrichments { def toSymbolKind: SymbolKind = if (isClass) SymbolKind.Class else if (isTrait) SymbolKind.Interface + else if (isTypeParam) SymbolKind.TypeParameter + else if (isObject) SymbolKind.Object else SymbolKind.Module } } diff --git a/metals/src/main/scala/scala/meta/metals/ScalametaEnrichments.scala b/metals/src/main/scala/scala/meta/metals/ScalametaEnrichments.scala index 8f33180551d..4c4fd47cf0a 100644 --- a/metals/src/main/scala/scala/meta/metals/ScalametaEnrichments.scala +++ b/metals/src/main/scala/scala/meta/metals/ScalametaEnrichments.scala @@ -66,6 +66,8 @@ object ScalametaEnrichments { case _: Defn.Object => SymbolKind.Module case _: Pkg.Object => SymbolKind.Namespace case _: Pkg => SymbolKind.Package + case _: Type.Param => SymbolKind.TypeParameter + case _: Lit.Null => SymbolKind.Null // TODO(alexey) are these kinds useful? // case ??? => SymbolKind.Enum // case ??? => SymbolKind.String diff --git a/metals/src/main/scala/scala/meta/metals/providers/CompletionProvider.scala b/metals/src/main/scala/scala/meta/metals/providers/CompletionProvider.scala index efe40ab1526..9099b5f7ac2 100644 --- a/metals/src/main/scala/scala/meta/metals/providers/CompletionProvider.scala +++ b/metals/src/main/scala/scala/meta/metals/providers/CompletionProvider.scala @@ -19,16 +19,26 @@ object CompletionProvider extends LazyLogging { ): CompletionList = { import compiler._ + def isFunction(symbol: Symbol): Boolean = { + compiler.definitions.isFunctionSymbol( + symbol.info.finalResultType.typeSymbol + ) + } + def completionItemKind(r: CompletionResult#M): CompletionItemKind = { - if (r.sym.hasPackageFlag) CompletionItemKind.Module - else if (r.sym.isPackageObject) CompletionItemKind.Module - else if (r.sym.isModuleOrModuleClass) CompletionItemKind.Module - else if (r.sym.isTraitOrInterface) CompletionItemKind.Interface - else if (r.sym.isClass) CompletionItemKind.Class - else if (r.sym.isMethod) CompletionItemKind.Method - else if (r.sym.isCaseAccessor) CompletionItemKind.Field - else if (r.sym.isVal) CompletionItemKind.Value - else if (r.sym.isVar) CompletionItemKind.Variable + val symbol = r.sym + val symbolIsFunction = isFunction(symbol) + if (symbol.hasPackageFlag) CompletionItemKind.Module + else if (symbol.isPackageObject) CompletionItemKind.Module + else if (symbol.isModuleOrModuleClass) CompletionItemKind.Module + else if (symbol.isTraitOrInterface) CompletionItemKind.Interface + else if (symbol.isClass) CompletionItemKind.Class + else if (symbol.isMethod) CompletionItemKind.Method + else if (symbol.isCaseAccessor) CompletionItemKind.Field + else if (symbol.isVal && !symbolIsFunction) CompletionItemKind.Value + else if (symbol.isVar && !symbolIsFunction) CompletionItemKind.Variable + else if (symbol.isTypeParameterOrSkolem) CompletionItemKind.TypeParameter + else if (symbolIsFunction) CompletionItemKind.Function else CompletionItemKind.Value } diff --git a/metals/src/test/scala/tests/compiler/CompletionsTest.scala b/metals/src/test/scala/tests/compiler/CompletionsTest.scala index 24913864fda..aa863395d48 100644 --- a/metals/src/test/scala/tests/compiler/CompletionsTest.scala +++ b/metals/src/test/scala/tests/compiler/CompletionsTest.scala @@ -165,6 +165,44 @@ object CompletionsTest extends CompilerSuite { detail = "" ) + check( + "type parameter", + """ + |trait Hmm[ABC] { + | val a: AB<<>> + |} + """.stripMargin, + label = "ABC", + kind = CompletionItemKind.TypeParameter, + detail = "" + ) + + check( + "function val", + """ + |object a { + | val xyz: Int => String => Boolean = _ => _ => false + | xy<<>> + |} + """.stripMargin, + label = "xyz", + kind = CompletionItemKind.Function, + detail = ": Int => (String => Boolean)" + ) + + check( + "function var", + """ + |object a { + | var xyz: Int => String => Boolean = _ => _ => false + | xy<<>> + |} + """.stripMargin, + label = "xyz", + kind = CompletionItemKind.Function, + detail = ": Int => (String => Boolean)" + ) + check( "sorting", """