cleanup
[idea/community.git] / plugins / groovy / src / org / jetbrains / plugins / groovy / lang / psi / impl / statements / expressions / GrThisReferenceExpressionImpl.java
1 /*
2 * Copyright 2000-2011 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 org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions;
17
18 import com.intellij.lang.ASTNode;
19 import com.intellij.psi.*;
20 import com.intellij.util.IncorrectOperationException;
21 import com.intellij.util.NullableFunction;
22 import org.jetbrains.annotations.NotNull;
23 import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
24 import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
25 import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
26 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
27 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrThisReferenceExpression;
28 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
29 import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager;
30 import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
31
32 /**
33  * @author ilyas
34  */
35 public class GrThisReferenceExpressionImpl extends GrThisSuperReferenceExpressionBase implements GrThisReferenceExpression {
36
37   private static final NullableFunction<GrThisReferenceExpressionImpl, PsiType> TYPE_CALCULATOR =
38     new NullableFunction<GrThisReferenceExpressionImpl, PsiType>() {
39       @Override
40       public PsiType fun(GrThisReferenceExpressionImpl ref) {
41         final GrReferenceExpression qualifier = ref.getQualifier();
42         if (qualifier == null) {
43           GroovyPsiElement context = PsiUtil.getFileOrClassContext(ref);
44           if (context instanceof GrTypeDefinition) {
45             return ref.createType((PsiClass)context);
46           }
47           else if (context instanceof GroovyFileBase) {
48             return ref.createType(((GroovyFileBase)context).getScriptClass());
49           }
50         }
51         else {
52           final PsiElement resolved = qualifier.resolve();
53           if (resolved instanceof PsiClass) {
54             return JavaPsiFacade.getElementFactory(ref.getProject()).createType((PsiClass)resolved);
55           }
56           else {
57             try {
58               return JavaPsiFacade.getElementFactory(ref.getProject()).createTypeFromText(qualifier.getText(), ref);
59             }
60             catch (IncorrectOperationException e) {
61               return null;
62             }
63           }
64         }
65
66         return null;
67       }
68     };
69
70   public GrThisReferenceExpressionImpl(@NotNull ASTNode node) {
71     super(node);
72   }
73
74   public void accept(GroovyElementVisitor visitor) {
75     visitor.visitThisExpression(this);
76   }
77
78   public String toString() {
79     return "'this' reference expression";
80   }
81
82   public PsiType getType() {
83     return GroovyPsiManager.getInstance(getProject()).getType(this, TYPE_CALCULATOR);
84   }
85
86   private PsiType createType(@NotNull PsiClass context) {
87     final JavaPsiFacade facade = JavaPsiFacade.getInstance(context.getProject());
88     PsiElementFactory elementFactory = facade.getElementFactory();
89
90     if (!PsiUtil.isInStaticContext(this)) return elementFactory.createType(context);
91
92     //create instance of java.lang.Class<CurrentClass>
93     if (context instanceof PsiAnonymousClass) {
94       final PsiClassType type = ((PsiAnonymousClass)context).getBaseClassType();
95       final PsiClass aClass = facade.findClass(CommonClassNames.JAVA_LANG_CLASS, context.getResolveScope());
96       if (aClass != null) {
97         return elementFactory.createType(aClass, type);
98       }
99       else {
100         return elementFactory.createTypeFromText(CommonClassNames.JAVA_LANG_CLASS + "<" + type.getCanonicalText() + ">", this);
101       }
102     }
103     return elementFactory.createTypeFromText(CommonClassNames.JAVA_LANG_CLASS + "<" + context.getName() + ">", this);
104   }
105
106   @NotNull
107   @Override
108   public String getReferenceName() {
109     return "this";
110   }
111
112   @Override
113   protected PsiElement resolveInner() {
114     final PsiElement resolved = super.resolveInner();
115     if (resolved != null) return resolved;
116     final GrReferenceExpression qualifier = getQualifier();
117     if (qualifier != null) {
118       return qualifier.resolve();
119     }
120
121     final GroovyPsiElement context = PsiUtil.getFileOrClassContext(this);
122     if (context instanceof GrTypeDefinition) {
123       return context;
124     }
125     else if (context instanceof GroovyFileBase) {
126       return ((GroovyFileBase)context).getScriptClass();
127     }
128     return null;
129   }
130
131 }