5d6c1102e0672437fdaa605ec1c0c1a1958a800f
[idea/community.git] / python / src / com / jetbrains / python / validation / PyDefinitionsAnnotator.java
1 /*
2  * Copyright 2000-2017 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.validation;
17
18 import com.intellij.lang.ASTNode;
19 import com.intellij.openapi.project.IndexNotReadyException;
20 import com.intellij.psi.PsiElement;
21 import com.jetbrains.python.PyNames;
22 import com.jetbrains.python.highlighting.PyHighlighter;
23 import com.jetbrains.python.psi.*;
24 import org.jetbrains.annotations.NotNull;
25
26 import java.util.Objects;
27
28 /**
29  * Highlights class definitions, functrion definitions, and decorators.
30  * User: dcheryasov
31  */
32 public class PyDefinitionsAnnotator extends PyAnnotator {
33
34   @Override
35   public void visitPyClass(PyClass node) {
36     final ASTNode name_node = node.getNameNode();
37     if (name_node != null) {
38       addHighlightingAnnotation(name_node, PyHighlighter.PY_CLASS_DEFINITION);
39     }
40   }
41
42   @Override
43   public void visitPyFunction(PyFunction node) {
44     ASTNode name_node = node.getNameNode();
45     if (name_node != null) {
46       final String name = node.getName();
47       LanguageLevel languageLevel = LanguageLevel.forElement(node);
48       if (PyNames.UNDERSCORED_ATTRIBUTES.contains(name) || PyNames.getBuiltinMethods(languageLevel).containsKey(name)) {
49         PyClass cls = node.getContainingClass();
50         if (PyUtil.isNewMethod(node)) {
51           boolean new_style_class = false;
52           try {
53             if (cls != null) new_style_class = cls.isNewStyleClass(null);
54           }
55           catch (IndexNotReadyException ignored) {
56           }
57           if (new_style_class) {
58             addHighlightingAnnotation(name_node, PyHighlighter.PY_PREDEFINED_DEFINITION);
59           }
60         }
61         else {
62           addHighlightingAnnotation(name_node, PyHighlighter.PY_PREDEFINED_DEFINITION);
63         }
64       }
65       else {
66         addHighlightingAnnotation(name_node, PyHighlighter.PY_FUNC_DEFINITION);
67       }
68     }
69   }
70
71   @Override
72   public void visitPyDecoratorList(PyDecoratorList node) {
73     PyDecorator[] decos = node.getDecorators();
74     for (PyDecorator deco : decos) {
75       highlightDecorator(deco);
76     }
77   }
78
79   private void highlightDecorator(@NotNull PyDecorator node) {
80     final PsiElement atSign = node.getFirstChild();
81     if (atSign != null) {
82       addHighlightingAnnotation(atSign, PyHighlighter.PY_DECORATOR);
83       if (node.getQualifiedName() != null) {
84         addHighlightingAnnotation(Objects.requireNonNull(node.getCallee()), PyHighlighter.PY_DECORATOR);
85       }
86     }
87   }
88 }