@@ -72,6 +72,8 @@ defmodule Livebook.Intellisense.Elixir.IdentifierMatcher do
7272 name: name ( ) ,
7373 arity: integer ( )
7474 }
75+ | % { kind: :keyword , name: name ( ) }
76+ | % { kind: :binary_operator , name: name ( ) , arity: arity ( ) }
7577
7678 @ type name :: atom ( )
7779 @ type display_name :: String . t ( )
@@ -99,6 +101,26 @@ defmodule Livebook.Intellisense.Elixir.IdentifierMatcher do
99101 @ alias_only_atoms ~w( alias import require) a
100102 @ alias_only_charlists ~w( alias import require) c
101103
104+ @ block_keywords ~w( do end after catch else rescue)
105+
106+ @ kernel_operators [ "**" , "*" , "/" , "+" , "-" , "++" , "--" , ".." , "<>" ] ++
107+ [ "in" , "|>" , "<" , ">" , "<=" , ">=" , "==" , "!=" , "=~" , "===" , "!==" ] ++
108+ [ "&&" , "and" , "||" , "or" , "=" ]
109+
110+ @ bitwise_operators [ "<<<" , ">>>" , "&&&" , "|||" ]
111+
112+ @ special_forms_operators [ "::" , "=" ]
113+
114+ @ binary_operators [ "+++" , "---" , "not in" , "<<~" , "~>>" , "<~" , "~>" , "<~>" ] ++
115+ [ "=>" , "|" , "when" , "<-" , "\\ \\ " ]
116+
117+ @ binary_operators_docs [
118+ { Kernel , @ kernel_operators } ,
119+ { Kernel.SpecialForms , @ special_forms_operators } ,
120+ { Bitwise , @ bitwise_operators } ,
121+ { nil , @ binary_operators }
122+ ]
123+
102124 @ doc """
103125 Clears all loaded entries stored for node.
104126 """
@@ -247,6 +269,9 @@ defmodule Livebook.Intellisense.Elixir.IdentifierMatcher do
247269 { :struct , struct } ->
248270 match_struct ( List . to_string ( struct ) , ctx )
249271
272+ { :block_keyword_or_binary_operator , hint } ->
273+ match_block_keyword_or_binary_operator ( List . to_string ( hint ) , ctx )
274+
250275 # :none
251276 _ ->
252277 [ ]
@@ -351,6 +376,35 @@ defmodule Livebook.Intellisense.Elixir.IdentifierMatcher do
351376 do: item
352377 end
353378
379+ defp match_block_keyword_or_binary_operator ( hint , ctx ) do
380+ block_keywords =
381+ for value <- match_values_from_hint ( hint , @ block_keywords , ctx ) do
382+ % { kind: :keyword , name: value }
383+ end
384+
385+ binary_operators =
386+ for { mod , values } <- @ binary_operators_docs ,
387+ name <- match_values_from_hint ( hint , values , ctx ) do
388+ if mod do
389+ match_module_function ( mod , hint , ctx )
390+ else
391+ % { kind: :binary_operator , name: name , arity: 2 }
392+ end
393+ end
394+
395+ result = List . flatten ( block_keywords ++ binary_operators )
396+
397+ if result != [ ] do
398+ result
399+ end
400+ end
401+
402+ defp match_values_from_hint ( hint , values , ctx ) do
403+ for value <- values , ctx . matcher . ( value , hint ) do
404+ String . to_existing_atom ( value )
405+ end
406+ end
407+
354408 defp has_struct? ( mod ) do
355409 Code . ensure_loaded? ( mod ) and function_exported? ( mod , :__struct__ , 1 )
356410 end
@@ -690,34 +744,33 @@ defmodule Livebook.Intellisense.Elixir.IdentifierMatcher do
690744 )
691745
692746 Enum . map ( matching_funs , fn { name , arity , type } ->
693- doc_item =
694- Enum . find (
695- doc_items ,
696- % { from_default: false , documentation: nil , signatures: [ ] , specs: [ ] , meta: % { } } ,
697- fn doc_item ->
698- doc_item . name == name && doc_item . arity == arity
699- end
700- )
701-
702- % {
703- kind: :function ,
704- module: mod ,
705- name: name ,
706- arity: arity ,
707- type: type ,
708- display_name: Atom . to_string ( name ) ,
709- from_default: doc_item . from_default ,
710- documentation: doc_item . documentation ,
711- signatures: doc_item . signatures ,
712- specs: doc_item . specs ,
713- meta: doc_item . meta
714- }
747+ function_with_docs ( mod , doc_items , name , arity , type )
715748 end )
716749 else
717750 [ ]
718751 end
719752 end
720753
754+ defp function_with_docs ( mod , doc_items , name , arity , type ) do
755+ item = % {
756+ kind: :function ,
757+ module: mod ,
758+ name: name ,
759+ arity: arity ,
760+ type: type ,
761+ display_name: Atom . to_string ( name )
762+ }
763+
764+ doc_item =
765+ if doc_item = Enum . find ( doc_items , & ( & 1 . name == name and & 1 . arity == arity ) ) do
766+ Map . take ( doc_item , [ :documentation , :from_default , :meta , :signatures , :specs ] )
767+ else
768+ % { from_default: false , documentation: nil , signatures: [ ] , specs: [ ] , meta: % { } }
769+ end
770+
771+ Map . merge ( item , doc_item )
772+ end
773+
721774 defp exports ( mod , node ) do
722775 try do
723776 :erpc . call ( node , mod , :module_info , [ :exports ] )
0 commit comments