a1913dc59ddc09494cb09f7671343a35618c76f2
[idea/community.git] / plugins / groovy / src / org / jetbrains / plugins / groovy / lang / psi / impl / statements / expressions / GrThisReferenceExpressionImpl.java
1
2 /*
3  * Copyright 2000-2011 JetBrains s.r.o.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 package org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions;
18
19 import com.intellij.lang.ASTNode;
20 import com.intellij.psi.*;
21 import com.intellij.util.IncorrectOperationException;
22 import com.intellij.util.NullableFunction;
23 import org.jetbrains.annotations.NotNull;
24 import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
25 import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
26 import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
27 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
28 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrThisReferenceExpression;
29 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
30 import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager;
31 import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
32
33 /**
34  * @author ilyas
35  */
36 public class GrThisReferenceExpressionImpl extends GrThisSuperReferenceExpressionBase implements GrThisReferenceExpression {
37
38   private static final NullableFunction<GrThisReferenceExpressionImpl,PsiType> TYPE_CALCULATOR =
39     new NullableFunction<GrThisReferenceExpressionImpl, PsiType>() {
40       @Override
41       public PsiType fun(GrThisReferenceExpressionImpl ref) {
42         final GrReferenceExpression qualifier = ref.getQualifier();
43         if (qualifier == null) {
44           GroovyPsiElement context = PsiUtil.getFileOrClassContext(ref);
45           if (context instanceof GrTypeDefinition) {
46             return ref.createType((PsiClass)context);
47           }
48           else if (context instanceof GroovyFileBase) {
49             return ref.createType(((GroovyFileBase)context).getScriptClass());
50           }
51         }
52         else {
53           final PsiElement resolved = qualifier.resolve();
54           if (resolved instanceof PsiClass) {
55             return JavaPsiFacade.getElementFactory(ref.getProject()).createType((PsiClass)resolved);
56           }
57           else {
58             try {
59               return JavaPsiFacade.getElementFactory(ref.getProject()).createTypeFromText(qualifier.getText(), ref);
60             }
61             catch (IncorrectOperationException e) {
62               return null;
63             }
64           }
65         }
66
67         return null;
68       }
69     };
70
71   public GrThisReferenceExpressionImpl(@NotNull ASTNode node) {
72     super(node);
73   }
74
75   public void accept(GroovyElementVisitor visitor) {
76     visitor.visitThisExpression(this);
77   }
78
79   public String toString() {
80     return "'this' reference expression";
81   }
82
83   public PsiType getType() {
84     return GroovyPsiManager.getInstance(getProject()).getType(this, TYPE_CALCULATOR);
85   }
86
87   private PsiType createType(PsiClass context) {
88     final JavaPsiFacade facade = JavaPsiFacade.getInstance(context.getProject());
89     PsiElementFactory elementFactory = facade.getElementFactory();
90
91     if (!PsiUtil.isInStaticContext(this)) return elementFactory.createType(context);
92
93     //create instance of java.lang.Class<CurrentClass>
94     if (context instanceof PsiAnonymousClass) {
95       final PsiClassType type = ((PsiAnonymousClass)context).getBaseClassType();
96       final PsiClass aClass =
97         facade.findClass(CommonClassNames.JAVA_LANG_CLASS, context.getResolveScope());
98       if (aClass != null) {
99         return elementFactory.createType(aClass, type);
100       }
101       else {
102         return elementFactory.createTypeFromText(CommonClassNames.JAVA_LANG_CLASS + "<" + type.getCanonicalText() + ">", this);
103       }
104     }
105     return elementFactory.createTypeFromText(CommonClassNames.JAVA_LANG_CLASS + "<" + context.getName() + ">", this);
106   }
107
108   @NotNull
109   @Override
110   public String getReferenceName() {
111     return "this";
112   }
113
114   @Override
115   protected PsiElement resolveInner() {
116     final PsiElement resolved = super.resolveInner();
117     if (resolved != null) return resolved;
118     final GrReferenceExpression qualifier = getQualifier();
119     if (qualifier != null) {
120       return qualifier.resolve();
121     }
122
123     final GroovyPsiElement context = PsiUtil.getFileOrClassContext(this);
124     if (context instanceof GrTypeDefinition) {
125       return context;
126     }
127     else if (context instanceof GroovyFileBase) {
128       return ((GroovyFileBase)context).getScriptClass();
129     }
130     return null;
131   }
132
133 }