PY-20844 PY-20773 Warn about '#' signs and backslashes inside f-strings
[idea/community.git] / python / testSrc / com / jetbrains / python / PythonHighlightingTest.java
1 /*
2  * Copyright 2000-2016 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.jetbrains.python;
17
18 import com.intellij.openapi.editor.colors.EditorColorsManager;
19 import com.intellij.openapi.editor.colors.EditorColorsScheme;
20 import com.intellij.openapi.editor.colors.TextAttributesKey;
21 import com.intellij.openapi.editor.markup.EffectType;
22 import com.intellij.openapi.editor.markup.TextAttributes;
23 import com.jetbrains.python.documentation.PyDocumentationSettings;
24 import com.jetbrains.python.documentation.docstrings.DocStringFormat;
25 import com.jetbrains.python.fixtures.PyTestCase;
26 import com.jetbrains.python.psi.LanguageLevel;
27 import com.jetbrains.python.psi.impl.PythonLanguageLevelPusher;
28
29 import java.awt.*;
30
31 /**
32  * Test highlighting added by annotators.
33  *
34  * @author yole
35  */
36 public class PythonHighlightingTest extends PyTestCase {
37   private static final String TEST_PATH = "/highlighting/";
38
39   public void testBuiltins() {
40     EditorColorsManager manager = EditorColorsManager.getInstance();
41     EditorColorsScheme scheme = (EditorColorsScheme)manager.getGlobalScheme().clone();
42     manager.addColorsScheme(scheme);
43     EditorColorsManager.getInstance().setGlobalScheme(scheme);
44
45     TextAttributesKey xKey;
46     TextAttributes xAttributes;
47     
48     xKey = TextAttributesKey.find("PY.BUILTIN_NAME");
49     xAttributes = new TextAttributes(Color.green, Color.black, Color.white, EffectType.BOXED, Font.BOLD);
50     scheme.setAttributes(xKey, xAttributes);
51
52     xKey = TextAttributesKey.find("PY.PREDEFINED_USAGE");
53     xAttributes = new TextAttributes(Color.yellow, Color.black, Color.white, EffectType.BOXED, Font.BOLD);
54     scheme.setAttributes(xKey, xAttributes);
55
56     doTest();
57   }
58
59   public void testDeclarations() {
60     EditorColorsManager manager = EditorColorsManager.getInstance();
61     EditorColorsScheme scheme = (EditorColorsScheme)manager.getGlobalScheme().clone();
62     manager.addColorsScheme(scheme);
63     EditorColorsManager.getInstance().setGlobalScheme(scheme);
64
65     TextAttributesKey xKey = TextAttributesKey.find("PY.CLASS_DEFINITION");
66     TextAttributes xAttributes = new TextAttributes(Color.blue, Color.black, Color.white, EffectType.BOXED, Font.BOLD);
67     scheme.setAttributes(xKey, xAttributes);
68
69     xKey = TextAttributesKey.find("PY.FUNC_DEFINITION");
70     xAttributes = new TextAttributes(Color.red, Color.black, Color.white, EffectType.BOXED, Font.BOLD);
71     scheme.setAttributes(xKey, xAttributes);
72
73     xKey = TextAttributesKey.find("PY.PREDEFINED_DEFINITION");
74     xAttributes = new TextAttributes(Color.green, Color.black, Color.white, EffectType.BOXED, Font.BOLD);
75     scheme.setAttributes(xKey, xAttributes);
76
77     doTest();
78   }
79
80   public void testAssignmentTargets() {
81     setLanguageLevel(LanguageLevel.PYTHON26);
82     doTest(true, false);
83   }
84
85   public void testAssignmentTargetWith() {  // PY-7529
86     setLanguageLevel(LanguageLevel.PYTHON27);
87     doTest(true, false);
88   }
89
90   public void testAssignmentTargets3K() {
91     doTest(LanguageLevel.PYTHON30, true, false);    
92   }
93   
94   public void testBreakOutsideOfLoop() {
95     doTest(true, false);
96   }
97
98   public void testReturnOutsideOfFunction() {
99     doTest();
100   }
101
102   public void testContinueInFinallyBlock() {
103     doTest(false, false);
104   }
105
106   public void testReturnWithArgumentsInGenerator() {
107     doTest();
108   }
109
110   public void testYieldOutsideOfFunction() {
111     doTest(LanguageLevel.PYTHON27, true, true);
112   }
113
114   public void testYieldInDefaultValue() {
115     doTest(LanguageLevel.PYTHON34, true, false);
116   }
117
118   // PY-11663
119   public void testYieldInLambda() {
120     doTest();
121   }
122   
123   public void testImportStarAtTopLevel() {
124     doTest(true, false);
125   }
126
127   public void testMalformedStringUnterminated() {
128     doTest();
129   }
130
131   public void testMalformedStringEscaped() {
132     doTest(false, false);
133   }
134
135   /*
136   public void testStringEscapedOK() {
137     doTest();
138   }
139   */
140
141   public void testStringMixedSeparatorsOK() {   // PY-299
142     doTest();
143   }
144
145   public void testStringBytesLiteralOK() {
146     doTest(LanguageLevel.PYTHON26, true, true);
147   }
148
149   public void testArgumentList() {
150     doTest(true, false);
151   }
152
153   public void testRegularAfterVarArgs() {
154     doTest(LanguageLevel.PYTHON30, true, false);
155   }
156
157   public void testKeywordOnlyArguments() {
158     doTest(LanguageLevel.PYTHON30, true, false);
159   }
160
161   public void testMalformedStringTripleQuoteUnterminated() {
162     doTest();
163   }
164
165   public void testMixedTripleQuotes() {   // PY-2806
166     doTest();
167   }
168
169   public void testOddNumberOfQuotes() {  // PY-2802
170     doTest(true, false);
171   }
172
173   public void testEscapedBackslash() {  // PY-2994
174     doTest(true, false);
175   }
176
177   public void testMultipleEscapedBackslashes() {
178     doTest(true, false);
179   }
180
181   public void testUnsupportedFeaturesInPython3() {
182     doTest(LanguageLevel.PYTHON30, true, false);
183   }
184
185   // PY-6703
186   public void testUnicode33() {
187     doTest(LanguageLevel.PYTHON33, true, false);
188   }
189
190   // PY-6702
191   public void testYieldFromBefore33() {
192     doTest(LanguageLevel.PYTHON32, true, false);
193   }
194
195   public void testParenthesizedGenerator() {
196     doTest(false, false);
197   }
198
199   public void testStarInGenerator() {  // PY-10177
200     doTest(LanguageLevel.PYTHON33, false, false);
201   }
202
203   public void testStarArgs() {  // PY-6456
204     doTest(LanguageLevel.PYTHON32, true, false);
205   }
206
207   public void testDocstring() {  // PY-8025
208     PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(myFixture.getModule());
209     documentationSettings.setFormat(DocStringFormat.REST);
210     try {
211       doTest(false, true);
212     }
213     finally {
214       documentationSettings.setFormat(DocStringFormat.PLAIN);
215     }
216   }
217
218   public void testYieldInNestedFunction() {
219     // highlight func declaration first, lest we get an "Extra fragment highlighted" error.
220     EditorColorsManager manager = EditorColorsManager.getInstance();
221     EditorColorsScheme scheme = (EditorColorsScheme)manager.getGlobalScheme().clone();
222     manager.addColorsScheme(scheme);
223     EditorColorsManager.getInstance().setGlobalScheme(scheme);
224
225     TextAttributesKey xKey = TextAttributesKey.find("PY.FUNC_DEFINITION");
226     TextAttributes xAttributes = new TextAttributes(Color.red, Color.black, Color.white, EffectType.BOXED, Font.BOLD);
227     scheme.setAttributes(xKey, xAttributes);
228
229     doTest();
230   }
231
232   public void testAsync() {
233     doTest(LanguageLevel.PYTHON35, true, true);
234   }
235
236   public void testAwait() {
237     doTest(LanguageLevel.PYTHON35, true, true);
238   }
239
240   // PY-19679
241   public void testAwaitInList() {
242     doTest(LanguageLevel.PYTHON35, true, false);
243   }
244
245   public void testAwaitInTuple() {
246     doTest(LanguageLevel.PYTHON35, true, false);
247   }
248
249   public void testAwaitInGenerator() {
250     doTest(LanguageLevel.PYTHON35, true, false);
251   }
252
253   public void testAwaitInSet() {
254     doTest(LanguageLevel.PYTHON35, true, false);
255   }
256
257   public void testAwaitInDict() {
258     doTest(LanguageLevel.PYTHON35, true, false);
259   }
260
261   public void testYieldInsideAsyncDef() {
262     doTest(LanguageLevel.PYTHON35, false, false);
263   }
264
265   public void testUnpackingStar() {
266     doTest(LanguageLevel.PYTHON35, false, false);
267   }
268
269   // PY-19927
270   public void testMagicMethods() {
271     EditorColorsManager manager = EditorColorsManager.getInstance();
272     EditorColorsScheme scheme = (EditorColorsScheme)manager.getGlobalScheme().clone();
273     manager.addColorsScheme(scheme);
274     EditorColorsManager.getInstance().setGlobalScheme(scheme);
275
276     TextAttributesKey xKey = TextAttributesKey.find("PY.PREDEFINED_DEFINITION");
277     TextAttributes xAttributes = new TextAttributes(Color.green, Color.black, Color.white, EffectType.BOXED, Font.BOLD);
278     scheme.setAttributes(xKey, xAttributes);
279
280     doTest();
281   }
282
283   // PY-19775
284   public void testAsyncBuiltinMethods() {
285     doTest(LanguageLevel.PYTHON35, true, false);
286   }
287
288   public void testImplicitOctLongInteger() {
289     doTest(LanguageLevel.PYTHON35, true, false);
290   }
291
292   public void testUnderscoresInNumericLiterals() {
293     doTest(LanguageLevel.PYTHON35, true, false);
294   }
295
296   public void testVariableAnnotations() {
297     doTest(LanguageLevel.PYTHON35, true, false);
298   }
299
300   public void testIllegalVariableAnnotationTarget() {
301     doTest(LanguageLevel.PYTHON36, true, false);
302   }
303
304   public void testFStringLiterals() {
305     doTest();
306   }
307
308   // PY-20775
309   public void testFStringMissingRightBrace() {
310     runWithLanguageLevel(LanguageLevel.PYTHON36, () -> doTest(true, false));
311   }
312
313   // PY-20776
314   public void testFStringEmptyExpressions() {
315     runWithLanguageLevel(LanguageLevel.PYTHON36, () -> doTest(true, false));
316   }
317
318   // PY-20778
319   public void testFStringIllegalConversionCharacter() {
320     runWithLanguageLevel(LanguageLevel.PYTHON36, () -> doTest(true, false));
321   }
322
323   // PY-20773
324   public void testFStringHashSigns() {
325     runWithLanguageLevel(LanguageLevel.PYTHON36, () -> doTest(true, false));
326   }
327   
328   // PY-20844
329   public void testFStringBackslashes() {
330     runWithLanguageLevel(LanguageLevel.PYTHON36, () -> doTest(true, false));
331   }
332   
333   // ---
334   private void doTest(final LanguageLevel languageLevel, final boolean checkWarnings, final boolean checkInfos) {
335     PythonLanguageLevelPusher.setForcedLanguageLevel(myFixture.getProject(), languageLevel);
336     try {
337       doTest(checkWarnings, checkInfos);
338     }
339     finally {
340       PythonLanguageLevelPusher.setForcedLanguageLevel(myFixture.getProject(), null);
341     }
342   }
343
344   private void doTest() {
345     final String TEST_PATH = "/highlighting/";
346     myFixture.testHighlighting(true, true, false, TEST_PATH + getTestName(true) + PyNames.DOT_PY);
347   }
348
349   private void doTest(boolean checkWarnings, boolean checkInfos) {
350     myFixture.testHighlighting(checkWarnings, checkInfos, false, TEST_PATH + getTestName(true) + PyNames.DOT_PY);
351   }
352
353 }