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.util;
19 import com.intellij.codeInsight.CodeInsightSettings;
20 import com.intellij.lang.ASTNode;
21 import com.intellij.openapi.application.ApplicationManager;
22 import com.intellij.openapi.diagnostic.Logger;
23 import com.intellij.openapi.util.Computable;
24 import com.intellij.openapi.util.Key;
25 import com.intellij.openapi.util.TextRange;
26 import com.intellij.psi.*;
27 import com.intellij.psi.codeStyle.CodeStyleManager;
28 import com.intellij.psi.search.GlobalSearchScope;
29 import com.intellij.psi.search.SearchScope;
30 import com.intellij.psi.util.InheritanceUtil;
31 import com.intellij.psi.util.PsiTreeUtil;
32 import com.intellij.util.IncorrectOperationException;
33 import com.intellij.util.containers.HashSet;
34 import gnu.trove.TIntStack;
35 import org.jetbrains.annotations.NotNull;
36 import org.jetbrains.annotations.Nullable;
37 import org.jetbrains.plugins.groovy.GroovyFileTypeLoader;
38 import org.jetbrains.plugins.groovy.debugger.fragments.GroovyCodeFragment;
39 import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocComment;
40 import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocMemberReference;
41 import org.jetbrains.plugins.groovy.lang.lexer.GroovyLexer;
42 import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
43 import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
44 import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
45 import org.jetbrains.plugins.groovy.lang.psi.*;
46 import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
47 import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap;
48 import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrConstructorInvocation;
49 import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
50 import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrTopLevelDefintion;
51 import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
52 import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument;
53 import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
54 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*;
55 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrCallExpression;
56 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrIndexProperty;
57 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression;
58 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrPropertySelection;
59 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousClassDefinition;
60 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
61 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod;
62 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant;
63 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
64 import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement;
65 import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature;
66 import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
67 import org.jetbrains.plugins.groovy.lang.psi.impl.GrClosureType;
68 import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
69 import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass;
70 import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.JavaIdentifier;
71 import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
72 import org.jetbrains.plugins.groovy.lang.resolve.NonCodeMembersProcessor;
73 import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
74 import org.jetbrains.plugins.groovy.lang.resolve.processors.MethodResolverProcessor;
75 import org.jetbrains.plugins.groovy.lang.resolve.processors.ResolverProcessor;
82 public class PsiUtil {
83 public static final Logger LOG = Logger.getInstance("org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil");
84 public static final Key<JavaIdentifier> NAME_IDENTIFIER = new Key<JavaIdentifier>("Java Identifier");
90 public static String getQualifiedReferenceText(GrCodeReferenceElement referenceElement) {
91 StringBuilder builder = new StringBuilder();
92 if (!appendName(referenceElement, builder)) return null;
94 return builder.toString();
97 private static boolean appendName(GrCodeReferenceElement referenceElement, StringBuilder builder) {
98 String refName = referenceElement.getReferenceName();
99 if (refName == null) return false;
100 GrCodeReferenceElement qualifier = referenceElement.getQualifier();
101 if (qualifier != null) {
102 appendName(qualifier, builder);
106 builder.append(refName);
110 public static boolean isLValue(GroovyPsiElement element) {
111 if (element instanceof GrExpression) {
112 PsiElement parent = element.getParent();
113 if (parent instanceof GrListOrMap && !((GrListOrMap)parent).isMap()) {
114 return isLValue((GroovyPsiElement)parent);
116 return parent instanceof GrAssignmentExpression && element.equals(((GrAssignmentExpression)parent).getLValue());
121 public static boolean isApplicable(@Nullable PsiType[] argumentTypes,
123 PsiSubstitutor substitutor,
124 boolean isInUseCategory, GroovyPsiElement place) {
125 if (argumentTypes == null) return true;
127 GrClosureSignature signature = GrClosureSignatureUtil.createSignature(method, substitutor);
128 if (isInUseCategory && method.hasModifierProperty(PsiModifier.STATIC) && method.getParameterList().getParametersCount() > 0) {
129 signature = signature.curry(1);
132 //check for default constructor
133 if (method.isConstructor() && method.getParameterList().getParametersCount() == 0 && argumentTypes.length == 1) {
134 return InheritanceUtil.isInheritor(argumentTypes[0], CommonClassNames.JAVA_UTIL_MAP);
136 LOG.assertTrue(signature != null);
137 return GrClosureSignatureUtil.isSignatureApplicable(signature, argumentTypes, place);
140 public static boolean isApplicable(@Nullable PsiType[] argumentTypes, GrClosureType type, GroovyPsiElement context) {
141 if (argumentTypes == null) return true;
143 GrClosureSignature signature = type.getSignature();
144 return GrClosureSignatureUtil.isSignatureApplicable(signature, argumentTypes, context);
147 public static PsiClassType createMapType(PsiManager manager, GlobalSearchScope scope) {
148 return JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createTypeByFQClassName(CommonClassNames.JAVA_UTIL_MAP, scope);
152 public static GrArgumentList getArgumentsList(PsiElement methodRef) {
153 PsiElement parent = methodRef.getParent();
154 if (parent instanceof GrCall) {
155 return ((GrCall)parent).getArgumentList();
157 if (parent instanceof GrAnonymousClassDefinition) {
158 return ((GrAnonymousClassDefinition)parent).getArgumentListGroovy();
164 public static PsiType[] getArgumentTypes(PsiElement place, boolean nullAsBottom) {
165 PsiElement parent = place.getParent();
166 if (parent instanceof GrCallExpression) {
167 List<PsiType> result = new ArrayList<PsiType>();
168 GrCallExpression call = (GrCallExpression)parent;
170 GrNamedArgument[] namedArgs = call.getNamedArguments();
171 if (namedArgs.length > 0) {
172 result.add(createMapType(place.getManager(), place.getResolveScope()));
175 GrExpression[] expressions = call.getExpressionArguments();
176 for (GrExpression expression : expressions) {
177 PsiType type = expression.getType();
179 result.add(nullAsBottom ? PsiType.NULL : TypesUtil.getJavaLangObject(call));
185 GrClosableBlock[] closures = call.getClosureArguments();
186 for (GrClosableBlock closure : closures) {
187 PsiType closureType = closure.getType();
188 if (closureType != null) {
189 result.add(closureType);
193 return result.toArray(new PsiType[result.size()]);
196 else if (parent instanceof GrAnonymousClassDefinition) {
197 final GrAnonymousClassDefinition anonymous = (GrAnonymousClassDefinition)parent;
198 final GrArgumentList argList = anonymous.getArgumentListGroovy();
199 List<PsiType> result = new ArrayList<PsiType>();
201 GrNamedArgument[] namedArgs = argList.getNamedArguments();
202 if (namedArgs.length > 0) {
203 result.add(createMapType(place.getManager(), place.getResolveScope()));
206 GrExpression[] expressions = argList.getExpressionArguments();
207 for (GrExpression expression : expressions) {
208 PsiType type = expression.getType();
210 result.add(nullAsBottom ? PsiType.NULL : TypesUtil.getJavaLangObject(argList));
216 return result.toArray(new PsiType[result.size()]);
218 else if (parent instanceof GrApplicationStatement) {
219 final GrApplicationStatement call = (GrApplicationStatement)parent;
220 GrExpression[] args = call.getArguments();
221 final GrArgumentList argList = call.getArgumentList();
222 GrNamedArgument[] namedArgs = argList != null ? argList.getNamedArguments() : GrNamedArgument.EMPTY_ARRAY;
223 final ArrayList<PsiType> result = new ArrayList<PsiType>();
224 if (namedArgs.length > 0) {
225 result.add(createMapType(place.getManager(), place.getResolveScope()));
227 for (GrExpression arg : args) {
228 PsiType argType = arg.getType();
229 if (argType == null) {
230 result.add(nullAsBottom ? PsiType.NULL : TypesUtil.getJavaLangObject(parent));
236 return result.toArray(new PsiType[result.size()]);
237 } else if (parent instanceof GrConstructorInvocation || parent instanceof GrEnumConstant) {
238 final GrArgumentList argList = ((GrCall)parent).getArgumentList();
239 if (argList == null) return PsiType.EMPTY_ARRAY;
241 List<PsiType> result = new ArrayList<PsiType>();
242 if (argList.getNamedArguments().length > 0) {
243 result.add(createMapType(place.getManager(), place.getResolveScope()));
246 GrExpression[] expressions = argList.getExpressionArguments();
247 for (GrExpression expression : expressions) {
248 PsiType type = expression.getType();
250 result.add(nullAsBottom ? PsiType.NULL : TypesUtil.getJavaLangObject(argList));
256 return result.toArray(new PsiType[result.size()]);
262 public static SearchScope restrictScopeToGroovyFiles(final Computable<SearchScope> originalScopeComputation) { //important to compute originalSearchScope in read action!
263 return ApplicationManager.getApplication().runReadAction(new Computable<SearchScope>() {
264 public SearchScope compute() {
265 final SearchScope originalScope = originalScopeComputation.compute();
266 if (originalScope instanceof GlobalSearchScope) {
267 return GlobalSearchScope
268 .getScopeRestrictedByFileTypes((GlobalSearchScope)originalScope, GroovyFileTypeLoader.getGroovyEnabledFileTypes());
270 return originalScope;
276 public static PsiClass getJavaLangClass(PsiElement resolved, GlobalSearchScope scope) {
277 return JavaPsiFacade.getInstance(resolved.getProject()).findClass(CommonClassNames.JAVA_LANG_CLASS, scope);
280 public static boolean isValidReferenceName(String text) {
281 final GroovyLexer lexer = new GroovyLexer();
283 return TokenSets.REFERENCE_NAMES.contains(lexer.getTokenType()) && lexer.getTokenEnd() == text.length();
286 public static void shortenReferences(GroovyPsiElement element) {
290 private static void doShorten(PsiElement element) {
291 PsiElement child = element.getFirstChild();
292 while (child != null) {
293 if (child instanceof GrCodeReferenceElement) {
294 shortenReference((GrCodeReferenceElement)child);
298 child = child.getNextSibling();
303 public static void shortenReference(GrReferenceElement ref) {
304 final PsiElement qualifier = ref.getQualifier();
305 if (qualifier != null &&
306 (PsiTreeUtil.getParentOfType(ref, GrDocMemberReference.class) != null ||
307 PsiTreeUtil.getParentOfType(ref, GrDocComment.class) == null) &&
308 PsiTreeUtil.getParentOfType(ref, GrImportStatement.class) == null &&
309 PsiTreeUtil.getParentOfType(ref, GroovyCodeFragment.class) == null) {
310 final PsiElement resolved = ref.resolve();
311 if (resolved instanceof PsiClass) {
312 setQualifier(ref, null);
313 if (ref.isReferenceTo(resolved)) return;
315 final GroovyFileBase file = (GroovyFileBase)ref.getContainingFile();
316 final PsiClass clazz = (PsiClass)resolved;
317 final String qName = clazz.getQualifiedName();
319 if (mayInsertImport(ref)) {
320 final GrImportStatement added = file.addImportForClass(clazz);
321 if (!ref.isReferenceTo(resolved)) {
322 file.removeImport(added);
323 setQualifier(ref, qualifier);
331 private static void setQualifier(@NotNull GrReferenceElement ref, @Nullable PsiElement qualifier) {
332 if (ref instanceof GrReferenceExpression) {
333 ((GrReferenceExpression)ref).setQualifierExpression((GrReferenceExpression)qualifier);
335 else if (ref instanceof GrCodeReferenceElement) {
336 ((GrCodeReferenceElement)ref).setQualifier((GrCodeReferenceElement)qualifier);
340 private static boolean mayInsertImport(GrReferenceElement ref) {
341 return PsiTreeUtil.getParentOfType(ref, GrDocComment.class) == null && !(ref.getContainingFile() instanceof GroovyCodeFragment) && PsiTreeUtil.getParentOfType(ref, GrImportStatement.class) == null;
345 public static GrTopLevelDefintion findPreviousTopLevelElementByThisElement(PsiElement element) {
346 PsiElement parent = element.getParent();
348 while (parent != null && !(parent instanceof GrTopLevelDefintion)) {
349 parent = parent.getParent();
352 if (parent == null) return null;
353 return ((GrTopLevelDefintion)parent);
356 public static boolean isStaticsOK(PsiModifierListOwner owner, PsiElement place) {
357 if (owner instanceof PsiMember) {
358 if (place instanceof GrReferenceExpression) {
359 GrExpression qualifier = ((GrReferenceExpression)place).getQualifierExpression();
360 if (qualifier != null) {
361 if (qualifier instanceof GrReferenceExpression) {
362 PsiElement qualifierResolved = ((GrReferenceExpression)qualifier).resolve();
363 if (qualifierResolved instanceof PsiClass || qualifierResolved instanceof PsiPackage) { //static context
364 if (owner instanceof PsiClass) {
367 //members from java.lang.Class can be invoked without ".class"
368 PsiClass javaLangClass = JavaPsiFacade.getInstance(place.getProject()).findClass("java.lang.Class", place.getResolveScope());
369 if (javaLangClass != null) {
370 PsiClass containingClass = ((PsiMember)owner).getContainingClass();
371 if ((containingClass == null) || //default groovy method
372 InheritanceUtil.isInheritorOrSelf(javaLangClass, containingClass, true)) {
376 return owner.hasModifierProperty(PsiModifier.STATIC);
381 if (owner instanceof PsiClass) {
384 return CodeInsightSettings.getInstance().SHOW_STATIC_AFTER_INSTANCE || !owner.hasModifierProperty(PsiModifier.STATIC);
391 public static boolean isAccessible(PsiElement place, PsiMember member) {
393 if (PsiTreeUtil.getParentOfType(place, GrDocComment.class) != null) return true;
394 if (!member.isPhysical()) {
398 if (place instanceof GrReferenceExpression && ((GrReferenceExpression)place).getQualifierExpression() == null) {
399 if (member.getContainingClass() instanceof GroovyScriptClass) { //calling toplevel script members from the same script file
403 return com.intellij.psi.util.PsiUtil.isAccessible(member, place, null);
406 public static void reformatCode(final PsiElement element) {
407 final TextRange textRange = element.getTextRange();
409 CodeStyleManager.getInstance(element.getProject())
410 .reformatText(element.getContainingFile(), textRange.getStartOffset(), textRange.getEndOffset());
412 catch (IncorrectOperationException e) {
417 public static boolean isInStaticContext(GrReferenceExpression refExpression, PsiClass targetClass) {
418 if (refExpression.isQualified()) {
419 GrExpression qualifer = refExpression.getQualifierExpression();
420 if (qualifer instanceof GrReferenceExpression) return ((GrReferenceExpression)qualifer).resolve() instanceof PsiClass;
422 PsiElement run = refExpression;
423 while (run != null && run != targetClass) {
424 if (run instanceof PsiModifierListOwner && ((PsiModifierListOwner)run).hasModifierProperty(PsiModifier.STATIC)) return true;
425 run = run.getParent();
432 public static Iterable<PsiClass> iterateSupers(final @NotNull PsiClass psiClass, final boolean includeSelf) {
433 return new Iterable<PsiClass>() {
434 public Iterator<PsiClass> iterator() {
435 return new Iterator<PsiClass>() {
436 TIntStack indices = new TIntStack();
437 Stack<PsiClassType[]> superTypesStack = new Stack<PsiClassType[]>();
439 boolean nextObtained;
440 Set<PsiClass> visited = new HashSet<PsiClass>();
448 nextObtained = false;
454 public boolean hasNext() {
456 return current != null;
459 private void nextElement() {
460 if (nextObtained) return;
463 while (!superTypesStack.empty()) {
464 assert indices.size() > 0;
466 int i = indices.pop();
467 PsiClassType[] superTypes = superTypesStack.peek();
468 while (i < superTypes.length) {
469 PsiClass clazz = superTypes[i].resolve();
470 if (clazz != null && !visited.contains(clazz)) {
480 superTypesStack.pop();
486 private void pushSuper(PsiClass clazz) {
487 superTypesStack.push(clazz.getSuperTypes());
492 public PsiClass next() {
494 nextObtained = false;
495 if (current == null) throw new NoSuchElementException();
499 public void remove() {
500 throw new IllegalStateException("should not be called");
508 public static PsiClass getContextClass(PsiElement context) {
509 GroovyPsiElement parent = PsiTreeUtil.getParentOfType(context, GrTypeDefinition.class, GroovyFileBase.class);
510 if (parent instanceof GrTypeDefinition) {
511 return (PsiClass)parent;
512 } else if (parent instanceof GroovyFileBase) {
513 return ((GroovyFileBase)parent).getScriptClass();
518 public static boolean mightBeLVlaue(GrExpression expr) {
519 if (expr instanceof GrParenthesizedExpression) return mightBeLVlaue(((GrParenthesizedExpression)expr).getOperand());
521 if (expr instanceof GrListOrMap) {
522 GrListOrMap listOrMap = (GrListOrMap)expr;
523 if (listOrMap.isMap()) return false;
524 GrExpression[] initializers = listOrMap.getInitializers();
525 for (GrExpression initializer : initializers) {
526 if (!mightBeLVlaue(initializer)) return false;
530 if (expr instanceof GrTupleExpression) return true;
531 return expr instanceof GrReferenceExpression || expr instanceof GrIndexProperty || expr instanceof GrPropertySelection;
534 public static boolean isRawMethodCall(GrMethodCallExpression call) {
535 final GroovyResolveResult[] resolveResults = call.getMethodVariants();
536 if (resolveResults.length == 0) return false;
537 final PsiElement element = resolveResults[0].getElement();
538 if (element instanceof PsiMethod) {
539 PsiType returnType = getSmartReturnType((PsiMethod)element);
540 return isRawType(returnType, resolveResults[0].getSubstitutor());
545 public static boolean isRawFieldAccess(GrReferenceExpression ref) {
546 PsiElement element = null;
547 final GroovyResolveResult[] resolveResults = ref.multiResolve(false);
548 if (resolveResults.length == 0) return false;
549 final GroovyResolveResult resolveResult = resolveResults[0];
550 if (resolveResult != null) {
551 element = resolveResult.getElement();
553 if (element instanceof PsiField) {
554 return isRawType(((PsiField)element).getType(), resolveResult.getSubstitutor());
556 else if (element instanceof GrAccessorMethod) {
557 return isRawType(((GrAccessorMethod)element).getReturnType(), resolveResult.getSubstitutor());
562 private static boolean isRawIndexPropertyAccess(GrIndexProperty expr) {
563 final GrExpression qualifier = expr.getSelectedExpression();
564 final PsiType qualifierType = qualifier.getType();
565 if (qualifierType instanceof PsiClassType) {
567 if (InheritanceUtil.isInheritor(qualifierType, CommonClassNames.JAVA_UTIL_LIST)) {
568 return com.intellij.psi.util.PsiUtil.extractIterableTypeParameter(qualifierType, false) == null;
571 if (InheritanceUtil.isInheritor(qualifierType, CommonClassNames.JAVA_UTIL_MAP)) {
572 return com.intellij.psi.util.PsiUtil.substituteTypeParameter(qualifierType, CommonClassNames.JAVA_UTIL_MAP, 1, false) == null;
574 PsiClassType classType = (PsiClassType)qualifierType;
575 final PsiClassType.ClassResolveResult resolveResult = classType.resolveGenerics();
576 GrExpression[] arguments = expr.getArgumentList().getExpressionArguments();
577 PsiType[] argTypes = new PsiType[arguments.length];
578 for (int i = 0; i < arguments.length; i++) {
579 PsiType argType = arguments[i].getType();
580 if (argType == null) argType = TypesUtil.getJavaLangObject(expr);
581 argTypes[i] = argType;
584 MethodResolverProcessor processor = new MethodResolverProcessor("getAt", expr, false, qualifierType, argTypes, PsiType.EMPTY_ARRAY);
586 final PsiClass qClass = resolveResult.getElement();
587 if (qClass != null) {
588 qClass.processDeclarations(processor, ResolveState.initial().put(PsiSubstitutor.KEY, PsiSubstitutor.EMPTY), null, expr);
591 ResolveUtil.processNonCodeMethods(qualifierType, processor, expr.getProject(), expr, false);
592 final GroovyResolveResult[] candidates = processor.getCandidates();
594 if (candidates.length == 1) {
595 final PsiElement element = candidates[0].getElement();
596 if (element instanceof PsiMethod) {
597 type = getSmartReturnType((PsiMethod)element);
600 return isRawType(type, resolveResult.getSubstitutor());
605 public static boolean isRawClassMemberAccess(GrExpression expr) {
606 while (expr instanceof GrParenthesizedExpression) {
607 expr = ((GrParenthesizedExpression)expr).getOperand();
610 if (expr instanceof GrMethodCallExpression) {
611 return isRawMethodCall((GrMethodCallExpression)expr);
613 if (expr instanceof GrReferenceExpression) {
614 return isRawFieldAccess((GrReferenceExpression)expr);
616 if (expr instanceof GrIndexProperty) {
617 return isRawIndexPropertyAccess((GrIndexProperty)expr);
622 public static boolean isRawType(PsiType type, PsiSubstitutor substitutor) {
623 if (type instanceof PsiClassType) {
624 final PsiClass returnClass = ((PsiClassType)type).resolve();
625 if (returnClass instanceof PsiTypeParameter) {
626 final PsiTypeParameter typeParameter = (PsiTypeParameter)returnClass;
627 final PsiType substitutedType = substitutor.substitute(typeParameter);
628 if (substitutedType == null) {
636 public static boolean isNewLine(PsiElement element) {
637 if (element == null) return false;
638 ASTNode node = element.getNode();
639 if (node == null) return false;
640 return node.getElementType() == GroovyTokenTypes.mNLS;
644 public static PsiElement getPrevNonSpace(final PsiElement elem) {
645 PsiElement prevSibling = elem.getPrevSibling();
646 while (prevSibling instanceof PsiWhiteSpace) {
647 prevSibling = prevSibling.getPrevSibling();
653 public static PsiElement getNextNonSpace(final PsiElement elem) {
654 PsiElement nextSibling = elem.getNextSibling();
655 while (nextSibling instanceof PsiWhiteSpace) {
656 nextSibling = nextSibling.getNextSibling();
661 public static PsiIdentifier getJavaNameIdentifier(GrNamedElement namedElement) {
662 final PsiElement element = namedElement.getNameIdentifierGroovy();
663 JavaIdentifier identifier = element.getUserData(NAME_IDENTIFIER);
664 if (identifier == null) {
665 //noinspection SynchronizationOnLocalVariableOrMethodParameter
666 synchronized (element) {
667 identifier = element.getUserData(NAME_IDENTIFIER);
668 if (identifier != null) {
672 identifier = new JavaIdentifier(element.getManager(), element);
673 element.putUserData(NAME_IDENTIFIER, identifier);
680 public static PsiElement findEnclosingStatement(@Nullable PsiElement context) {
681 if (context == null) return null;
682 context = PsiTreeUtil.getParentOfType(context, GrStatement.class, false);
683 while (context != null) {
684 final PsiElement parent = context.getParent();
685 if (parent instanceof GrControlFlowOwner) return context;
691 public static boolean isMethodCall(GrMethodCallExpression call, String methodName) {
692 final GrExpression expression = call.getInvokedExpression();
693 return expression instanceof GrReferenceExpression && methodName.equals(expression.getText().trim());
696 public static boolean hasEnclosingInstanceInScope(PsiClass clazz, PsiElement scope, boolean isSuperClassAccepted) {
697 PsiElement place = scope;
698 while (place != null && place != clazz && !(place instanceof PsiFile)) {
699 if (place instanceof PsiClass) {
700 if (isSuperClassAccepted) {
701 if (InheritanceUtil.isInheritorOrSelf((PsiClass)place, clazz, true)) return true;
704 if (clazz.getManager().areElementsEquivalent(place, clazz)) return true;
707 if (place instanceof PsiModifierListOwner && ((PsiModifierListOwner)place).hasModifierProperty(PsiModifier.STATIC)) return false;
708 place = place.getParent();
710 return place == clazz;
714 public static PsiElement skipWhitespaces(@Nullable PsiElement elem, boolean forward) {
715 //noinspection ConstantConditions
716 while (elem != null &&
717 elem.getNode() != null &&
718 GroovyElementTypes.WHITE_SPACES_OR_COMMENTS.contains(elem.getNode().getElementType())) {
720 elem = elem.getNextSibling();
723 elem = elem.getPrevSibling();
730 public static PsiType getSmartReturnType(PsiMethod method) {
731 if (method instanceof GrMethod) {
732 return ((GrMethod)method).getInferredReturnType();
734 else if (method instanceof GrAccessorMethod) {
735 return ((GrAccessorMethod)method).getInferredReturnType();
738 return method.getReturnType();
742 public static boolean isMethodUsage(PsiElement element) {
743 if (element instanceof GrEnumConstant) return true;
744 if (!(element instanceof GrReferenceElement)) return false;
745 PsiElement parent = element.getParent();
746 if (parent instanceof GrCall) {
749 else if (parent instanceof GrAnonymousClassDefinition) {
750 return element.equals(((GrAnonymousClassDefinition)parent).getBaseClassReferenceGroovy());
755 public static GroovyResolveResult[] getConstructorCandidates(GroovyPsiElement place, GroovyResolveResult[] classCandidates, PsiType[] argTypes) {
756 List<GroovyResolveResult> constructorResults = new ArrayList<GroovyResolveResult>();
757 for (GroovyResolveResult classResult : classCandidates) {
758 final PsiElement element = classResult.getElement();
759 if (element instanceof PsiClass) {
760 final GroovyPsiElement context = classResult.getCurrentFileResolveContext();
761 PsiClass clazz = (PsiClass)element;
762 String className = clazz.getName();
763 PsiType thisType = JavaPsiFacade.getInstance(place.getProject()).getElementFactory().createType(clazz, classResult.getSubstitutor());
764 final MethodResolverProcessor processor = new MethodResolverProcessor(className, place, true, thisType, argTypes, PsiType.EMPTY_ARRAY);
765 PsiSubstitutor substitutor = classResult.getSubstitutor();
766 final ResolveState state =
767 ResolveState.initial().put(PsiSubstitutor.KEY, substitutor).put(ResolverProcessor.RESOLVE_CONTEXT, context);
768 final boolean toBreak = element.processDeclarations(processor, state, null, place);
770 for (NonCodeMembersProcessor membersProcessor : NonCodeMembersProcessor.EP_NAME.getExtensions()) {
771 if (!membersProcessor.processNonCodeMembers(thisType, processor, place, true)) break;
773 constructorResults.addAll(Arrays.asList(processor.getCandidates()));
778 return constructorResults.toArray(new GroovyResolveResult[constructorResults.size()]);