2020-03-14 00:07:44 +02:00
/*
2022-02-26 10:30:59 -07:00
* Copyright ( c ) 2020 - 2022 , the SerenityOS developers .
2020-03-14 00:07:44 +02:00
*
2021-04-22 01:24:48 -07:00
* SPDX - License - Identifier : BSD - 2 - Clause
2020-03-14 00:07:44 +02:00
*/
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>
2022-04-09 09:28:38 +02:00
# include <LibGfx/Font/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-06-03 23:17:34 +02:00
static Syntax : : TextStyle style_for_token_type ( Gfx : : Palette const & 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-06-07 12:03:09 +04:30
bool SyntaxHighlighter : : is_identifier ( u64 token ) const
2020-03-12 17:23:54 +02:00
{
2021-06-07 12:03:09 +04:30
auto cpp_token = static_cast < Cpp : : Token : : Type > ( token ) ;
2020-09-28 16:21:25 +03:00
return cpp_token = = Cpp : : Token : : Type : : Identifier ;
2020-03-12 17:23:54 +02:00
}
2021-06-07 12:03:09 +04:30
bool SyntaxHighlighter : : is_navigatable ( u64 token ) const
2020-03-12 17:23:54 +02:00
{
2021-06-07 12:03:09 +04:30
auto cpp_token = static_cast < Cpp : : Token : : Type > ( token ) ;
2020-09-28 16:21:25 +03:00
return cpp_token = = Cpp : : Token : : Type : : IncludePath ;
2020-03-12 17:23:54 +02:00
}
2021-06-03 23:17:34 +02:00
void SyntaxHighlighter : : rehighlight ( Palette const & 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
2023-03-03 12:53:08 +00:00
Vector < Token > folding_region_start_tokens ;
Vector < GUI : : TextDocumentFoldingRegion > folding_regions ;
2020-02-07 20:07:15 +01:00
Vector < GUI : : TextDocumentSpan > spans ;
2021-08-21 16:48:21 +03:00
lexer . lex_iterable ( [ & ] ( auto token ) {
2021-06-04 21:12:19 +02:00
// FIXME: The +1 for the token end column is a quick hack due to not wanting to modify the lexer (which is also used by the parser). Maybe there's a better way to do this.
2022-12-06 01:12:49 +00:00
dbgln_if ( SYNTAX_HIGHLIGHTING_DEBUG , " {} @ {}:{} - {}:{} " , token . type_as_deprecated_string ( ) , token . start ( ) . line , token . start ( ) . column , token . end ( ) . line , token . end ( ) . column + 1 ) ;
2020-02-07 20:07:15 +01:00
GUI : : TextDocumentSpan span ;
2021-03-12 12:46:40 +02:00
span . range . set_start ( { token . start ( ) . line , token . start ( ) . column } ) ;
2021-06-04 21:12:19 +02:00
span . range . set_end ( { token . end ( ) . line , token . end ( ) . column + 1 } ) ;
2021-03-12 12:46:40 +02:00
auto style = style_for_token_type ( palette , token . type ( ) ) ;
2021-01-02 20:31:45 +01:00
span . attributes . color = style . color ;
span . attributes . bold = style . bold ;
2021-03-12 12:46:40 +02:00
span . is_skippable = token . type ( ) = = Cpp : : Token : : Type : : Whitespace ;
2021-06-07 12:03:09 +04:30
span . data = static_cast < u64 > ( token . type ( ) ) ;
2020-02-07 20:07:15 +01:00
spans . append ( span ) ;
2023-03-03 12:53:08 +00:00
if ( token . type ( ) = = Token : : Type : : LeftCurly ) {
folding_region_start_tokens . append ( token ) ;
} else if ( token . type ( ) = = Token : : Type : : RightCurly ) {
if ( ! folding_region_start_tokens . is_empty ( ) ) {
auto start_token = folding_region_start_tokens . take_last ( ) ;
GUI : : TextDocumentFoldingRegion folding_region ;
folding_region . range . set_start ( { start_token . end ( ) . line , start_token . end ( ) . column } ) ;
folding_region . range . set_end ( { token . start ( ) . line , token . start ( ) . column } ) ;
folding_regions . append ( move ( folding_region ) ) ;
}
}
2021-08-21 16:48:21 +03:00
} ) ;
2021-02-07 16:56:02 +01:00
m_client - > do_set_spans ( move ( spans ) ) ;
2023-03-03 12:53:08 +00:00
m_client - > do_set_folding_regions ( move ( folding_regions ) ) ;
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-06-07 12:03:09 +04:30
Vector < SyntaxHighlighter : : MatchingTokenPair > SyntaxHighlighter : : matching_token_pairs_impl ( ) 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 ( ) ) {
2021-06-07 12:03:09 +04:30
pairs . append ( { static_cast < u64 > ( Cpp : : Token : : Type : : LeftCurly ) , static_cast < u64 > ( Cpp : : Token : : Type : : RightCurly ) } ) ;
pairs . append ( { static_cast < u64 > ( Cpp : : Token : : Type : : LeftParen ) , static_cast < u64 > ( Cpp : : Token : : Type : : RightParen ) } ) ;
pairs . append ( { static_cast < u64 > ( Cpp : : Token : : Type : : LeftBracket ) , static_cast < u64 > ( Cpp : : Token : : Type : : RightBracket ) } ) ;
2020-02-07 20:07:15 +01:00
}
2020-03-13 00:51:02 +02:00
return pairs ;
}
2021-06-07 12:03:09 +04:30
bool SyntaxHighlighter : : token_types_equal ( u64 token1 , u64 token2 ) const
2020-03-13 00:51:02 +02:00
{
2021-06-07 12:03:09 +04:30
return static_cast < Cpp : : Token : : Type > ( token1 ) = = static_cast < Cpp : : Token : : Type > ( token2 ) ;
2020-02-07 20:07:15 +01:00
}
}