| 
									
										
										
										
											2020-03-14 00:07:44 +02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright (c) 2020, the SerenityOS developers. | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Redistribution and use in source and binary forms, with or without | 
					
						
							|  |  |  |  * modification, are permitted provided that the following conditions are met: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * 1. Redistributions of source code must retain the above copyright notice, this | 
					
						
							|  |  |  |  *    list of conditions and the following disclaimer. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * 2. Redistributions in binary form must reproduce the above copyright notice, | 
					
						
							|  |  |  |  *    this list of conditions and the following disclaimer in the documentation | 
					
						
							|  |  |  |  *    and/or other materials provided with the distribution. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | 
					
						
							|  |  |  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 
					
						
							|  |  |  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 
					
						
							|  |  |  |  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | 
					
						
							|  |  |  |  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 
					
						
							|  |  |  |  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | 
					
						
							|  |  |  |  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | 
					
						
							|  |  |  |  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | 
					
						
							|  |  |  |  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
					
						
							|  |  |  |  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-16 15:51:56 +01:00
										 |  |  | #include <AK/Debug.h>
 | 
					
						
							| 
									
										
										
										
											2020-09-28 16:21:25 +03:00
										 |  |  | #include <LibCpp/Lexer.h>
 | 
					
						
							| 
									
										
										
										
											2021-02-07 14:40:36 +01:00
										 |  |  | #include <LibCpp/SyntaxHighlighter.h>
 | 
					
						
							| 
									
										
										
										
											2020-02-07 20:07:15 +01:00
										 |  |  | #include <LibGUI/TextEditor.h>
 | 
					
						
							| 
									
										
										
										
											2020-02-15 00:24:14 +01:00
										 |  |  | #include <LibGfx/Font.h>
 | 
					
						
							| 
									
										
										
										
											2020-03-16 01:05:06 +02:00
										 |  |  | #include <LibGfx/Palette.h>
 | 
					
						
							| 
									
										
										
										
											2020-02-07 20:07:15 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-07 14:40:36 +01:00
										 |  |  | namespace Cpp { | 
					
						
							| 
									
										
										
										
											2020-02-07 20:07:15 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-07 15:15:10 +01:00
										 |  |  | static Syntax::TextStyle style_for_token_type(const Gfx::Palette& palette, Cpp::Token::Type type) | 
					
						
							| 
									
										
										
										
											2020-02-07 20:07:15 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     switch (type) { | 
					
						
							| 
									
										
										
										
											2020-09-28 16:21:25 +03:00
										 |  |  |     case Cpp::Token::Type::Keyword: | 
					
						
							| 
									
										
										
										
											2020-12-28 15:51:43 +01:00
										 |  |  |         return { palette.syntax_keyword(), true }; | 
					
						
							| 
									
										
										
										
											2020-09-28 16:21:25 +03:00
										 |  |  |     case Cpp::Token::Type::KnownType: | 
					
						
							| 
									
										
										
										
											2020-12-28 15:51:43 +01:00
										 |  |  |         return { palette.syntax_type(), true }; | 
					
						
							| 
									
										
										
										
											2020-09-28 16:21:25 +03:00
										 |  |  |     case Cpp::Token::Type::Identifier: | 
					
						
							| 
									
										
										
										
											2020-12-28 15:51:43 +01:00
										 |  |  |         return { palette.syntax_identifier(), false }; | 
					
						
							| 
									
										
										
										
											2020-09-28 16:21:25 +03:00
										 |  |  |     case Cpp::Token::Type::DoubleQuotedString: | 
					
						
							|  |  |  |     case Cpp::Token::Type::SingleQuotedString: | 
					
						
							|  |  |  |     case Cpp::Token::Type::RawString: | 
					
						
							| 
									
										
										
										
											2020-12-28 15:51:43 +01:00
										 |  |  |         return { palette.syntax_string(), false }; | 
					
						
							| 
									
										
										
										
											2020-09-28 16:21:25 +03:00
										 |  |  |     case Cpp::Token::Type::Integer: | 
					
						
							|  |  |  |     case Cpp::Token::Type::Float: | 
					
						
							| 
									
										
										
										
											2020-12-28 15:51:43 +01:00
										 |  |  |         return { palette.syntax_number(), false }; | 
					
						
							| 
									
										
										
										
											2020-09-28 16:21:25 +03:00
										 |  |  |     case Cpp::Token::Type::IncludePath: | 
					
						
							| 
									
										
										
										
											2020-12-28 15:51:43 +01:00
										 |  |  |         return { palette.syntax_preprocessor_value(), false }; | 
					
						
							| 
									
										
										
										
											2020-09-28 16:21:25 +03:00
										 |  |  |     case Cpp::Token::Type::EscapeSequence: | 
					
						
							| 
									
										
										
										
											2020-12-28 15:51:43 +01:00
										 |  |  |         return { palette.syntax_keyword(), true }; | 
					
						
							| 
									
										
										
										
											2020-09-28 16:21:25 +03:00
										 |  |  |     case Cpp::Token::Type::PreprocessorStatement: | 
					
						
							|  |  |  |     case Cpp::Token::Type::IncludeStatement: | 
					
						
							| 
									
										
										
										
											2020-12-28 15:51:43 +01:00
										 |  |  |         return { palette.syntax_preprocessor_statement(), false }; | 
					
						
							| 
									
										
										
										
											2020-09-28 16:21:25 +03:00
										 |  |  |     case Cpp::Token::Type::Comment: | 
					
						
							| 
									
										
										
										
											2020-12-28 15:51:43 +01:00
										 |  |  |         return { palette.syntax_comment(), false }; | 
					
						
							| 
									
										
										
										
											2020-02-07 20:07:15 +01:00
										 |  |  |     default: | 
					
						
							| 
									
										
										
										
											2020-12-28 15:51:43 +01:00
										 |  |  |         return { palette.base_text(), false }; | 
					
						
							| 
									
										
										
										
											2020-02-07 20:07:15 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-07 14:40:36 +01:00
										 |  |  | bool SyntaxHighlighter::is_identifier(void* token) const | 
					
						
							| 
									
										
										
										
											2020-03-12 17:23:54 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-28 16:21:25 +03:00
										 |  |  |     auto cpp_token = static_cast<Cpp::Token::Type>(reinterpret_cast<size_t>(token)); | 
					
						
							|  |  |  |     return cpp_token == Cpp::Token::Type::Identifier; | 
					
						
							| 
									
										
										
										
											2020-03-12 17:23:54 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-07 14:40:36 +01:00
										 |  |  | bool SyntaxHighlighter::is_navigatable(void* token) const | 
					
						
							| 
									
										
										
										
											2020-03-12 17:23:54 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-28 16:21:25 +03:00
										 |  |  |     auto cpp_token = static_cast<Cpp::Token::Type>(reinterpret_cast<size_t>(token)); | 
					
						
							|  |  |  |     return cpp_token == Cpp::Token::Type::IncludePath; | 
					
						
							| 
									
										
										
										
											2020-03-12 17:23:54 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-07 14:40:36 +01:00
										 |  |  | void SyntaxHighlighter::rehighlight(Gfx::Palette palette) | 
					
						
							| 
									
										
										
										
											2020-02-07 20:07:15 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-02-07 16:56:02 +01:00
										 |  |  |     auto text = m_client->get_text(); | 
					
						
							| 
									
										
										
										
											2020-09-28 16:21:25 +03:00
										 |  |  |     Cpp::Lexer lexer(text); | 
					
						
							| 
									
										
										
										
											2020-02-07 20:07:15 +01:00
										 |  |  |     auto tokens = lexer.lex(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Vector<GUI::TextDocumentSpan> spans; | 
					
						
							|  |  |  |     for (auto& token : tokens) { | 
					
						
							| 
									
										
										
										
											2021-02-07 15:33:24 +03:30
										 |  |  |         dbgln_if(SYNTAX_HIGHLIGHTING_DEBUG, "{} @ {}:{} - {}:{}", token.to_string(), token.m_start.line, token.m_start.column, token.m_end.line, token.m_end.column); | 
					
						
							| 
									
										
										
										
											2020-02-07 20:07:15 +01:00
										 |  |  |         GUI::TextDocumentSpan span; | 
					
						
							|  |  |  |         span.range.set_start({ token.m_start.line, token.m_start.column }); | 
					
						
							|  |  |  |         span.range.set_end({ token.m_end.line, token.m_end.column }); | 
					
						
							| 
									
										
										
										
											2020-03-16 01:05:06 +02:00
										 |  |  |         auto style = style_for_token_type(palette, token.m_type); | 
					
						
							| 
									
										
										
										
											2021-01-02 20:31:45 +01:00
										 |  |  |         span.attributes.color = style.color; | 
					
						
							|  |  |  |         span.attributes.bold = style.bold; | 
					
						
							| 
									
										
										
										
											2020-09-28 16:21:25 +03:00
										 |  |  |         span.is_skippable = token.m_type == Cpp::Token::Type::Whitespace; | 
					
						
							| 
									
										
										
										
											2020-03-12 16:36:25 +02:00
										 |  |  |         span.data = reinterpret_cast<void*>(token.m_type); | 
					
						
							| 
									
										
										
										
											2020-02-07 20:07:15 +01:00
										 |  |  |         spans.append(span); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-02-07 16:56:02 +01:00
										 |  |  |     m_client->do_set_spans(move(spans)); | 
					
						
							| 
									
										
										
										
											2020-02-07 20:07:15 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     m_has_brace_buddies = false; | 
					
						
							|  |  |  |     highlight_matching_token_pair(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-07 16:56:02 +01:00
										 |  |  |     m_client->do_update(); | 
					
						
							| 
									
										
										
										
											2020-02-07 20:07:15 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-07 14:40:36 +01:00
										 |  |  | Vector<SyntaxHighlighter::MatchingTokenPair> SyntaxHighlighter::matching_token_pairs() const | 
					
						
							| 
									
										
										
										
											2020-02-07 20:07:15 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-03-13 00:51:02 +02:00
										 |  |  |     static Vector<SyntaxHighlighter::MatchingTokenPair> pairs; | 
					
						
							|  |  |  |     if (pairs.is_empty()) { | 
					
						
							| 
									
										
										
										
											2020-09-28 16:21:25 +03:00
										 |  |  |         pairs.append({ reinterpret_cast<void*>(Cpp::Token::Type::LeftCurly), reinterpret_cast<void*>(Cpp::Token::Type::RightCurly) }); | 
					
						
							|  |  |  |         pairs.append({ reinterpret_cast<void*>(Cpp::Token::Type::LeftParen), reinterpret_cast<void*>(Cpp::Token::Type::RightParen) }); | 
					
						
							|  |  |  |         pairs.append({ reinterpret_cast<void*>(Cpp::Token::Type::LeftBracket), reinterpret_cast<void*>(Cpp::Token::Type::RightBracket) }); | 
					
						
							| 
									
										
										
										
											2020-02-07 20:07:15 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-03-13 00:51:02 +02:00
										 |  |  |     return pairs; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-07 14:40:36 +01:00
										 |  |  | bool SyntaxHighlighter::token_types_equal(void* token1, void* token2) const | 
					
						
							| 
									
										
										
										
											2020-03-13 00:51:02 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-28 16:21:25 +03:00
										 |  |  |     return static_cast<Cpp::Token::Type>(reinterpret_cast<size_t>(token1)) == static_cast<Cpp::Token::Type>(reinterpret_cast<size_t>(token2)); | 
					
						
							| 
									
										
										
										
											2020-02-07 20:07:15 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-07 14:40:36 +01:00
										 |  |  | SyntaxHighlighter::~SyntaxHighlighter() | 
					
						
							| 
									
										
										
										
											2020-02-07 20:07:15 +01:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |