2 * Copyright 2000-2009 JetBrains s.r.o.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package org
.jetbrains
.plugins
.groovy
.lang
.psi
.impl
;
19 import com
.intellij
.openapi
.util
.Comparing
;
20 import com
.intellij
.pom
.java
.LanguageLevel
;
21 import com
.intellij
.psi
.*;
22 import com
.intellij
.psi
.search
.GlobalSearchScope
;
23 import org
.jetbrains
.annotations
.NonNls
;
24 import org
.jetbrains
.annotations
.NotNull
;
25 import org
.jetbrains
.annotations
.Nullable
;
26 import org
.jetbrains
.plugins
.groovy
.lang
.psi
.api
.statements
.blocks
.GrClosableBlock
;
27 import org
.jetbrains
.plugins
.groovy
.lang
.psi
.api
.statements
.params
.GrParameter
;
32 public class GrClosureType
extends PsiClassType
{
33 private final GlobalSearchScope myScope
;
35 private final PsiType myReturnType
;
36 private final PsiType
[] myParameterTypes
;
37 private final boolean[] myOptionals
;
38 private final PsiManager myManager
;
40 private GrClosureType(GlobalSearchScope scope
,
41 @Nullable PsiType returnType
,
44 PsiManager manager
, LanguageLevel languageLevel
) {
47 myReturnType
= returnType
;
48 myParameterTypes
= parameters
;
49 myOptionals
= optionals
;
54 public PsiClass
resolve() {
55 return JavaPsiFacade
.getInstance(myManager
.getProject()).findClass(GrClosableBlock
.GROOVY_LANG_CLOSURE
, getResolveScope());
59 public PsiType
getClosureReturnType() {
63 public PsiType
[] getClosureParameterTypes() {
64 return myParameterTypes
;
67 public boolean isOptionalParameter(int parameterIndex
) {
68 return myOptionals
[parameterIndex
];
71 public String
getClassName() {
76 public PsiType
[] getParameters() {
78 return PsiType
.EMPTY_ARRAY
;
82 public ClassResolveResult
resolveGenerics() {
83 return new ClassResolveResult() {
84 public PsiClass
getElement() {
88 public PsiSubstitutor
getSubstitutor() {
89 return PsiSubstitutor
.UNKNOWN
;
92 public boolean isPackagePrefixPackageReference() {
96 public boolean isAccessible() {
100 public boolean isStaticsScopeCorrect() {
104 public PsiElement
getCurrentFileResolveScope() {
108 public boolean isValidResult() {
109 return isStaticsScopeCorrect() && isAccessible();
115 public PsiClassType
rawType() {
119 public String
getPresentableText() {
124 public String
getCanonicalText() {
125 PsiClass resolved
= resolve();
126 if (resolved
== null) return null;
127 return resolved
.getQualifiedName();
130 public String
getInternalCanonicalText() {
131 return getCanonicalText();
134 public boolean isValid() {
135 if (myParameterTypes
.length
> 0 && !myParameterTypes
[0].isValid()) return false;
136 return myReturnType
== null || myReturnType
.isValid();
139 public boolean equals(Object obj
) {
140 if (obj
instanceof GrClosureType
) {
141 GrClosureType other
= (GrClosureType
)obj
;
142 if (!Comparing
.equal(myReturnType
, other
.myReturnType
)) return false;
143 if (myParameterTypes
.length
!= other
.myParameterTypes
.length
) return false;
144 for (int i
= 0; i
< myParameterTypes
.length
; i
++) {
145 if (myOptionals
[i
] != other
.myOptionals
[i
]) return false;
146 if (!other
.myParameterTypes
[i
].equals(myParameterTypes
[i
])) return false;
151 return super.equals(obj
);
154 public boolean isAssignableFrom(@NotNull PsiType type
) {
155 if (type
instanceof GrClosureType
) {
156 GrClosureType other
= (GrClosureType
)type
;
157 if (myReturnType
== null || other
.myReturnType
== null) {
158 return myReturnType
== null && other
.myReturnType
== null;
160 if (!myReturnType
.isAssignableFrom(other
.myReturnType
)) return false;
161 if (myParameterTypes
.length
!= other
.myParameterTypes
.length
) return false;
162 for (int i
= 0; i
< myParameterTypes
.length
; i
++) {
163 if (myOptionals
[i
] != other
.myOptionals
[i
]) return false;
164 if (!other
.myParameterTypes
[i
].isAssignableFrom(myParameterTypes
[i
])) return false;
168 return super.isAssignableFrom(type
);
171 public boolean equalsToText(@NonNls String text
) {
172 return text
.equals(GrClosableBlock
.GROOVY_LANG_CLOSURE
);
176 public GlobalSearchScope
getResolveScope() {
181 public LanguageLevel
getLanguageLevel() {
182 return myLanguageLevel
;
185 public PsiClassType
setLanguageLevel(final LanguageLevel languageLevel
) {
186 return create(myReturnType
, myParameterTypes
, myOptionals
, myManager
, myScope
, languageLevel
);
189 public static GrClosureType
create(GrClosableBlock closure
) {
190 return create(closure
.getResolveScope(), closure
.getReturnType(), closure
.getAllParameters(), closure
.getManager());
193 public static GrClosureType
create(GlobalSearchScope scope
, PsiType returnType
, PsiParameter
[] parameters
, PsiManager manager
) {
194 PsiType
[] parameterTypes
= new PsiType
[parameters
.length
];
195 boolean[] optionals
= new boolean[parameters
.length
];
196 for (int i
= 0; i
< optionals
.length
; i
++) {
197 PsiParameter parameter
= parameters
[i
];
198 if (parameter
instanceof GrParameter
) {
199 optionals
[i
] = ((GrParameter
)parameter
).isOptional();
200 } else if (i
== 0) { // for implicit "it" parameter
203 optionals
[i
] = false;
205 parameterTypes
[i
] = parameter
.getType();
207 return create(returnType
, parameterTypes
, optionals
, manager
, scope
, LanguageLevel
.JDK_1_5
);
210 public static GrClosureType
create(PsiType returnType
,
211 PsiType
[] parameterTypes
,
214 GlobalSearchScope scope
, LanguageLevel languageLevel
) {
215 return new GrClosureType(scope
, returnType
, parameterTypes
, optionals
, manager
,languageLevel
);
219 public PsiType
curry(int num
) {
220 if (num
> myParameterTypes
.length
) return null;
221 PsiType
[] newParameterTypes
= new PsiType
[myParameterTypes
.length
- num
];
222 boolean[] newOptionals
= new boolean[myParameterTypes
.length
- num
];
223 System
.arraycopy(myParameterTypes
, num
, newParameterTypes
, 0, newParameterTypes
.length
);
224 System
.arraycopy(myOptionals
, num
, newOptionals
, 0, newOptionals
.length
);
225 return create(myReturnType
, newParameterTypes
, newOptionals
, myManager
, myScope
, myLanguageLevel
);