Skip to content

Commit

Permalink
LSP fixes and improvements (#62)
Browse files Browse the repository at this point in the history
* LSP does not leave running BEAM when VSC is closed

* First opened source file was not validated

* Navigation works for records and fields

* Navigation works for records in included files
  • Loading branch information
wojteksurowka authored and pgourlain committed May 12, 2018
1 parent ae5b35d commit 71190d4
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 17 deletions.
2 changes: 2 additions & 0 deletions apps/erlangbridge/src/gen_lsp_server.erl
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ handle_info({tcp, Socket, RawData}, State) ->
lsp_navigation:references_info(file_uri_to_file(FileName), to_int(Line), to_int(Column));
{codelens_info, FileName} ->
lsp_navigation:codelens_info(file_uri_to_file(FileName));
{stop_server} ->
init:stop();
_ ->
#{parse_result => false,
error_message => <<"unknown command">>}
Expand Down
87 changes: 73 additions & 14 deletions apps/erlangbridge/src/lsp_navigation.erl
Original file line number Diff line number Diff line change
Expand Up @@ -220,25 +220,29 @@ fold_in_file_syntax_tree(FileSyntaxTree, StartAcc, Fun) ->
end, StartAcc, FileSyntaxTree).

find_in_file_syntax_tree(FileSyntaxTree, Fun) ->
fold_in_file_syntax_tree(FileSyntaxTree, undefined,
fun (SyntaxTree, SingleAcc) ->
fold_in_file_syntax_tree(FileSyntaxTree, {undefined, undefined},
fun (SyntaxTree, {SingleAcc, CurrentFile}) ->
UpdatedFile = case SyntaxTree of
{attribute, _, file, {FileName, _}} -> FileName;
_ -> CurrentFile
end,
case SingleAcc of
undefined ->
Fun(SyntaxTree);
{Fun(SyntaxTree, UpdatedFile), UpdatedFile};
_ ->
SingleAcc
{SingleAcc, CurrentFile}
end
end).

element_at_position(CurrentModule, FileSyntaxTree, Line, Column) ->
Fun = fun
({call, {L, StartColumn}, {atom, {L, StartColumn}, Function}, Args}) when L =:= Line andalso StartColumn =< Column ->
({call, {L, StartColumn}, {atom, {L, StartColumn}, Function}, Args}, _) when L =:= Line andalso StartColumn =< Column ->
EndColumn = StartColumn + length(atom_to_list(Function)),
if
Column =< EndColumn -> {function_use, CurrentModule, Function, length(Args)};
true -> undefined
end;
({call, {_, _}, {remote, {_, _}, {atom, {_, MStartColumn}, Module}, {atom, {L, StartColumn}, Function}}, Args}) when L =:= Line andalso MStartColumn =< Column ->
({call, {_, _}, {remote, {_, _}, {atom, {_, MStartColumn}, Module}, {atom, {L, StartColumn}, Function}}, Args}, _) when L =:= Line andalso MStartColumn =< Column ->
MEndColumn = MStartColumn + length(atom_to_list(Module)),
EndColumn = StartColumn + length(atom_to_list(Module)) + 1 + length(atom_to_list(Function)),
if
Expand All @@ -248,28 +252,57 @@ element_at_position(CurrentModule, FileSyntaxTree, Line, Column) ->
true -> undefined
end
end;
({'fun',{L, StartColumn}, {function, Function, Arity}}) when L =:= Line andalso StartColumn =< Column ->
({'fun',{L, StartColumn}, {function, Function, Arity}}, _) when L =:= Line andalso StartColumn =< Column ->
EndColumn = StartColumn + 4 + length(atom_to_list(Function)),
if
Column =< EndColumn -> {function_use, CurrentModule, Function, Arity};
true -> undefined
end;
({'fun', {_, _}, {function, {atom, {_, _}, Module}, {atom, {L, StartColumn}, Function}, {integer, {_, _}, Arity}}}) when L =:= Line andalso StartColumn =< Column ->
({'fun', {_, _}, {function, {atom, {_, _}, Module}, {atom, {L, StartColumn}, Function}, {integer, {_, _}, Arity}}}, _) when L =:= Line andalso StartColumn =< Column ->
EndColumn = StartColumn + length(atom_to_list(Function)),
if
Column =< EndColumn -> {function_use, Module, Function, Arity};
true -> undefined
end;
({var, {L, StartColumn}, Variable}) when L =:= Line andalso StartColumn =< Column ->
({var, {L, StartColumn}, Variable}, _) when L =:= Line andalso StartColumn =< Column ->
EndColumn = StartColumn + length(atom_to_list(Variable)),
if
Column =< EndColumn -> {variable, Variable, L, StartColumn};
true -> undefined
end;
(_SyntaxTree) ->
({record, {L, StartColumn}, Record, Fields}, _) when L =:= Line andalso StartColumn =< Column ->
EndColumn = StartColumn + length(atom_to_list(Record)) + 1,
if
Column =< EndColumn -> {record, Record};
true -> find_record_field_use(Record, Fields, Column)
end;
({record, {L, StartColumn}, _, Record, Fields}, _) when L =:= Line andalso StartColumn =< Column ->
EndColumn = StartColumn + length(atom_to_list(Record)) + 1,
if
Column =< EndColumn -> {record, Record};
true -> find_record_field_use(Record, Fields, Column)
end;
({record_field, {L, RecordSttartColumn}, _, Record, {atom, {L, FieldStartColumn}, Field}}, _) when L =:= Line andalso RecordSttartColumn =< Column ->
FieldEndColumn = FieldStartColumn + length(atom_to_list(Field)),
if
Column < FieldStartColumn -> {record, Record};
Column < FieldEndColumn -> {field, Record, Field};
true -> undefined
end;
(_SyntaxTree, _File) ->
undefined
end,
find_in_file_syntax_tree(FileSyntaxTree, Fun).
{What, _File} = find_in_file_syntax_tree(FileSyntaxTree, Fun),
What.

find_record_field_use(_Record, [], _Column) ->
undefined;
find_record_field_use(Record, [{record_field, _, {atom, {_, StartColumn}, Field}, _} | Tail], Column) ->
EndColumn = StartColumn + length(atom_to_list(Field)),
if
StartColumn =< Column andalso Column =< EndColumn -> {field, Record, Field};
true -> find_record_field_use(Record, Tail, Column)
end.

get_module_syntax_tree(Module, CurrentFileSyntaxTree, CurrentFile) ->
CurrentModule = list_to_atom(filename:basename(CurrentFile)),
Expand Down Expand Up @@ -335,13 +368,22 @@ find_element({module_use, Module}, CurrentFileSyntaxTree, CurrentFile) ->
{attribute, {Line, Column}, _} -> {File, Line, Column};
_ -> undefined
end;

find_element({function_use, Module, Function, Arity}, CurrentFileSyntaxTree, CurrentFile) ->
{SyntaxTree, File} = get_module_syntax_tree(Module, CurrentFileSyntaxTree, CurrentFile),
case find_function(SyntaxTree, Function, Arity) of
{function, {Line, Column}, _Function, _Arity, _Clauses} -> {File, Line, Column};
_ -> undefined
end;
find_element({record, Record}, CurrentFileSyntaxTree, _CurrentFile) ->
case find_record(CurrentFileSyntaxTree, Record) of
{{attribute, {Line, Column}, record, {Record, _}}, File} -> {File, Line, Column};
undefined -> undefined
end;
find_element({field, Record, Field}, CurrentFileSyntaxTree, _CurrentFile) ->
case find_record(CurrentFileSyntaxTree, Record) of
{{attribute, _, record, {Record, Fields}}, File} -> find_record_field(Field, Fields, File);
undefined -> undefined
end;
find_element({variable, Variable, Line, Column}, CurrentFileSyntaxTree, CurrentFile) ->
AllFunctionsInReverseOrder = lists:foldl(fun (TopLevelSyntaxTree, Acc) ->
erl_syntax_lib:fold(fun (SyntaxTree, SingleAcc) ->
Expand Down Expand Up @@ -404,18 +446,35 @@ variable_in_fun_clause_arguments(Variable, {clause, {_, _}, Arguments, _, _}) ->
length(find_variable_occurrences(Variable, Arguments)) > 0.

find_function(FileSyntaxTree, Function, Arity) ->
Fun = fun (SyntaxTree) ->
Fun = fun (SyntaxTree, _File) ->
case SyntaxTree of
{function, _Position, FoundFunction, FoundArity, _Clauses} when FoundFunction =:= Function andalso FoundArity =:= Arity ->
SyntaxTree;
_ ->
undefined
end
end,
find_in_file_syntax_tree(FileSyntaxTree, Fun).
{SyntaxTree, _File} = find_in_file_syntax_tree(FileSyntaxTree, Fun),
SyntaxTree.

find_module(FileSyntaxTree, Module) ->
case lists:keyfind(module, 3, FileSyntaxTree) of
{attribute, Position, module, Module} -> {attribute, Position, Module};
_ -> undefined
end.

find_record(FileSyntaxTree, Record) ->
Fun = fun (SyntaxTree, File) ->
case SyntaxTree of
{attribute, _, record, {Record, _}} -> SyntaxTree;
_ -> undefined
end
end,
find_in_file_syntax_tree(FileSyntaxTree, Fun).

find_record_field(_Field, [], _CurrentFile) ->
undefined;
find_record_field(Field, [{record_field, _, {atom, {Line, Column}, Field}} | _], CurrentFile) ->
{CurrentFile, Line, Column};
find_record_field(Field, [_ | Tail], CurrentFile) ->
find_record_field(Field, Tail, CurrentFile).
1 change: 1 addition & 0 deletions lib/lsp/erlangLspConnection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ export class ErlangLspConnection extends ErlangConnection {
}

public Quit() : void {
this.post("stop_server");
this.events_receiver.close();
}

Expand Down
15 changes: 12 additions & 3 deletions lib/lsp/lspserver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,12 +118,12 @@ connection.onExecuteCommand((cmdParams: ExecuteCommandParams): any => {

connection.onShutdown(() => {
    debugLog("connection.onShutDown");
    erlangLsp.Kill();
erlangLspConnection.Quit();
});

connection.onExit(() => {
    debugLog("connection.onExit");
    erlangLsp.Kill();
erlangLspConnection.Quit();
});

// The global settings, used when the `workspace/configuration` request is not supported by the client.
Expand Down Expand Up @@ -163,7 +163,16 @@ function getDocumentSettings(resource: string): Thenable<ErlangSettings> {
}

documents.onDidOpen(e => {
    validateTextDocument(e.document);
var validateWhenReady = function () {
if (erlangLspConnection.isConnected)
    validateTextDocument(e.document);
else {
setTimeout(function () {
validateWhenReady();
}, 100);
}
};
validateWhenReady();
});

documents.onDidClose(e => {
Expand Down

0 comments on commit 71190d4

Please sign in to comment.