mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 17:52:45 +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
	
	 Itamar
						Itamar