mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 20: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"); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     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 })); | ||||
| } | ||||
|  |  | |||
|  | @ -343,10 +343,26 @@ Optional<GUI::AutocompleteProvider::ProjectLocation> ParserAutoComplete::find_de | |||
|         return {}; | ||||
|     } | ||||
|     auto decl = find_declaration_of(document, *node); | ||||
|     if (!decl) | ||||
|         return {}; | ||||
| 
 | ||||
|     if (decl) | ||||
|         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 | ||||
|  | @ -409,7 +425,7 @@ OwnPtr<ParserAutoComplete::DocumentData> ParserAutoComplete::create_document_dat | |||
|     auto document_data = make<DocumentData>(); | ||||
|     document_data->m_filename = move(filename); | ||||
|     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(); | ||||
| 
 | ||||
|     Preprocessor::Definitions all_definitions; | ||||
|  |  | |||
|  | @ -106,6 +106,7 @@ private: | |||
|     String document_path_from_include_path(const StringView& include_path) const; | ||||
|     void update_declared_symbols(const DocumentData&); | ||||
|     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); | ||||
| 
 | ||||
|  |  | |||
|  | @ -54,6 +54,7 @@ Parser::Parser(const StringView& program, const String& filename, Preprocessor:: | |||
|     } | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| void Parser::initialize_program_tokens(const StringView& program) | ||||
| { | ||||
|     Lexer lexer(program); | ||||
|  | @ -63,6 +64,7 @@ void Parser::initialize_program_tokens(const StringView& program) | |||
|         if (token.type() == Token::Type::Identifier) { | ||||
|             if (auto defined_value = m_definitions.find(text_of_token(token)); defined_value != m_definitions.end()) { | ||||
|                 add_tokens_for_preprocessor(token, defined_value->value); | ||||
|                 m_replaced_preprocessor_tokens.append({ token, defined_value->value }); | ||||
|                 continue; | ||||
|             } | ||||
|         } | ||||
|  |  | |||
|  | @ -56,6 +56,12 @@ public: | |||
|     Vector<String> errors() const { return m_errors; } | ||||
|     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: | ||||
|     enum class DeclarationType { | ||||
|         Function, | ||||
|  | @ -171,6 +177,8 @@ private: | |||
|     RefPtr<TranslationUnit> m_root_node; | ||||
|     NonnullRefPtrVector<ASTNode> m_nodes; | ||||
|     Vector<String> m_errors; | ||||
| 
 | ||||
|     Vector<TokenAndPreprocessorDefinition> m_replaced_preprocessor_tokens; | ||||
| }; | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -31,8 +31,9 @@ | |||
| #include <ctype.h> | ||||
| 
 | ||||
| namespace Cpp { | ||||
| Preprocessor::Preprocessor(const StringView& program) | ||||
|     : m_program(program) | ||||
| Preprocessor::Preprocessor(const String& filename, const StringView& program) | ||||
|     : m_filename(filename) | ||||
|     , m_program(program) | ||||
| { | ||||
|     m_lines = m_program.split_view('\n', true); | ||||
| } | ||||
|  | @ -107,6 +108,7 @@ void Preprocessor::handle_preprocessor_line(const StringView& line) | |||
|             consume_whitespace(); | ||||
| 
 | ||||
|             DefinedValue value; | ||||
|             value.filename = m_filename; | ||||
|             value.line = m_line_index; | ||||
| 
 | ||||
|             auto string_value = lexer.consume_all(); | ||||
|  |  | |||
|  | @ -26,6 +26,7 @@ | |||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <AK/FlyString.h> | ||||
| #include <AK/HashMap.h> | ||||
| #include <AK/Optional.h> | ||||
| #include <AK/String.h> | ||||
|  | @ -36,13 +37,14 @@ namespace Cpp { | |||
| class Preprocessor { | ||||
| 
 | ||||
| public: | ||||
|     explicit Preprocessor(const StringView&); | ||||
|     explicit Preprocessor(const String& filename, const StringView& program); | ||||
|     const String& process(); | ||||
|     const String& processed_text(); | ||||
|     Vector<StringView> included_paths() const { return m_included_paths; } | ||||
| 
 | ||||
|     struct DefinedValue { | ||||
|         Optional<StringView> value; | ||||
|         FlyString filename; | ||||
|         size_t line { 0 }; | ||||
|         size_t column { 0 }; | ||||
|     }; | ||||
|  | @ -54,6 +56,7 @@ private: | |||
|     void handle_preprocessor_line(const StringView&); | ||||
| 
 | ||||
|     Definitions m_definitions; | ||||
|     const String m_filename; | ||||
|     const StringView m_program; | ||||
|     StringBuilder m_builder; | ||||
|     Vector<StringView> m_lines; | ||||
|  |  | |||
|  | @ -35,6 +35,6 @@ int main(int, char**) | |||
|         exit(1); | ||||
|     } | ||||
|     auto content = file->read_all(); | ||||
|     Cpp::Preprocessor cpp(StringView { content }); | ||||
|     Cpp::Preprocessor cpp("other.h", StringView { content }); | ||||
|     dbgln("{}", cpp.process()); | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Itamar
						Itamar