Skip to content

Commit

Permalink
Add tentative scope-aware completion capability
Browse files Browse the repository at this point in the history
Add the server capability and the required helper functions.
The proposed elements should be from within the designated
scope or (if no scope is selected) from the edited file.

The returned symbol should be declared before the cursor.
  • Loading branch information
suzizecat committed Dec 29, 2024
1 parent 39f6c0f commit 2af32df
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 2 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
# 0.3.0-dev

## Added

- Added scope-aware completion.

## Changed

- Full rework of the indexer
- Full rework of the indexer.

# 0.2.1

Expand Down
7 changes: 7 additions & 0 deletions indexer/include/index_scope.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,13 @@ namespace diplomat::index
*/
IndexSymbol* resolve_symbol(const std::string_view& path);

/**
* @brief Get the visible symbols object from the current scope.
* This represent all symbols declared here and all symbols declared in parents.
* @return std::vector<const IndexSymbol*> the set of found symbols.
*/
std::vector<const IndexSymbol*> get_visible_symbols() const;

/**
* @brief Get the scope for position object
*
Expand Down
1 change: 1 addition & 0 deletions indexer/include/index_symbols.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ namespace diplomat::index
};

inline const std::optional<IndexRange>& get_source() const {return _source_range;};
inline const std::optional<IndexLocation> get_source_location() const {return _source_range ? _source_range->start : std::optional<IndexLocation>();};
inline const std::string& get_name() const {return _name;};
inline const std::unordered_set<IndexRange>& get_references() const {return _references_locations;};

Expand Down
18 changes: 18 additions & 0 deletions indexer/index_scope.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,24 @@ namespace diplomat::index {

}

std::vector<const IndexSymbol*> IndexScope::get_visible_symbols() const
{
const IndexScope* lu_scope = this;
std::vector<const IndexSymbol*> ret;
do {
for(auto& symb : std::views::values(lu_scope->_content))
{
ret.push_back(symb);
}

if(lu_scope->get_parent_access())
lu_scope = lu_scope->_parent;

} while (lu_scope->get_parent_access());

return ret;
}

IndexScope *IndexScope::get_scope_for_location(const IndexLocation &loc, bool deep)
{
if(deep)
Expand Down
2 changes: 2 additions & 0 deletions lsp-server/diplomat/include/diplomat_lsp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,11 @@ class DiplomatLSP : public slsp::BaseLSP

std::shared_ptr<DiplomatLSP> _this_shared;


void _h_didChangeWorkspaceFolders(json params);
void _h_didSaveTextDocument(json params);
void _h_didOpenTextDocument(json params);
json _h_completion(slsp::types::CompletionParams params);
json _h_formatting(json params);
json _h_gotoDefinition(json params);
json _h_references(json params);
Expand Down
5 changes: 5 additions & 0 deletions lsp-server/diplomat/src/diplomat_lsp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,16 @@ _project_file_tree_valid(false)
ServerCapabilities_workspace sc_ws;
sc_ws.workspaceFolders = ws;

CompletionOptions sc_completion;
sc_completion.resolveProvider = false;

capabilities.textDocumentSync = sync;
capabilities.workspace = sc_ws;
capabilities.definitionProvider = true;
capabilities.referencesProvider = true;
capabilities.documentFormattingProvider = true; // Can handle formatting options
capabilities.renameProvider = true;
capabilities.completionProvider = sc_completion;

_bind_methods();
}
Expand Down Expand Up @@ -165,6 +169,7 @@ void DiplomatLSP::_bind_methods()

bind_notification("textDocument/didOpen", LSP_MEMBER_BIND(DiplomatLSP, _h_didOpenTextDocument));
bind_notification("textDocument/didSave", LSP_MEMBER_BIND(DiplomatLSP, _h_didSaveTextDocument));
bind_request("textDocument/completion", LSP_MEMBER_BIND(DiplomatLSP, _h_completion));
bind_request("textDocument/definition", LSP_MEMBER_BIND(DiplomatLSP, _h_gotoDefinition));
bind_request("textDocument/formatting", LSP_MEMBER_BIND(DiplomatLSP, _h_formatting));
bind_request("textDocument/references", LSP_MEMBER_BIND(DiplomatLSP, _h_references));
Expand Down
40 changes: 39 additions & 1 deletion lsp-server/diplomat/src/diplomat_lsp_binds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,45 @@ void DiplomatLSP::_h_didOpenTextDocument(json _)
{
DidOpenTextDocumentParams params = _;
_save_client_uri(params.textDocument.uri);
}
}

json DiplomatLSP::_h_completion(slsp::types::CompletionParams params)
{
CompletionList result;
result.isIncomplete = false;
_assert_index(true);

di::IndexLocation trigger_location = _lsp_to_index_location(params);
di::IndexScope* trigger_scope = _index->get_scope_by_position(trigger_location);

if(trigger_scope)
{
for(const di::IndexSymbol* symb : trigger_scope->get_visible_symbols() )
{
if(symb->get_source_location().value_or(trigger_location) > trigger_location)
continue;

CompletionItem record;
record.label = symb->get_name();
result.items.push_back(record);
}
}
else
{
// Propose symbols from the whole file.
for(const auto& symb : _index->get_file(trigger_location.file)->get_symbols() )
{
if(symb->get_source_location().value_or(trigger_location) > trigger_location)
continue;

CompletionItem record;
record.label = symb->get_name();
result.items.push_back(record);
}
}

return result;
}

json DiplomatLSP::_h_formatting(json _)
{
Expand Down

0 comments on commit 2af32df

Please sign in to comment.