PY-33235 Add highlighting annotator for nested functions
[idea/community.git] / python / testSrc / com / jetbrains / python / PythonHighlightingTest.java
1 // Copyright 2000-2017 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;
3
4 import com.intellij.openapi.editor.colors.EditorColorsManager;
5 import com.intellij.openapi.editor.colors.EditorColorsScheme;
6 import com.intellij.openapi.editor.colors.TextAttributesKey;
7 import com.intellij.openapi.editor.markup.EffectType;
8 import com.intellij.openapi.editor.markup.TextAttributes;
9 import com.jetbrains.python.documentation.PyDocumentationSettings;
10 import com.jetbrains.python.documentation.docstrings.DocStringFormat;
11 import com.jetbrains.python.fixtures.PyTestCase;
12 import com.jetbrains.python.psi.LanguageLevel;
13 import org.jetbrains.annotations.NotNull;
14
15 import java.awt.*;
16
17 /**
18  * Test highlighting added by annotators.
19  *
20  * @author yole
21  */
22 public class PythonHighlightingTest extends PyTestCase {
23
24   public void testBuiltins() {
25     EditorColorsScheme scheme = createTemporaryColorScheme();
26
27     TextAttributesKey xKey;
28     TextAttributes xAttributes;
29     
30     xKey = TextAttributesKey.find("PY.BUILTIN_NAME");
31     xAttributes = new TextAttributes(Color.green, Color.black, Color.white, EffectType.BOXED, Font.BOLD);
32     scheme.setAttributes(xKey, xAttributes);
33
34     xKey = TextAttributesKey.find("PY.PREDEFINED_USAGE");
35     xAttributes = new TextAttributes(Color.yellow, Color.black, Color.white, EffectType.BOXED, Font.BOLD);
36     scheme.setAttributes(xKey, xAttributes);
37
38     doTest();
39   }
40
41   public void testDeclarations() {
42     EditorColorsScheme scheme = createTemporaryColorScheme();
43
44     TextAttributesKey xKey = TextAttributesKey.find("PY.CLASS_DEFINITION");
45     TextAttributes xAttributes = new TextAttributes(Color.blue, Color.black, Color.white, EffectType.BOXED, Font.BOLD);
46     scheme.setAttributes(xKey, xAttributes);
47
48     xKey = TextAttributesKey.find("PY.FUNC_DEFINITION");
49     xAttributes = new TextAttributes(Color.red, Color.black, Color.white, EffectType.BOXED, Font.BOLD);
50     scheme.setAttributes(xKey, xAttributes);
51
52     xKey = TextAttributesKey.find("PY.PREDEFINED_DEFINITION");
53     xAttributes = new TextAttributes(Color.green, Color.black, Color.white, EffectType.BOXED, Font.BOLD);
54     scheme.setAttributes(xKey, xAttributes);
55
56     doTest();
57   }
58
59   public void testAssignmentTargets() {
60     runWithLanguageLevel(LanguageLevel.PYTHON26, () -> doTest(true, false));
61   }
62
63   public void testAssignmentTargetWith() {  // PY-7529
64     runWithLanguageLevel(LanguageLevel.PYTHON27, () -> doTest(true, false));
65   }
66
67   public void testAssignmentTargets3K() {
68     doTest(LanguageLevel.PYTHON34, true, false);    
69   }
70   
71   public void testBreakOutsideOfLoop() {
72     doTest(true, false);
73   }
74
75   public void testReturnOutsideOfFunction() {
76     doTest();
77   }
78
79   public void testContinueOutsideOfLoop() {
80     doTest(false, false);
81   }
82
83   // PY-36003
84   public void testContinueInFinallyBlockBefore38() {
85     doTest(LanguageLevel.PYTHON37, false, false);
86   }
87
88   // PY-36003
89   public void testContinueInFinallyBlock() {
90     doTest(LanguageLevel.PYTHON38, false, false);
91   }
92
93   public void testReturnWithArgumentsInGenerator() {
94     doTest();
95   }
96
97   public void testYieldOutsideOfFunction() {
98     doTest(LanguageLevel.PYTHON27, true, true);
99   }
100
101   public void testYieldInDefaultValue() {
102     doTest(LanguageLevel.PYTHON34, true, false);
103   }
104
105   // PY-11663
106   public void testYieldInLambda() {
107     doTest();
108   }
109   
110   public void testImportStarAtTopLevel() {
111     doTest(true, false);
112   }
113
114   public void testMalformedStringUnterminated() {
115     doTest();
116   }
117
118   public void testMalformedStringEscaped() {
119     doTest(false, false);
120   }
121
122   public void testStringEscapedOK() {
123     doTest();
124   }
125
126   public void testStringMixedSeparatorsOK() {   // PY-299
127     doTest();
128   }
129
130   public void testStringBytesLiteralOK() {
131     doTest(LanguageLevel.PYTHON26, true, true);
132   }
133
134   public void testArgumentList() {
135     doTest(true, false);
136   }
137
138   public void testRegularAfterVarArgs() {
139     doTest(LanguageLevel.PYTHON34, true, false);
140   }
141
142   public void testKeywordOnlyArguments() {
143     doTest(LanguageLevel.PYTHON34, true, false);
144   }
145
146   public void testMalformedStringTripleQuoteUnterminated() {
147     doTest();
148   }
149
150   public void testMixedTripleQuotes() {   // PY-2806
151     doTest();
152   }
153
154   public void testOddNumberOfQuotes() {  // PY-2802
155     doTest(true, false);
156   }
157
158   public void testEscapedBackslash() {  // PY-2994
159     doTest(true, false);
160   }
161
162   public void testMultipleEscapedBackslashes() {
163     doTest(true, false);
164   }
165
166   public void testUnsupportedFeaturesInPython3() {
167     doTest(LanguageLevel.PYTHON34, true, false);
168   }
169
170   // PY-6703
171   public void testUnicode33() {
172     doTest(LanguageLevel.PYTHON34, true, false);
173   }
174
175   public void testParenthesizedGenerator() {
176     doTest(false, false);
177   }
178
179   public void testStarInGenerator() {  // PY-10177
180     doTest(LanguageLevel.PYTHON34, false, false);
181   }
182
183   public void testStarArgs() {  // PY-6456
184     doTest(LanguageLevel.PYTHON34, true, false);
185   }
186
187   public void testDocstring() {  // PY-8025
188     PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(myFixture.getModule());
189     documentationSettings.setFormat(DocStringFormat.REST);
190     try {
191       doTest(false, true);
192     }
193     finally {
194       documentationSettings.setFormat(DocStringFormat.PLAIN);
195     }
196   }
197
198   public void testYieldInNestedFunction() {
199     // highlight func declaration first, lest we get an "Extra fragment highlighted" error.
200     EditorColorsScheme scheme = createTemporaryColorScheme();
201
202     TextAttributesKey xKey = TextAttributesKey.find("PY.FUNC_DEFINITION");
203     TextAttributes xAttributes = new TextAttributes(Color.red, Color.black, Color.white, EffectType.BOXED, Font.BOLD);
204     scheme.setAttributes(xKey, xAttributes);
205
206     doTest();
207   }
208
209   // PY-33235
210   public void testNestedFunction() {
211     EditorColorsScheme scheme = createTemporaryColorScheme();
212
213     TextAttributesKey xKey = TextAttributesKey.find("PY.CLASS_DEFINITION");
214     TextAttributes xAttributes = new TextAttributes(Color.blue, Color.black, Color.white, EffectType.BOXED, Font.BOLD);
215     scheme.setAttributes(xKey, xAttributes);
216
217     xKey = TextAttributesKey.find("PY.FUNC_DEFINITION");
218     xAttributes = new TextAttributes(Color.red, Color.black, Color.white, EffectType.BOXED, Font.BOLD);
219     scheme.setAttributes(xKey, xAttributes);
220
221     xKey = TextAttributesKey.find("PY.NESTED_FUNC_DEFINITION");
222     xAttributes = new TextAttributes(Color.green, Color.blue, Color.white, EffectType.BOXED, Font.BOLD);
223     scheme.setAttributes(xKey, xAttributes);
224
225     doTest();
226   }
227
228   public void testAsync() {
229     doTest(LanguageLevel.PYTHON35, true, true);
230   }
231
232   public void testAwait() {
233     doTest(LanguageLevel.PYTHON35, true, true);
234   }
235
236   // PY-19679
237   public void testAwaitInListPy35() {
238     doTest(LanguageLevel.PYTHON35, true, false);
239   }
240
241   public void testAwaitInTuple() {
242     doTest(LanguageLevel.PYTHON35, true, false);
243   }
244
245   public void testAwaitInGenerator() {
246     doTest(LanguageLevel.PYTHON35, true, false);
247   }
248
249   public void testAwaitInSetPy35() {
250     doTest(LanguageLevel.PYTHON35, true, false);
251   }
252
253   public void testAwaitInDictPy35() {
254     doTest(LanguageLevel.PYTHON35, true, false);
255   }
256
257   // PY-20770
258   public void testAwaitInListPy36() {
259     doTest(LanguageLevel.PYTHON36, true, false);
260   }
261
262   // PY-20770
263   public void testAwaitInSetPy36() {
264     doTest(LanguageLevel.PYTHON36, true, false);
265   }
266
267   // PY-20770
268   public void testAwaitInDictPy36() {
269     doTest(LanguageLevel.PYTHON36, true, false);
270   }
271
272   public void testYieldInsideAsyncDefPy35() {
273     doTest(LanguageLevel.PYTHON35, false, false);
274   }
275
276   // PY-20770
277   public void testYieldInsideAsyncDefPy36() {
278     doTest(LanguageLevel.PYTHON36, true, false);
279   }
280
281   public void testUnpackingStar() {
282     doTest(LanguageLevel.PYTHON35, false, false);
283   }
284
285   // PY-35961
286   public void testUnpackingInNonParenthesizedTuplesInReturnAndYieldBefore38() {
287     doTest(LanguageLevel.PYTHON35, false, false);
288   }
289
290   // PY-35961
291   public void testUnpackingInNonParenthesizedTuplesInReturnAndYield() {
292     doTest(LanguageLevel.PYTHON38, false, false);
293   }
294
295   // PY-19927
296   public void testMagicMethods() {
297     EditorColorsScheme scheme = createTemporaryColorScheme();
298
299     TextAttributesKey xKey = TextAttributesKey.find("PY.PREDEFINED_DEFINITION");
300     TextAttributes xAttributes = new TextAttributes(Color.green, Color.black, Color.white, EffectType.BOXED, Font.BOLD);
301     scheme.setAttributes(xKey, xAttributes);
302
303     doTest();
304   }
305
306   // PY-19775
307   public void testAsyncBuiltinMethods() {
308     doTest(LanguageLevel.PYTHON35, true, false);
309   }
310
311   // PY-28017
312   public void testAsyncModuleBuiltinMethods() {
313     doTest(LanguageLevel.PYTHON37, true, false);
314   }
315
316   // PY-28017
317   public void testModuleBuiltinMethods() {
318     doTest(LanguageLevel.PYTHON37, false, true);
319   }
320
321   public void testImplicitOctLongInteger() {
322     doTest(LanguageLevel.PYTHON35, true, false);
323   }
324
325   public void testUnderscoresInNumericLiterals() {
326     doTest(LanguageLevel.PYTHON35, true, false);
327   }
328
329   public void testVariableAnnotations() {
330     doTest(LanguageLevel.PYTHON35, true, false);
331   }
332
333   public void testIllegalVariableAnnotationTarget() {
334     doTest(LanguageLevel.PYTHON36, true, false);
335   }
336
337   public void testFStringLiterals() {
338     doTest();
339   }
340
341   // PY-20770
342   public void testAsyncComprehensionsPy35() {
343     doTest(LanguageLevel.PYTHON35, true, false);
344   }
345
346   // PY-20770
347   public void testAsyncComprehensionsPy36() {
348     doTest(LanguageLevel.PYTHON36, true, false);
349   }
350
351   // PY-20775
352   public void testFStringMissingRightBrace() {
353     runWithLanguageLevel(LanguageLevel.PYTHON36, () -> doTest(true, false));
354   }
355
356   // PY-20776
357   public void testFStringEmptyExpressions() {
358     runWithLanguageLevel(LanguageLevel.PYTHON36, () -> doTest(true, false));
359   }
360
361   // PY-20778
362   public void testFStringIllegalConversionCharacter() {
363     runWithLanguageLevel(LanguageLevel.PYTHON36, () -> doTest(true, false));
364   }
365
366   // PY-20773
367   public void testFStringHashSigns() {
368     runWithLanguageLevel(LanguageLevel.PYTHON36, () -> doTest(true, false));
369   }
370
371   // PY-20844
372   public void testFStringBackslashes() {
373     runWithLanguageLevel(LanguageLevel.PYTHON36, () -> doTest(true, false));
374   }
375
376   // PY-20897
377   public void testFStringSingleRightBraces() {
378     runWithLanguageLevel(LanguageLevel.PYTHON36, () -> doTest(true, false));
379   }
380   
381   // PY-20901
382   public void testFStringTooDeeplyNestedExpressionFragments() {
383     runWithLanguageLevel(LanguageLevel.PYTHON36, () -> doTest(true, false));
384   }
385
386   // PY-12634
387   public void testSpaceBetweenAtAndDecorator() {
388     doTest(true, true);
389   }
390
391   // PY-41305
392   public void testExpressionAsDecorator() {
393     runWithLanguageLevel(LanguageLevel.getLatest(), this::doTest);
394   }
395
396   // PY-25381
397   public void testBuiltinDecorator() {
398     doTest(true, true);
399   }
400
401   // PY-11418
402   public void testFunctionCalls() {
403     doTest();
404   }
405
406   // PY-20401
407   public void testAnnotations() {
408     runWithLanguageLevel(LanguageLevel.PYTHON36, this::doTest);
409   }
410
411   // PY-22729
412   public void testParametersWithAnnotationsAndDefaults() {
413     runWithLanguageLevel(LanguageLevel.PYTHON34, this::doTest);
414   }
415
416   // PY-26491
417   public void testMultiplePositionalContainers() {
418     doTest(LanguageLevel.PYTHON35, true, false);
419   }
420
421   // PY-26491
422   public void testMultipleKeywordContainers() {
423     doTest(LanguageLevel.PYTHON35, true, false);
424   }
425
426   // PY-26510
427   public void testEmptyRaise() {
428     doTest(false, false);
429   }
430
431   // PY-28247
432   public void testAsyncAndAwaitAsIdentifiersIn37() {
433     doTest(LanguageLevel.PYTHON37, false, false);
434   }
435
436   // PY-27913
437   public void testDunderClassGetItem() {
438     doTest(LanguageLevel.PYTHON37, false, true);
439   }
440
441   // PY-28313
442   public void testVarargs() {
443     doTest();
444   }
445
446   // PY-28313
447   public void testKwargs() {
448     doTest();
449   }
450
451   // PY-20530
452   public void testUnparsedTypeHints() {
453     doTest(LanguageLevel.PYTHON36, false, false);
454   }
455
456   // PY-32321
457   public void testMixedBytesAndNonBytes() {
458     doTest(LanguageLevel.PYTHON36, false, false);
459   }
460
461   // PY-35512
462   public void testInvalidPositionalOnlyParameters() {
463     doTest(LanguageLevel.PYTHON38, false, false);
464   }
465
466   // PY-35512
467   public void testUnsupportedPositionalOnlyParameters() {
468     doTest(LanguageLevel.PYTHON37, false, false);
469   }
470
471   // PY-33886
472   public void testInvalidAssignmentExpressions() {
473     doTest(LanguageLevel.PYTHON38, false, false);
474   }
475
476   // PY-33886
477   public void testUnsupportedAssignmentExpressions() {
478     doTest(LanguageLevel.PYTHON37, false, false);
479   }
480
481   // PY-36004
482   public void testNamedUnicodeBefore38() {
483     doTest(LanguageLevel.PYTHON37, false, false);
484   }
485
486   // PY-36004
487   public void testNamedUnicode() {
488     doTest(LanguageLevel.PYTHON38, false, false);
489   }
490
491   @NotNull
492   private static EditorColorsScheme createTemporaryColorScheme() {
493     EditorColorsManager manager = EditorColorsManager.getInstance();
494     EditorColorsScheme scheme = (EditorColorsScheme)manager.getGlobalScheme().clone();
495     manager.addColorsScheme(scheme);
496     EditorColorsManager.getInstance().setGlobalScheme(scheme);
497     return scheme;
498   }
499
500   // ---
501   private void doTest(final LanguageLevel languageLevel, final boolean checkWarnings, final boolean checkInfos) {
502     runWithLanguageLevel(languageLevel, () -> doTest(checkWarnings, checkInfos));
503   }
504
505   private void doTest() {
506     doTest(true, true);
507   }
508
509   private void doTest(boolean checkWarnings, boolean checkInfos) {
510     myFixture.testHighlighting(checkWarnings, checkInfos, false, getTestName(true) + PyNames.DOT_PY);
511   }
512
513   @Override
514   protected String getTestDataPath() {
515     return super.getTestDataPath() + "/highlighting/";
516   }
517 }