dc8bcfa307d010e5d7499bb112a709f4a9aa37b0
[idea/community.git] / python / src / com / jetbrains / python / highlighting / PyHighlighter.java
1 // Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 package com.jetbrains.python.highlighting;
3
4 import com.intellij.lexer.LayeredLexer;
5 import com.intellij.lexer.Lexer;
6 import com.intellij.openapi.editor.HighlighterColors;
7 import com.intellij.openapi.editor.colors.TextAttributesKey;
8 import com.intellij.openapi.fileTypes.SyntaxHighlighterBase;
9 import com.intellij.psi.StringEscapesTokenTypes;
10 import com.intellij.psi.tree.IElementType;
11 import com.jetbrains.python.PyTokenTypes;
12 import com.jetbrains.python.PythonDialectsTokenSetProvider;
13 import com.jetbrains.python.lexer.PyFStringLiteralLexer;
14 import com.jetbrains.python.lexer.PyStringLiteralLexer;
15 import com.jetbrains.python.lexer.PythonHighlightingLexer;
16 import com.jetbrains.python.psi.LanguageLevel;
17 import org.jetbrains.annotations.NotNull;
18
19 import java.util.HashMap;
20 import java.util.Map;
21
22 import static com.intellij.openapi.editor.DefaultLanguageHighlighterColors.*;
23
24 /**
25  * Colors and lexer(s) needed for highlighting.
26  */
27 public class PyHighlighter extends SyntaxHighlighterBase {
28   private final Map<IElementType, TextAttributesKey> keys;
29   private final LanguageLevel myLanguageLevel;
30
31   @Override
32   @NotNull
33   public Lexer getHighlightingLexer() {
34     LayeredLexer ret = new LayeredLexer(createHighlightingLexer(myLanguageLevel));
35     ret.registerLayer(
36       new PyStringLiteralLexer(PyTokenTypes.SINGLE_QUOTED_STRING),
37       PyTokenTypes.SINGLE_QUOTED_STRING
38     );
39     ret.registerLayer(
40       new PyStringLiteralLexer(PyTokenTypes.SINGLE_QUOTED_UNICODE),
41       PyTokenTypes.SINGLE_QUOTED_UNICODE
42     );
43     ret.registerLayer(
44       new PyStringLiteralLexer(PyTokenTypes.TRIPLE_QUOTED_STRING),
45       PyTokenTypes.TRIPLE_QUOTED_STRING
46     );
47     ret.registerLayer(
48       new PyStringLiteralLexer(PyTokenTypes.TRIPLE_QUOTED_UNICODE),
49       PyTokenTypes.TRIPLE_QUOTED_UNICODE
50     );
51     ret.registerLayer(
52       new PyFStringLiteralLexer(PyTokenTypes.FSTRING_TEXT),
53       PyTokenTypes.FSTRING_TEXT
54     );
55     ret.registerLayer(
56       new PyFStringLiteralLexer(PyTokenTypes.FSTRING_RAW_TEXT),
57       PyTokenTypes.FSTRING_RAW_TEXT
58     );
59
60     return ret;
61   }
62
63   protected PythonHighlightingLexer createHighlightingLexer(LanguageLevel languageLevel) {
64     return new PythonHighlightingLexer(myLanguageLevel);
65   }
66
67   public static final TextAttributesKey PY_KEYWORD = TextAttributesKey.createTextAttributesKey("PY.KEYWORD", KEYWORD);
68
69   public static final TextAttributesKey PY_BYTE_STRING = TextAttributesKey.createTextAttributesKey("PY.STRING.B", STRING);
70   public static final TextAttributesKey PY_UNICODE_STRING = TextAttributesKey.createTextAttributesKey("PY.STRING.U", STRING);
71   public static final TextAttributesKey PY_NUMBER = TextAttributesKey.createTextAttributesKey("PY.NUMBER", NUMBER);
72
73   static final TextAttributesKey PY_OPERATION_SIGN = TextAttributesKey.createTextAttributesKey("PY.OPERATION_SIGN", OPERATION_SIGN);
74
75   static final TextAttributesKey PY_PARENTHS = TextAttributesKey.createTextAttributesKey("PY.PARENTHS", PARENTHESES);
76
77   static final TextAttributesKey PY_BRACKETS = TextAttributesKey.createTextAttributesKey("PY.BRACKETS", BRACKETS);
78
79   static final TextAttributesKey PY_BRACES = TextAttributesKey.createTextAttributesKey("PY.BRACES", BRACES);
80
81   static final TextAttributesKey PY_COMMA = TextAttributesKey.createTextAttributesKey("PY.COMMA", COMMA);
82
83   static final TextAttributesKey PY_DOT = TextAttributesKey.createTextAttributesKey("PY.DOT", DOT);
84
85   public static final TextAttributesKey PY_LINE_COMMENT = TextAttributesKey.createTextAttributesKey("PY.LINE_COMMENT", LINE_COMMENT);
86
87   public static final TextAttributesKey PY_DOC_COMMENT = TextAttributesKey.createTextAttributesKey("PY.DOC_COMMENT", DOC_COMMENT);
88
89   public static final TextAttributesKey PY_DOC_COMMENT_TAG = TextAttributesKey.createTextAttributesKey("PY.DOC_COMMENT_TAG", DOC_COMMENT_TAG);
90
91   public static final TextAttributesKey PY_DECORATOR = TextAttributesKey.createTextAttributesKey("PY.DECORATOR", IDENTIFIER);
92
93   public static final TextAttributesKey PY_CLASS_DEFINITION = TextAttributesKey.createTextAttributesKey("PY.CLASS_DEFINITION", CLASS_NAME);
94
95   public static final TextAttributesKey PY_FUNC_DEFINITION = TextAttributesKey.createTextAttributesKey("PY.FUNC_DEFINITION", FUNCTION_DECLARATION);
96
97   public static final TextAttributesKey PY_PREDEFINED_DEFINITION = TextAttributesKey.createTextAttributesKey("PY.PREDEFINED_DEFINITION", PREDEFINED_SYMBOL);
98
99   public static final TextAttributesKey PY_PREDEFINED_USAGE = TextAttributesKey.createTextAttributesKey("PY.PREDEFINED_USAGE", PREDEFINED_SYMBOL);
100
101   public static final TextAttributesKey PY_BUILTIN_NAME = TextAttributesKey.createTextAttributesKey("PY.BUILTIN_NAME", PREDEFINED_SYMBOL);
102
103   public static final TextAttributesKey PY_PARAMETER = TextAttributesKey.createTextAttributesKey("PY.PARAMETER", PARAMETER);
104   public static final TextAttributesKey PY_SELF_PARAMETER = TextAttributesKey.createTextAttributesKey( "PY.SELF_PARAMETER", PARAMETER);
105
106   public static final TextAttributesKey PY_KEYWORD_ARGUMENT = TextAttributesKey.createTextAttributesKey("PY.KEYWORD_ARGUMENT", PARAMETER);
107
108   public static final TextAttributesKey PY_FUNCTION_CALL = TextAttributesKey.createTextAttributesKey("PY.FUNCTION_CALL", FUNCTION_CALL);
109   public static final TextAttributesKey PY_METHOD_CALL = TextAttributesKey.createTextAttributesKey("PY.METHOD_CALL", PY_FUNCTION_CALL);
110
111   public static final TextAttributesKey PY_ANNOTATION = TextAttributesKey.createTextAttributesKey("PY.ANNOTATION", IDENTIFIER);
112
113   public static final TextAttributesKey PY_VALID_STRING_ESCAPE = TextAttributesKey.createTextAttributesKey("PY.VALID_STRING_ESCAPE", VALID_STRING_ESCAPE);
114
115   public static final TextAttributesKey PY_INVALID_STRING_ESCAPE = TextAttributesKey.createTextAttributesKey("PY.INVALID_STRING_ESCAPE", INVALID_STRING_ESCAPE);
116   
117   public static final TextAttributesKey PY_FSTRING_FRAGMENT_BRACES = TextAttributesKey.createTextAttributesKey("PY.FSTRING_FRAGMENT_BRACES", VALID_STRING_ESCAPE);
118   public static final TextAttributesKey PY_FSTRING_FRAGMENT_COLON = TextAttributesKey.createTextAttributesKey("PY.FSTRING_FRAGMENT_COLON", VALID_STRING_ESCAPE);
119   public static final TextAttributesKey PY_FSTRING_FRAGMENT_TYPE_CONVERSION = TextAttributesKey.createTextAttributesKey("PY.FSTRING_FRAGMENT_TYPE_CONVERSION", VALID_STRING_ESCAPE);
120
121   /**
122    * The 'heavy' constructor that initializes everything. PySyntaxHighlighterFactory caches such instances per level.
123    * @param languageLevel
124    */
125   public PyHighlighter(LanguageLevel languageLevel) {
126     myLanguageLevel = languageLevel;
127     keys = new HashMap<>();
128
129     fillMap(keys, PythonDialectsTokenSetProvider.getInstance().getKeywordTokens(), PY_KEYWORD);
130     fillMap(keys, PyTokenTypes.OPERATIONS, PY_OPERATION_SIGN);
131
132     keys.put(PyTokenTypes.INTEGER_LITERAL, PY_NUMBER);
133     keys.put(PyTokenTypes.FLOAT_LITERAL, PY_NUMBER);
134     keys.put(PyTokenTypes.IMAGINARY_LITERAL, PY_NUMBER);
135     keys.put(PyTokenTypes.SINGLE_QUOTED_STRING, PY_BYTE_STRING);
136     keys.put(PyTokenTypes.TRIPLE_QUOTED_STRING, PY_BYTE_STRING);
137     keys.put(PyTokenTypes.SINGLE_QUOTED_UNICODE, PY_UNICODE_STRING);
138     keys.put(PyTokenTypes.TRIPLE_QUOTED_UNICODE, PY_UNICODE_STRING);
139
140     keys.put(PyTokenTypes.FSTRING_START, PY_UNICODE_STRING);
141     keys.put(PyTokenTypes.FSTRING_END, PY_UNICODE_STRING);
142     keys.put(PyTokenTypes.FSTRING_TEXT, PY_UNICODE_STRING);
143     keys.put(PyTokenTypes.FSTRING_RAW_TEXT, PY_UNICODE_STRING);
144
145     keys.put(PyTokenTypes.FSTRING_FRAGMENT_TYPE_CONVERSION, PY_FSTRING_FRAGMENT_TYPE_CONVERSION);
146     keys.put(PyTokenTypes.FSTRING_FRAGMENT_FORMAT_START, PY_FSTRING_FRAGMENT_COLON);
147     keys.put(PyTokenTypes.FSTRING_FRAGMENT_START, PY_FSTRING_FRAGMENT_BRACES);
148     keys.put(PyTokenTypes.FSTRING_FRAGMENT_END, PY_FSTRING_FRAGMENT_BRACES);
149
150     keys.put(PyTokenTypes.DOCSTRING, PY_DOC_COMMENT);
151
152     keys.put(PyTokenTypes.LPAR, PY_PARENTHS);
153     keys.put(PyTokenTypes.RPAR, PY_PARENTHS);
154
155     keys.put(PyTokenTypes.LBRACE, PY_BRACES);
156     keys.put(PyTokenTypes.RBRACE, PY_BRACES);
157
158     keys.put(PyTokenTypes.LBRACKET, PY_BRACKETS);
159     keys.put(PyTokenTypes.RBRACKET, PY_BRACKETS);
160
161     keys.put(PyTokenTypes.COMMA, PY_COMMA);
162     keys.put(PyTokenTypes.DOT, PY_DOT);
163
164     keys.put(PyTokenTypes.END_OF_LINE_COMMENT, PY_LINE_COMMENT);
165     keys.put(PyTokenTypes.BAD_CHARACTER, HighlighterColors.BAD_CHARACTER);
166
167     keys.put(StringEscapesTokenTypes.VALID_STRING_ESCAPE_TOKEN, PY_VALID_STRING_ESCAPE);
168     keys.put(StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN, PY_INVALID_STRING_ESCAPE);
169     keys.put(StringEscapesTokenTypes.INVALID_UNICODE_ESCAPE_TOKEN, PY_INVALID_STRING_ESCAPE);
170   }
171
172   @Override
173   public TextAttributesKey @NotNull [] getTokenHighlights(IElementType tokenType) {
174     return pack(keys.get(tokenType));
175   }
176 }