mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 22:07:34 +00:00
LanguageServers/Cpp: Support jumping to declaration of preprocessor
.. definitions.
This commit is contained in:
parent
7bf6eca9d8
commit
8688259ed9
8 changed files with 43 additions and 10 deletions
|
@ -135,6 +135,7 @@ void ClientConnection::handle(const Messages::LanguageServer::FindDeclaration& m
|
||||||
dbgln("could not find declaration");
|
dbgln("could not find declaration");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dbgln_if(LANGUAGE_SERVER_DEBUG, "declaration location: {} {}:{}", location.value().file, location.value().line, location.value().column);
|
dbgln_if(LANGUAGE_SERVER_DEBUG, "declaration location: {} {}:{}", location.value().file, location.value().line, location.value().column);
|
||||||
post_message(Messages::LanguageClient::DeclarationLocation(GUI::AutocompleteProvider::ProjectLocation { location.value().file, location.value().line, location.value().column }));
|
post_message(Messages::LanguageClient::DeclarationLocation(GUI::AutocompleteProvider::ProjectLocation { location.value().file, location.value().line, location.value().column }));
|
||||||
}
|
}
|
||||||
|
|
|
@ -343,10 +343,26 @@ Optional<GUI::AutocompleteProvider::ProjectLocation> ParserAutoComplete::find_de
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
auto decl = find_declaration_of(document, *node);
|
auto decl = find_declaration_of(document, *node);
|
||||||
if (!decl)
|
if (decl)
|
||||||
return {};
|
return GUI::AutocompleteProvider::ProjectLocation { decl->filename(), decl->start().line, decl->start().column };
|
||||||
|
|
||||||
return GUI::AutocompleteProvider::ProjectLocation { decl->filename(), decl->start().line, decl->start().column };
|
return find_preprocessor_definition(document, identifier_position);
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<GUI::AutocompleteProvider::ProjectLocation> ParserAutoComplete::find_preprocessor_definition(const DocumentData& document, const GUI::TextPosition& text_position)
|
||||||
|
{
|
||||||
|
Position cpp_position { text_position.line(), text_position.column() };
|
||||||
|
|
||||||
|
// Search for a replaced preprocessor token that intersects with text_position
|
||||||
|
for (auto& replaced_token : document.parser().replaced_preprocessor_tokens()) {
|
||||||
|
if (replaced_token.token.start() > cpp_position)
|
||||||
|
continue;
|
||||||
|
if (replaced_token.token.end() < cpp_position)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return GUI::AutocompleteProvider::ProjectLocation { replaced_token.preprocessor_value.filename, replaced_token.preprocessor_value.line, replaced_token.preprocessor_value.column };
|
||||||
|
}
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<Declaration> ParserAutoComplete::find_declaration_of(const DocumentData& document_data, const ASTNode& node) const
|
RefPtr<Declaration> ParserAutoComplete::find_declaration_of(const DocumentData& document_data, const ASTNode& node) const
|
||||||
|
@ -409,7 +425,7 @@ OwnPtr<ParserAutoComplete::DocumentData> ParserAutoComplete::create_document_dat
|
||||||
auto document_data = make<DocumentData>();
|
auto document_data = make<DocumentData>();
|
||||||
document_data->m_filename = move(filename);
|
document_data->m_filename = move(filename);
|
||||||
document_data->m_text = move(text);
|
document_data->m_text = move(text);
|
||||||
document_data->m_preprocessor = make<Preprocessor>(document_data->text());
|
document_data->m_preprocessor = make<Preprocessor>(document_data->m_filename, document_data->text());
|
||||||
document_data->preprocessor().process();
|
document_data->preprocessor().process();
|
||||||
|
|
||||||
Preprocessor::Definitions all_definitions;
|
Preprocessor::Definitions all_definitions;
|
||||||
|
|
|
@ -106,6 +106,7 @@ private:
|
||||||
String document_path_from_include_path(const StringView& include_path) const;
|
String document_path_from_include_path(const StringView& include_path) const;
|
||||||
void update_declared_symbols(const DocumentData&);
|
void update_declared_symbols(const DocumentData&);
|
||||||
GUI::AutocompleteProvider::DeclarationType type_of_declaration(const Declaration&);
|
GUI::AutocompleteProvider::DeclarationType type_of_declaration(const Declaration&);
|
||||||
|
Optional<GUI::AutocompleteProvider::ProjectLocation> find_preprocessor_definition(const DocumentData&, const GUI::TextPosition&);
|
||||||
|
|
||||||
OwnPtr<DocumentData> create_document_data(String&& text, const String& filename);
|
OwnPtr<DocumentData> create_document_data(String&& text, const String& filename);
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,7 @@ Parser::Parser(const StringView& program, const String& filename, Preprocessor::
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Parser::initialize_program_tokens(const StringView& program)
|
void Parser::initialize_program_tokens(const StringView& program)
|
||||||
{
|
{
|
||||||
Lexer lexer(program);
|
Lexer lexer(program);
|
||||||
|
@ -63,6 +64,7 @@ void Parser::initialize_program_tokens(const StringView& program)
|
||||||
if (token.type() == Token::Type::Identifier) {
|
if (token.type() == Token::Type::Identifier) {
|
||||||
if (auto defined_value = m_definitions.find(text_of_token(token)); defined_value != m_definitions.end()) {
|
if (auto defined_value = m_definitions.find(text_of_token(token)); defined_value != m_definitions.end()) {
|
||||||
add_tokens_for_preprocessor(token, defined_value->value);
|
add_tokens_for_preprocessor(token, defined_value->value);
|
||||||
|
m_replaced_preprocessor_tokens.append({ token, defined_value->value });
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,12 @@ public:
|
||||||
Vector<String> errors() const { return m_errors; }
|
Vector<String> errors() const { return m_errors; }
|
||||||
const Preprocessor::Definitions& definitions() const { return m_definitions; }
|
const Preprocessor::Definitions& definitions() const { return m_definitions; }
|
||||||
|
|
||||||
|
struct TokenAndPreprocessorDefinition {
|
||||||
|
Token token;
|
||||||
|
Preprocessor::DefinedValue preprocessor_value;
|
||||||
|
};
|
||||||
|
const Vector<TokenAndPreprocessorDefinition>& replaced_preprocessor_tokens() const { return m_replaced_preprocessor_tokens; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class DeclarationType {
|
enum class DeclarationType {
|
||||||
Function,
|
Function,
|
||||||
|
@ -171,6 +177,8 @@ private:
|
||||||
RefPtr<TranslationUnit> m_root_node;
|
RefPtr<TranslationUnit> m_root_node;
|
||||||
NonnullRefPtrVector<ASTNode> m_nodes;
|
NonnullRefPtrVector<ASTNode> m_nodes;
|
||||||
Vector<String> m_errors;
|
Vector<String> m_errors;
|
||||||
|
|
||||||
|
Vector<TokenAndPreprocessorDefinition> m_replaced_preprocessor_tokens;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,8 +31,9 @@
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
namespace Cpp {
|
namespace Cpp {
|
||||||
Preprocessor::Preprocessor(const StringView& program)
|
Preprocessor::Preprocessor(const String& filename, const StringView& program)
|
||||||
: m_program(program)
|
: m_filename(filename)
|
||||||
|
, m_program(program)
|
||||||
{
|
{
|
||||||
m_lines = m_program.split_view('\n', true);
|
m_lines = m_program.split_view('\n', true);
|
||||||
}
|
}
|
||||||
|
@ -107,6 +108,7 @@ void Preprocessor::handle_preprocessor_line(const StringView& line)
|
||||||
consume_whitespace();
|
consume_whitespace();
|
||||||
|
|
||||||
DefinedValue value;
|
DefinedValue value;
|
||||||
|
value.filename = m_filename;
|
||||||
value.line = m_line_index;
|
value.line = m_line_index;
|
||||||
|
|
||||||
auto string_value = lexer.consume_all();
|
auto string_value = lexer.consume_all();
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/FlyString.h>
|
||||||
#include <AK/HashMap.h>
|
#include <AK/HashMap.h>
|
||||||
#include <AK/Optional.h>
|
#include <AK/Optional.h>
|
||||||
#include <AK/String.h>
|
#include <AK/String.h>
|
||||||
|
@ -36,15 +37,16 @@ namespace Cpp {
|
||||||
class Preprocessor {
|
class Preprocessor {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Preprocessor(const StringView&);
|
explicit Preprocessor(const String& filename, const StringView& program);
|
||||||
const String& process();
|
const String& process();
|
||||||
const String& processed_text();
|
const String& processed_text();
|
||||||
Vector<StringView> included_paths() const { return m_included_paths; }
|
Vector<StringView> included_paths() const { return m_included_paths; }
|
||||||
|
|
||||||
struct DefinedValue {
|
struct DefinedValue {
|
||||||
Optional<StringView> value;
|
Optional<StringView> value;
|
||||||
size_t line {0};
|
FlyString filename;
|
||||||
size_t column {0};
|
size_t line { 0 };
|
||||||
|
size_t column { 0 };
|
||||||
};
|
};
|
||||||
using Definitions = HashMap<StringView, DefinedValue>;
|
using Definitions = HashMap<StringView, DefinedValue>;
|
||||||
|
|
||||||
|
@ -54,6 +56,7 @@ private:
|
||||||
void handle_preprocessor_line(const StringView&);
|
void handle_preprocessor_line(const StringView&);
|
||||||
|
|
||||||
Definitions m_definitions;
|
Definitions m_definitions;
|
||||||
|
const String m_filename;
|
||||||
const StringView m_program;
|
const StringView m_program;
|
||||||
StringBuilder m_builder;
|
StringBuilder m_builder;
|
||||||
Vector<StringView> m_lines;
|
Vector<StringView> m_lines;
|
||||||
|
|
|
@ -35,6 +35,6 @@ int main(int, char**)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
auto content = file->read_all();
|
auto content = file->read_all();
|
||||||
Cpp::Preprocessor cpp(StringView { content });
|
Cpp::Preprocessor cpp("other.h", StringView { content });
|
||||||
dbgln("{}", cpp.process());
|
dbgln("{}", cpp.process());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue