@@ -10,189 +10,13 @@ defmodule ElixirLS.LanguageServer.Providers.CodeLens do
10
10
disable this feature.
11
11
"""
12
12
13
- alias ElixirLS.LanguageServer . { Server , SourceFile }
14
- alias ElixirSense.Core.Parser
15
- alias ElixirSense.Core.State
16
- alias Erl2ex.Convert . { Context , ErlForms }
17
- alias Erl2ex.Pipeline . { Parse , ModuleData , ExSpec }
13
+ alias ElixirLS.LanguageServer.Providers.CodeLens
18
14
import ElixirLS.LanguageServer.Protocol
19
15
20
- defmodule ContractTranslator do
21
- def translate_contract ( fun , contract , is_macro ) do
22
- # FIXME: Private module
23
- { [ % ExSpec { specs: [ spec ] } | _ ] , _ } =
24
- "-spec foo#{ contract } ."
25
- # FIXME: Private module
26
- |> Parse . string ( )
27
- |> hd ( )
28
- |> elem ( 0 )
29
- # FIXME: Private module
30
- |> ErlForms . conv_form ( % Context {
31
- in_type_expr: true ,
32
- # FIXME: Private module
33
- module_data: % ModuleData { }
34
- } )
16
+ def spec_code_lens ( server_instance_id , uri , text ) ,
17
+ do: CodeLens.Spec . code_lens ( server_instance_id , uri , text )
35
18
36
- spec
37
- |> Macro . postwalk ( & tweak_specs / 1 )
38
- |> drop_macro_env ( is_macro )
39
- |> Macro . to_string ( )
40
- |> String . replace ( "()" , "" )
41
- |> Code . format_string! ( line_length: :infinity )
42
- |> IO . iodata_to_binary ( )
43
- |> String . replace_prefix ( "foo" , to_string ( fun ) )
44
- end
45
-
46
- defp tweak_specs ( { :list , _meta , args } ) do
47
- case args do
48
- [ { :{} , _ , [ { :atom , _ , [ ] } , { wild , _ , _ } ] } ] when wild in [ :_ , :any ] -> quote do: keyword ( )
49
- list -> list
50
- end
51
- end
52
-
53
- defp tweak_specs ( { :nonempty_list , _meta , args } ) do
54
- case args do
55
- [ { :any , _ , [ ] } ] -> quote do: [ ... ]
56
- _ -> args ++ quote do: [ ... ]
57
- end
58
- end
59
-
60
- defp tweak_specs ( { :%{} , _meta , fields } ) do
61
- fields =
62
- Enum . map ( fields , fn
63
- { :map_field_exact , _ , [ key , value ] } -> { key , value }
64
- { key , value } -> quote do: { optional ( unquote ( key ) ) , unquote ( value ) }
65
- field -> field
66
- end )
67
- |> Enum . reject ( & match? ( { { :optional , _ , [ { :any , _ , [ ] } ] } , { :any , _ , [ ] } } , & 1 ) )
68
-
69
- fields
70
- |> Enum . find_value ( fn
71
- { :__struct__ , struct_type } when is_atom ( struct_type ) -> struct_type
72
- _ -> nil
73
- end )
74
- |> case do
75
- nil -> { :%{} , [ ] , fields }
76
- struct_type -> { { :. , [ ] , [ struct_type , :t ] } , [ ] , [ ] }
77
- end
78
- end
79
-
80
- # Undo conversion of _ to any() when inside binary spec
81
- defp tweak_specs ( { :<<>> , _ , children } ) do
82
- children =
83
- Macro . postwalk ( children , fn
84
- { :any , _ , [ ] } -> quote do: _
85
- other -> other
86
- end )
87
-
88
- { :<<>> , [ ] , children }
89
- end
90
-
91
- defp tweak_specs ( { :_ , _ , _ } ) do
92
- quote do: any ( )
93
- end
94
-
95
- defp tweak_specs ( { :when , [ ] , [ spec , substitutions ] } ) do
96
- substitutions = Enum . reject ( substitutions , & match? ( { :_ , { :any , _ , [ ] } } , & 1 ) )
97
-
98
- case substitutions do
99
- [ ] -> spec
100
- _ -> { :when , [ ] , [ spec , substitutions ] }
101
- end
102
- end
103
-
104
- defp tweak_specs ( node ) do
105
- node
106
- end
107
-
108
- defp drop_macro_env ( ast , false ) , do: ast
109
-
110
- defp drop_macro_env ( { :"::" , [ ] , [ { :foo , [ ] , [ _env | rest ] } , res ] } , true ) do
111
- { :"::" , [ ] , [ { :foo , [ ] , rest } , res ] }
112
- end
113
- end
114
-
115
- def spec_code_lens ( server_instance_id , uri , text ) do
116
- resp =
117
- for { _ , line , { mod , fun , arity } , contract , is_macro } <- Server . suggest_contracts ( uri ) ,
118
- SourceFile . function_def_on_line? ( text , line , fun ) ,
119
- spec = ContractTranslator . translate_contract ( fun , contract , is_macro ) do
120
- build_code_lens (
121
- line ,
122
- "@spec #{ spec } " ,
123
- "spec:#{ server_instance_id } " ,
124
- % {
125
- "uri" => uri ,
126
- "mod" => to_string ( mod ) ,
127
- "fun" => to_string ( fun ) ,
128
- "arity" => arity ,
129
- "spec" => spec ,
130
- "line" => line
131
- }
132
- )
133
- end
134
-
135
- { :ok , resp }
136
- end
137
-
138
- def test_code_lens ( uri , src ) do
139
- file_path = SourceFile . path_from_uri ( uri )
140
-
141
- if imports? ( src , ExUnit.Case ) do
142
- test_calls = calls_to ( src , :test )
143
- describe_calls = calls_to ( src , :describe )
144
-
145
- calls_lenses =
146
- for { line , _col } <- test_calls ++ describe_calls do
147
- test_filter = "#{ file_path } :#{ line } "
148
-
149
- build_code_lens ( line , "Run test" , "elixir.test.run" , test_filter )
150
- end
151
-
152
- file_lens = build_code_lens ( 1 , "Run test" , "elixir.test.run" , file_path )
153
-
154
- { :ok , [ file_lens | calls_lenses ] }
155
- end
156
- end
157
-
158
- @ spec imports? ( String . t ( ) , [ atom ( ) ] | atom ( ) ) :: boolean ( )
159
- defp imports? ( buffer , modules ) do
160
- buffer_file_metadata =
161
- buffer
162
- |> Parser . parse_string ( true , true , 1 )
163
-
164
- imports_set =
165
- buffer_file_metadata . lines_to_env
166
- |> get_imports ( )
167
- |> MapSet . new ( )
168
-
169
- modules
170
- |> List . wrap ( )
171
- |> MapSet . new ( )
172
- |> MapSet . subset? ( imports_set )
173
- end
174
-
175
- defp get_imports ( lines_to_env ) do
176
- % State.Env { imports: imports } =
177
- lines_to_env
178
- |> Enum . max_by ( fn { k , _v } -> k end )
179
- |> elem ( 1 )
180
-
181
- imports
182
- end
183
-
184
- @ spec calls_to ( String . t ( ) , atom ( ) | { atom ( ) , integer ( ) } ) :: [ { pos_integer ( ) , pos_integer ( ) } ]
185
- defp calls_to ( buffer , function ) do
186
- buffer_file_metadata =
187
- buffer
188
- |> Parser . parse_string ( true , true , 1 )
189
-
190
- buffer_file_metadata . calls
191
- |> Enum . map ( fn { _k , v } -> v end )
192
- |> List . flatten ( )
193
- |> Enum . filter ( fn call_info -> call_info . func == function end )
194
- |> Enum . map ( fn call -> call . position end )
195
- end
19
+ def test_code_lens ( uri , text ) , do: CodeLens.Test . code_lens ( uri , text )
196
20
197
21
def build_code_lens ( line , title , command , argument ) do
198
22
% {
0 commit comments