All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil Maven / Gradle / Ivy

Go to download

A packaging of the IntelliJ Community Edition groovy-psi library. This is release number 1 of trunk branch 142.

The newest version!
/*
 * Copyright 2000-2014 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.jetbrains.plugins.groovy.lang.psi.util;

import com.intellij.lang.ASTNode;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.Trinity;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.impl.light.JavaIdentifier;
import com.intellij.psi.impl.light.LightElement;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import com.intellij.psi.util.*;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.VisibilityUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashSet;
import gnu.trove.TIntStack;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils;
import org.jetbrains.plugins.groovy.config.GroovyConfigUtils;
import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocComment;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyLexer;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
import org.jetbrains.plugins.groovy.lang.psi.*;
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.*;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrSpreadArgument;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrAssertStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrReturnStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrThrowStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.clauses.GrCaseSection;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.clauses.GrForInClause;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrIndexProperty;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrPropertySelection;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousClassDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.*;
import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
import org.jetbrains.plugins.groovy.lang.psi.api.util.GrNamedArgumentsOwner;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction;
import org.jetbrains.plugins.groovy.lang.psi.dataFlow.types.TypeInferenceHelper;
import org.jetbrains.plugins.groovy.lang.psi.impl.*;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrBindingVariable;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass;
import org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.ClosureParameterEnhancer;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
import org.jetbrains.plugins.groovy.lang.resolve.processors.MethodResolverProcessor;

import java.util.*;

/**
 * @author ven
 */
public class PsiUtil {
  public static final Logger LOG = Logger.getInstance("org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil");
  public static final Key NAME_IDENTIFIER = new Key("Java Identifier");
  public static final Set OPERATOR_METHOD_NAMES = ContainerUtil.newHashSet(
    "plus", "minus", "multiply", "power", "div", "mod", "or", "and", "xor", "next", "previous", "getAt", "putAt", "leftShift", "rightShift",
    "isCase", "bitwiseNegate", "negative", "positive", "call"
  );

  private PsiUtil() {
  }

  @Nullable
  public static PsiElement findModifierInList(@NotNull GrModifierList list, @GrModifier.GrModifierConstant @NotNull String modifier) {
    for (PsiElement element : list.getModifiers()) {
      if (modifier.equals(element.getText())) return element;
    }
    return null;
  }

  @Nullable
  public static String getMethodName(GrMethodCall methodCall) {
    GrExpression invokedExpression = methodCall.getInvokedExpression();
    if (!(invokedExpression instanceof GrReferenceExpression)) return null;

    return ((GrReferenceExpression)invokedExpression).getReferenceName();
  }

  @Nullable
  public static String getUnqualifiedMethodName(GrMethodCall methodCall) {
    GrExpression invokedExpression = methodCall.getInvokedExpression();
    if (!(invokedExpression instanceof GrReferenceExpression)) return null;

    if (((GrReferenceExpression)invokedExpression).isQualified()) return null;

    return ((GrReferenceExpression)invokedExpression).getReferenceName();
  }

  @Nullable
  public static String getQualifiedReferenceText(GrCodeReferenceElement referenceElement) {
    StringBuilder builder = new StringBuilder();
    if (!appendName(referenceElement, builder)) return null;

    return builder.toString();
  }

  private static boolean appendName(GrCodeReferenceElement referenceElement, StringBuilder builder) {
    String refName = referenceElement.getReferenceName();
    if (refName == null) return false;
    GrCodeReferenceElement qualifier = referenceElement.getQualifier();
    if (qualifier != null) {
      appendName(qualifier, builder);
      builder.append(".");
    }

    builder.append(refName);
    return true;
  }

  public static boolean isLValue(GroovyPsiElement element) {
    if (element instanceof GrExpression) {
      PsiElement parent = PsiTreeUtil.skipParentsOfType(element, GrParenthesizedExpression.class);
      if (parent instanceof GrTupleExpression) {
        return isLValue((GroovyPsiElement)parent);
      }
      return parent instanceof GrAssignmentExpression &&
             PsiTreeUtil.isAncestor(((GrAssignmentExpression)parent).getLValue(), element, false);
    }
    return false;
  }

  public static boolean isApplicable(@Nullable PsiType[] argumentTypes,
                                     PsiMethod method,
                                     PsiSubstitutor substitutor,
                                     PsiElement place,
                                     final boolean eraseParameterTypes) {
    return isApplicableConcrete(argumentTypes, method, substitutor, place, eraseParameterTypes) !=
           GrClosureSignatureUtil.ApplicabilityResult.inapplicable;
  }

  public static GrClosureSignatureUtil.ApplicabilityResult isApplicableConcrete(@Nullable PsiType[] argumentTypes,
                                                                                PsiMethod method,
                                                                                PsiSubstitutor substitutor,
                                                                                PsiElement place,
                                                                                final boolean eraseParameterTypes) {
    if (argumentTypes == null) return GrClosureSignatureUtil.ApplicabilityResult.canBeApplicable;

    GrClosureSignature signature = eraseParameterTypes
                                   ? GrClosureSignatureUtil.createSignatureWithErasedParameterTypes(method)
                                   : GrClosureSignatureUtil.createSignature(method, substitutor);

    //check for default constructor
    if (method.isConstructor()) {
      final PsiParameter[] parameters = method.getParameterList().getParameters();
      if (parameters.length == 0 && argumentTypes.length == 1) {
        return InheritanceUtil.isInheritor(argumentTypes[0], CommonClassNames.JAVA_UTIL_MAP)
               ? GrClosureSignatureUtil.ApplicabilityResult.applicable
               : GrClosureSignatureUtil.ApplicabilityResult.inapplicable;
      }
      if (parameters.length == 1 &&
          argumentTypes.length == 0 &&
          InheritanceUtil.isInheritor(parameters[0].getType(), CommonClassNames.JAVA_UTIL_MAP)) {
        return GrClosureSignatureUtil.ApplicabilityResult.inapplicable;
      }
    }
    LOG.assertTrue(signature != null);
    GrClosureSignatureUtil.ApplicabilityResult result =
      GrClosureSignatureUtil.isSignatureApplicableConcrete(signature, argumentTypes, place);
    if (result != GrClosureSignatureUtil.ApplicabilityResult.inapplicable) {
      return result;
    }

    if (method instanceof GrBuilderMethod && !((GrBuilderMethod)method).hasObligatoryNamedArguments()) {
      final PsiParameter[] parameters = method.getParameterList().getParameters();
      if (parameters.length > 0 && parameters[0].getType() instanceof GrMapType &&
          (argumentTypes.length == 0 || !(argumentTypes[0] instanceof GrMapType))) {
        return GrClosureSignatureUtil.isSignatureApplicableConcrete(GrClosureSignatureUtil.removeParam(signature, 0), argumentTypes, place);
      }
    }
    return GrClosureSignatureUtil.ApplicabilityResult.inapplicable;
  }

  public static boolean isApplicable(@Nullable PsiType[] argumentTypes,
                                     GrClosureType type,
                                     GroovyPsiElement context) {
    return isApplicableConcrete(argumentTypes, type, context) != GrClosureSignatureUtil.ApplicabilityResult.inapplicable;
  }

  public static GrClosureSignatureUtil.ApplicabilityResult isApplicableConcrete(@Nullable PsiType[] argumentTypes,
                                                                                GrClosureType type,
                                                                                GroovyPsiElement context) {
    if (argumentTypes == null) return GrClosureSignatureUtil.ApplicabilityResult.canBeApplicable;

    GrSignature signature = type.getSignature();
    return GrClosureSignatureUtil.isSignatureApplicableConcrete(signature, argumentTypes, context);
  }

  @Nullable
  public static GrArgumentList getArgumentsList(@Nullable PsiElement methodRef) {
    if (methodRef == null) return null;

    if (methodRef instanceof GrEnumConstant) return ((GrEnumConstant)methodRef).getArgumentList();
    PsiElement parent = methodRef.getParent();
    if (parent instanceof GrCall) {
      return ((GrCall)parent).getArgumentList();
    }
    if (parent instanceof GrAnonymousClassDefinition) {
      return ((GrAnonymousClassDefinition)parent).getArgumentListGroovy();
    }
    return null;
  }

  @Nullable
  public static PsiType[] getArgumentTypes(@Nullable PsiElement place, boolean nullAsBottom) {
    return getArgumentTypes(place, nullAsBottom, null, false);
  }

  @Nullable
  public static PsiType[] getArgumentTypes(@Nullable PsiElement place,
                                           boolean nullAsBottom,
                                           @Nullable GrExpression stopAt,
                                           boolean byShape) {
    PsiElement parent = place instanceof GrEnumConstant ? place : place != null ? place.getParent() : null;

    if (parent instanceof GrIndexProperty) {
      GrIndexProperty index = (GrIndexProperty)parent;
      PsiType[] argTypes = getArgumentTypes(index.getNamedArguments(), index.getExpressionArguments(), index.getClosureArguments(), nullAsBottom, stopAt, byShape);
      if (isLValue(index) && argTypes != null) {
        PsiType rawInitializer = TypeInferenceHelper.getInitializerTypeFor(index);

        PsiType initializer = notNullizeType(rawInitializer, nullAsBottom, index);
        return ArrayUtil.append(argTypes, initializer);
      }
      else {
        return argTypes;
      }
    }
    if (parent instanceof GrCall) {
      GrCall call = (GrCall)parent;
      GrNamedArgument[] namedArgs = call.getNamedArguments();
      GrExpression[] expressions = call.getExpressionArguments();
      GrClosableBlock[] closures = call.getClosureArguments();

      return getArgumentTypes(namedArgs, expressions, closures, nullAsBottom, stopAt, byShape);
    }
    else if (parent instanceof GrAnonymousClassDefinition) {
      final GrArgumentList argList = ((GrAnonymousClassDefinition)parent).getArgumentListGroovy();
      if (argList == null) {
        return getArgumentTypes(GrNamedArgument.EMPTY_ARRAY, GrExpression.EMPTY_ARRAY, GrClosableBlock.EMPTY_ARRAY, nullAsBottom, stopAt, byShape);
      }
      else {
        return getArgumentTypes(argList.getNamedArguments(), argList.getExpressionArguments(), GrClosableBlock.EMPTY_ARRAY, nullAsBottom, stopAt, byShape);
      }
    }
    else if (parent instanceof GrBinaryExpression) {
      GrExpression right = ((GrBinaryExpression)parent).getRightOperand();
      PsiType type = right != null ? right.getType() : null;
      return new PsiType[] {notNullizeType(type, nullAsBottom, parent)};
    }

    return null;
  }

  @Contract("_, false, _ -> !null; !null, _, _ -> !null; null, true, _ -> null")
  private static PsiType notNullizeType(PsiType type, boolean acceptNull, PsiElement context) {
    return type != null || acceptNull ? type : TypesUtil.getJavaLangObject(context);
  }

  @Nullable
  public static PsiType[] getArgumentTypes(GrArgumentList argList) {
    return getArgumentTypes(argList, false, null, false);
  }

  @Nullable
  public static PsiType[] getArgumentTypes(@NotNull GrNamedArgument[] namedArgs,
                                           @NotNull GrExpression[] expressions,
                                           @NotNull GrClosableBlock[] closures,
                                           boolean nullAsBottom,
                                           @Nullable GrExpression stopAt,
                                           boolean byShape) {
    List result = new ArrayList();

    if (namedArgs.length > 0) {
      GrNamedArgument context = namedArgs[0];
      result.add(GrMapType.createFromNamedArgs(context, byShape ? new GrNamedArgument[0] : namedArgs));
    }

    for (GrExpression expression : expressions) {
      PsiType type = expression.getType();
      if (expression instanceof GrSpreadArgument) {
        if (type instanceof GrTupleType) {
          result.addAll(Arrays.asList(((GrTupleType)type).getComponentTypes()));
        }
        else {
          return null;
        }
      }
      else {
        if (type == null) {
          result.add(nullAsBottom ? null : TypesUtil.getJavaLangObject(expression));
        }
        else {
          if (stopAt == expression) {
            type = TypeConversionUtil.erasure(type);
          }
          result.add(type);
        }
      }

      if (stopAt == expression) {
        return result.toArray(PsiType.createArray(result.size()));
      }
    }

    for (GrClosableBlock closure : closures) {
      PsiType closureType = closure.getType();
      if (closureType != null) {
        if (stopAt == closure) {
          closureType = TypeConversionUtil.erasure(closureType);
        }
        result.add(notNullizeType(closureType, nullAsBottom, closure));
      }
      if (stopAt == closure) {
        break;
      }
    }

    return result.toArray(PsiType.createArray(result.size()));
  }

  @Nullable
  public static PsiClass getJavaLangClass(PsiElement resolved, GlobalSearchScope scope) {
    return JavaPsiFacade.getInstance(resolved.getProject()).findClass(CommonClassNames.JAVA_LANG_CLASS, scope);
  }

  public static boolean isValidReferenceName(@NotNull String text) {
    final GroovyLexer lexer = new GroovyLexer();
    lexer.start(text);
    return TokenSets.REFERENCE_NAMES_WITHOUT_NUMBERS.contains(lexer.getTokenType()) && lexer.getTokenEnd() == text.length();
  }

  public static boolean isAccessible(@NotNull PsiElement place, @NotNull PsiMember member) {
    if (member instanceof LightElement) {
      return true;
    }

    if (place instanceof GrReferenceExpression && ((GrReferenceExpression)place).getQualifierExpression() == null) {
      if (member.getContainingClass() instanceof GroovyScriptClass) { //calling top level script members from the same script file
        return true;
      }
    }

    if (PsiTreeUtil.getParentOfType(place, GrDocComment.class) != null) return true;

    return com.intellij.psi.util.PsiUtil.isAccessible(member, place, null);
  }

  public static void reformatCode(final PsiElement element) {
    final TextRange textRange = element.getTextRange();

    PsiFile file = element.getContainingFile();
    FileViewProvider viewProvider = file.getViewProvider();

    if (viewProvider instanceof MultiplePsiFilesPerDocumentFileViewProvider) {
      MultiplePsiFilesPerDocumentFileViewProvider multiProvider = (MultiplePsiFilesPerDocumentFileViewProvider)viewProvider;
      file = multiProvider.getPsi(multiProvider.getBaseLanguage());
      LOG.assertTrue(file != null, element + " " + multiProvider.getBaseLanguage());
    }

    try {
      CodeStyleManager.getInstance(element.getProject())
        .reformatText(file, textRange.getStartOffset(), textRange.getEndOffset());
    }
    catch (IncorrectOperationException e) {
      LOG.error(e);
    }
  }

  public static Iterable iterateSupers(@NotNull final PsiClass psiClass, final boolean includeSelf) {
    return new Iterable() {
      @Override
      public Iterator iterator() {
        return new Iterator() {
          TIntStack indices = new TIntStack();
          Stack superTypesStack = new Stack();
          PsiClass current;
          boolean nextObtained;
          Set visited = new HashSet();

          {
            if (includeSelf) {
              current = psiClass;
              nextObtained = true;
            }
            else {
              current = null;
              nextObtained = false;
            }

            pushSuper(psiClass);
          }

          @Override
          public boolean hasNext() {
            nextElement();
            return current != null;
          }

          private void nextElement() {
            if (nextObtained) return;

            nextObtained = true;
            while (!superTypesStack.empty()) {
              assert indices.size() > 0;

              int i = indices.pop();
              PsiClassType[] superTypes = superTypesStack.peek();
              while (i < superTypes.length) {
                PsiClass clazz = superTypes[i].resolve();
                if (clazz != null && !visited.contains(clazz)) {
                  current = clazz;
                  visited.add(clazz);
                  indices.push(i + 1);
                  pushSuper(clazz);
                  return;
                }
                i++;
              }

              superTypesStack.pop();
            }

            current = null;
          }

          private void pushSuper(PsiClass clazz) {
            superTypesStack.push(clazz.getSuperTypes());
            indices.push(0);
          }

          @Override
          @NotNull
          public PsiClass next() {
            nextElement();
            nextObtained = false;
            if (current == null) throw new NoSuchElementException();
            return current;
          }

          @Override
          public void remove() {
            throw new IllegalStateException("should not be called");
          }
        };
      }
    };
  }

  @Nullable
  public static PsiClass getContextClass(@Nullable PsiElement context) {
    while (context != null) {
      if (context instanceof PsiClass && !isInDummyFile(context)) {
        return (PsiClass)context;
      }
      else if (context instanceof GroovyFileBase && !isInDummyFile(context)) {
        return ((GroovyFileBase)context).getScriptClass();
      }

      context = context.getContext();
    }
    return null;
  }

  public static boolean isInDummyFile(@NotNull PsiElement context) {
    PsiFile file = context.getContainingFile();
    if (file == null) return false;

    String name = file.getName();
    return name.startsWith(GroovyPsiElementFactory.DUMMY_FILE_NAME);
  }

  @Nullable
  public static GroovyPsiElement getFileOrClassContext(PsiElement context) {
    while (context != null) {
      if (context instanceof GrTypeDefinition) {
        return (GroovyPsiElement)context;
      }
      else if (context instanceof GroovyFileBase && context.isPhysical()) {
        return (GroovyPsiElement)context;
      }

      context = context.getContext();
    }

    return null;
  }

  public static boolean mightBeLValue(@Nullable GrExpression expr) {
    if (expr instanceof GrParenthesizedExpression) return mightBeLValue(((GrParenthesizedExpression)expr).getOperand());

    if (expr instanceof GrTupleExpression ||
        expr instanceof GrReferenceExpression ||
        expr instanceof GrIndexProperty ||
        expr instanceof GrPropertySelection) {
      return true;
    }

    if ((isThisOrSuperRef(expr)) &&
        GroovyConfigUtils.getInstance().isVersionAtLeast(expr, GroovyConfigUtils.GROOVY1_8)) {
      return true;
    }
    return false;
  }

  public static boolean isRawMethodCall(GrMethodCallExpression call) {
    final GroovyResolveResult result = call.advancedResolve();
    final PsiElement element = result.getElement();
    if (element == null) return false;
    if (element instanceof PsiMethod) {
      PsiType returnType = getSmartReturnType((PsiMethod)element);
      final GrExpression expression = call.getInvokedExpression();
      if (expression instanceof GrReferenceExpression && result.isInvokedOnProperty()) {
        if (returnType instanceof GrClosureType) {
          return isRawClosureCall(call, result, (GrClosureType)returnType);
        }
      }
      else {
        return isRawType(returnType, result.getSubstitutor());
      }
    }
    if (element instanceof PsiVariable) {
      GrExpression expression = call.getInvokedExpression();
      final PsiType type = expression.getType();
      if (type instanceof GrClosureType) {
        return isRawClosureCall(call, result, (GrClosureType)type);
      }
    }

    return false;
  }

  private static boolean isRawClosureCall(GrMethodCallExpression call, GroovyResolveResult result, GrClosureType returnType) {
    final GrSignature signature = returnType.getSignature();
    GrClosureSignature _signature;
    if (signature instanceof GrClosureSignature) {
      _signature = (GrClosureSignature)signature;
    }
    else {
      final PsiType[] types = getArgumentTypes(call.getInvokedExpression(), true);
      final Trinity[], GrClosureSignatureUtil.ApplicabilityResult>
        resultTrinity = types != null ? GrClosureSignatureUtil.getApplicableSignature(signature, types, call) : null;
      _signature = resultTrinity != null ? resultTrinity.first : null;
    }
    if (_signature != null) {
      return isRawType(_signature.getReturnType(), TypesUtil.composeSubstitutors(_signature.getSubstitutor(), result.getSubstitutor()));
    }
    return false;
  }

  public static boolean isRawFieldAccess(GrReferenceExpression ref) {
    PsiElement element = null;
    final GroovyResolveResult[] resolveResults = ref.multiResolve(false);
    if (resolveResults.length == 0) return false;
    final GroovyResolveResult resolveResult = resolveResults[0];
    if (resolveResult != null) {
      element = resolveResult.getElement();
    }
    if (element instanceof PsiField) {
      return isRawType(((PsiField)element).getType(), resolveResult.getSubstitutor());
    }
    else if (element instanceof GrAccessorMethod) {
      return isRawType(((GrAccessorMethod)element).getReturnType(), resolveResult.getSubstitutor());
    }
    return false;
  }

  private static boolean isRawIndexPropertyAccess(GrIndexProperty expr) {
    final GrExpression qualifier = expr.getInvokedExpression();
    final PsiType qualifierType = qualifier.getType();
    if (qualifierType instanceof PsiClassType) {

      if (InheritanceUtil.isInheritor(qualifierType, CommonClassNames.JAVA_UTIL_LIST)) {
        return com.intellij.psi.util.PsiUtil.extractIterableTypeParameter(qualifierType, false) == null;
      }

      if (InheritanceUtil.isInheritor(qualifierType, CommonClassNames.JAVA_UTIL_MAP)) {
        return com.intellij.psi.util.PsiUtil.substituteTypeParameter(qualifierType, CommonClassNames.JAVA_UTIL_MAP, 1, false) == null;
      }
      PsiClassType classType = (PsiClassType)qualifierType;
      final PsiClassType.ClassResolveResult resolveResult = classType.resolveGenerics();
      GrExpression[] arguments = expr.getArgumentList().getExpressionArguments();
      PsiType[] argTypes = PsiType.createArray(arguments.length);
      for (int i = 0; i < arguments.length; i++) {
        PsiType argType = arguments[i].getType();
        if (argType == null) argType = TypesUtil.getJavaLangObject(expr);
        argTypes[i] = argType;
      }

      MethodResolverProcessor processor = new MethodResolverProcessor("getAt", expr, false, qualifierType, argTypes, PsiType.EMPTY_ARRAY);

      final PsiClass qClass = resolveResult.getElement();
      final ResolveState state = ResolveState.initial().put(PsiSubstitutor.KEY, PsiSubstitutor.EMPTY);
      if (qClass != null) {
        qClass.processDeclarations(processor, state, null, expr);
      }

      ResolveUtil.processNonCodeMembers(qualifierType, processor, qualifier, state);
      final GroovyResolveResult[] candidates = processor.getCandidates();
      PsiType type = null;
      if (candidates.length == 1) {
        final PsiElement element = candidates[0].getElement();
        if (element instanceof PsiMethod) {
          type = getSmartReturnType((PsiMethod)element);
        }
      }
      return isRawType(type, resolveResult.getSubstitutor());
    }
    return false;
  }

  public static boolean isRawClassMemberAccess(GrExpression expr) {
    expr = (GrExpression)skipParentheses(expr, false);

    if (expr instanceof GrMethodCallExpression) {
      return isRawMethodCall((GrMethodCallExpression)expr);
    }
    if (expr instanceof GrReferenceExpression) {
      return isRawFieldAccess((GrReferenceExpression)expr);
    }
    if (expr instanceof GrIndexProperty) {
      return isRawIndexPropertyAccess((GrIndexProperty)expr);
    }
    return false;
  }

  public static boolean isRawType(@Nullable PsiType type, @NotNull PsiSubstitutor substitutor) {
    if (type instanceof PsiClassType) {
      final PsiClass returnClass = ((PsiClassType)type).resolve();
      if (returnClass instanceof PsiTypeParameter) {
        final PsiTypeParameter typeParameter = (PsiTypeParameter)returnClass;
        return substitutor.substitute(typeParameter) == null;
      }
    }
    return false;
  }

  public static boolean isNewLine(PsiElement element) {
    if (element == null) return false;
    ASTNode node = element.getNode();
    if (node == null) return false;
    IElementType elementType = node.getElementType();
    return elementType == GroovyTokenTypes.mNLS || elementType == TokenType.WHITE_SPACE && element.getText().contains("\n");
  }

  @Nullable
  public static PsiElement getPrevNonSpace(@NotNull final PsiElement elem) {
    PsiElement prevSibling = elem.getPrevSibling();
    while (prevSibling instanceof PsiWhiteSpace) {
      prevSibling = prevSibling.getPrevSibling();
    }
    return prevSibling;
  }

  @Nullable
  public static PsiElement getNextNonSpace(final PsiElement elem) {
    PsiElement nextSibling = elem.getNextSibling();
    while (nextSibling instanceof PsiWhiteSpace) {
      nextSibling = nextSibling.getNextSibling();
    }
    return nextSibling;
  }

  @NotNull
  public static PsiIdentifier getJavaNameIdentifier(@NotNull GrNamedElement namedElement) {
    final PsiElement element = namedElement.getNameIdentifierGroovy();
    JavaIdentifier identifier = element.getUserData(NAME_IDENTIFIER);
    if (identifier == null) {
      //noinspection SynchronizationOnLocalVariableOrMethodParameter
      synchronized (element) {
        identifier = element.getUserData(NAME_IDENTIFIER);
        if (identifier != null) {
          return identifier;
        }

        identifier = new JavaIdentifier(element.getManager(), element);
        element.putUserData(NAME_IDENTIFIER, identifier);
      }
    }
    return identifier;
  }

  @Nullable
  public static GrStatement findEnclosingStatement(@Nullable PsiElement context) {
    while (context != null) {
      if (isExpressionStatement(context)) return (GrStatement)context;
      context = PsiTreeUtil.getParentOfType(context, GrStatement.class, true);
    }
    return null;
  }

  public static boolean isMethodCall(GrMethodCall call, String methodName) {
    final GrExpression expression = call.getInvokedExpression();
    return expression instanceof GrReferenceExpression && methodName.equals(expression.getText().trim());
  }
  public static boolean hasEnclosingInstanceInScope(@NotNull PsiClass clazz, @Nullable PsiElement scope, boolean isSuperClassAccepted) {
    return findEnclosingInstanceClassInScope(clazz, scope, isSuperClassAccepted) != null;
  }

  public static PsiClass findEnclosingInstanceClassInScope(@NotNull PsiClass clazz, @Nullable PsiElement scope, boolean isInheritorOfClazzAccepted) {
    PsiElement place = scope;
    while (place != null && place != clazz && !(place instanceof PsiFile && place.isPhysical())) {
      if (place instanceof PsiClass) {
        if (isInheritorOfClazzAccepted) {
          if (InheritanceUtil.isInheritorOrSelf((PsiClass)place, clazz, true)) return (PsiClass)place;
        }
        else {
          if (clazz.getManager().areElementsEquivalent(place, clazz)) return (PsiClass)place;
        }
      }
      if (place instanceof PsiModifierListOwner && ((PsiModifierListOwner)place).hasModifierProperty(PsiModifier.STATIC)) return null;
      place = place.getContext();
    }
    if (clazz instanceof GroovyScriptClass && place == clazz.getContainingFile() || place == clazz) {
      return clazz;
    }
    return null;
  }


  @Nullable
  public static PsiElement skipWhitespacesAndComments(@Nullable PsiElement elem, boolean forward, boolean skipNLs) {
    return skipSet(elem, forward, TokenSets.WHITE_SPACES_OR_COMMENTS, skipNLs);
  }


  @Nullable
  public static PsiElement skipWhitespacesAndComments(@Nullable PsiElement elem, boolean forward) {
    return skipSet(elem, forward, TokenSets.WHITE_SPACES_OR_COMMENTS, true);
  }

  private static PsiElement skipSet(PsiElement elem, boolean forward, TokenSet set, boolean skipNLs) {
    while (elem != null &&
           elem.getNode() != null &&
           set.contains(elem.getNode().getElementType()) &&
           (skipNLs || elem.getText().indexOf('\n') == -1)) {
      if (forward) {
        elem = elem.getNextSibling();
      }
      else {
        elem = elem.getPrevSibling();
      }
    }
    return elem;
  }

  @Nullable
  public static PsiElement skipWhitespaces(@Nullable PsiElement elem, boolean forward) {
    return skipSet(elem, forward, TokenSets.WHITE_SPACES_SET, true);
  }


  @Nullable
  public static PsiType getSmartReturnType(@NotNull PsiMethod method) {
    if (method instanceof GrMethod) {
      return ((GrMethod)method).getInferredReturnType();
    }
    else if (method instanceof GrAccessorMethod) {
      return ((GrAccessorMethod)method).getInferredReturnType();
    }
    else if (method instanceof GrGdkMethod) {
      return getSmartReturnType(((GrGdkMethod)method).getStaticMethod());
    }
    else {
      return method.getReturnType();
    }
  }

  public static boolean isClosurePropertyGetter(PsiMethod method) {
    String methodName = method.getName();
    if (methodName.startsWith("get") && GroovyPropertyUtils.isGetterName(methodName)) { // exclude isXXX()
      PsiModifierList modifiers = method.getModifierList();

      if (!modifiers.hasModifierProperty(PsiModifier.STATIC)
          && !modifiers.hasModifierProperty(PsiModifier.PRIVATE)
          && !modifiers.hasModifierProperty(PsiModifier.PROTECTED)
          && method.getParameterList().getParametersCount() == 0) {
        final PsiType type = getSmartReturnType(method);
        if (type != null && (TypesUtil.isClassType(type, CommonClassNames.JAVA_LANG_OBJECT) || TypesUtil.isClassType(type,
                                                                                                                     GroovyCommonClassNames.GROOVY_LANG_CLOSURE))) {
          return true;
        }
      }
    }

    return false;
  }

  public static boolean isMethodUsage(PsiElement element) {
    if (element instanceof GrEnumConstant) return true;
    if (!(element instanceof GrReferenceElement)) return false;
    PsiElement parent = element.getParent();
    if (parent instanceof GrCall) {
      return true;
    }
    else if (parent instanceof GrAnonymousClassDefinition) {
      return element.equals(((GrAnonymousClassDefinition)parent).getBaseClassReferenceGroovy());
    }
    return false;
  }

  @NotNull
  public static GroovyResolveResult[] getConstructorCandidates(@NotNull PsiElement place,
                                                               @NotNull GroovyResolveResult classCandidate,
                                                               @Nullable PsiType[] argTypes) {
    final PsiElement element = classCandidate.getElement();
    if (!(element instanceof PsiClass)) return GroovyResolveResult.EMPTY_ARRAY;

    PsiClass clazz = (PsiClass)element;
    PsiSubstitutor substitutor = classCandidate.getSubstitutor();
    return ResolveUtil.getAllClassConstructors(clazz, substitutor, argTypes, place);
  }

  public static boolean isAccessedForReading(GrExpression expr) {
    return !isLValue(expr);
  }

  public static boolean isAccessedForWriting(GrExpression expr) {
    return isLValue(expr) || isUsedInIncOrDec(expr);
  }

  public static boolean isUsedInIncOrDec(GrExpression expr) {
    PsiElement parent = PsiTreeUtil.skipParentsOfType(expr, GrParenthesizedExpression.class);

    if (parent instanceof GrUnaryExpression) {
      IElementType tokenType = ((GrUnaryExpression)parent).getOperationTokenType();
      return tokenType == GroovyTokenTypes.mINC || tokenType == GroovyTokenTypes.mDEC;
    }
    return false;
  }

  public static GrReferenceExpression qualifyMemberReference(GrReferenceExpression refExpr, PsiMember member, String name) {
    assert refExpr.getQualifierExpression() == null;

    final PsiClass clazz = member.getContainingClass();
    assert clazz != null;

    final PsiElement replaced;
    if (member.hasModifierProperty(PsiModifier.STATIC)) {
      final GrReferenceExpression newRefExpr = GroovyPsiElementFactory.getInstance(member.getProject())
        .createReferenceExpressionFromText(clazz.getQualifiedName() + "." + name);
      replaced = refExpr.replace(newRefExpr);
    }
    else {
      final PsiClass containingClass = PsiTreeUtil.getParentOfType(refExpr, PsiClass.class);
      if (member.getManager().areElementsEquivalent(containingClass, clazz)) {
        final GrReferenceExpression newRefExpr = GroovyPsiElementFactory.getInstance(member.getProject())
          .createReferenceExpressionFromText("this." + name);
        replaced = refExpr.replace(newRefExpr);
      }
      else {
        final GrReferenceExpression newRefExpr = GroovyPsiElementFactory.getInstance(member.getProject())
          .createReferenceExpressionFromText(clazz.getName() + ".this." + name);
        replaced = refExpr.replace(newRefExpr);
      }
    }
    return (GrReferenceExpression)replaced;
  }

  public static GroovyResolveResult[] getConstructorCandidates(PsiClassType classType, PsiType[] argTypes, GroovyPsiElement context) {
    final PsiClassType.ClassResolveResult resolveResult = classType.resolveGenerics();
    final PsiClass psiClass = resolveResult.getElement();
    final PsiSubstitutor substitutor = resolveResult.getSubstitutor();
    if (psiClass == null) {
      return GroovyResolveResult.EMPTY_ARRAY;
    }

    final GroovyResolveResult grResult = resolveResult instanceof GroovyResolveResult
                                         ? (GroovyResolveResult)resolveResult
                                         : new GroovyResolveResultImpl(psiClass, context, null, substitutor, true, true);
    return getConstructorCandidates(context, grResult, argTypes);
  }

  @Nullable
  public static PsiElement skipParentheses(@Nullable PsiElement element, boolean up) {
    if (element == null) return null;
    if (up) {
      PsiElement parent;
      while ((parent = element.getParent()) instanceof GrParenthesizedExpression) {
        element = parent;
      }
      return element;
    }
    else {
      while (element instanceof GrParenthesizedExpression) {
        element = ((GrParenthesizedExpression)element).getOperand();
      }
      return element;
    }
  }

  @NotNull
  public static PsiElement skipParenthesesIfSensibly(@NotNull PsiElement element, boolean up) {
    PsiElement res = skipParentheses(element, up);
    return res == null ? element : res;
  }


  @Nullable
  public static PsiElement getNamedArgumentValue(GrNamedArgument otherNamedArgument, String argumentName) {
    PsiElement parent = otherNamedArgument.getParent();

    if (!(parent instanceof GrNamedArgumentsOwner)) return null;

    GrNamedArgument namedArgument = ((GrNamedArgumentsOwner)parent).findNamedArgument(argumentName);
    if (namedArgument == null) return null;

    return namedArgument.getExpression();
  }

  @NotNull
  public static PsiClass getOriginalClass(@NotNull PsiClass aClass) {
    PsiFile file = aClass.getContainingFile();
    if (file == null) return aClass;

    PsiFile originalFile = file.getOriginalFile();
    if (originalFile == file) return aClass;

    if (!(originalFile instanceof PsiClassOwner)) return aClass;

    String name = aClass.getName();
    if (name == null) return aClass;

    for (PsiClass originalClass : ((PsiClassOwner)originalFile).getClasses()) {
      if (name.equals(originalClass.getName())) {
        return originalClass;
      }
    }

    return aClass;
  }


  private static final String[] visibilityModifiers = new String[]{PsiModifier.PRIVATE, PsiModifier.PROTECTED, PsiModifier.PUBLIC};

  public static void escalateVisibility(PsiMember owner, PsiElement place) {
    PsiModifierList modifierList = owner.getModifierList();
    LOG.assertTrue(modifierList != null);
    final String visibilityModifier = VisibilityUtil.getVisibilityModifier(modifierList);
    int index;
    for (index = 0; index < visibilityModifiers.length; index++) {
      String modifier = visibilityModifiers[index];
      if (modifier.equals(visibilityModifier)) break;
    }
    for (; index < visibilityModifiers.length && !isAccessible(place, owner); index++) {
      @PsiModifier.ModifierConstant
      String modifier = visibilityModifiers[index];
      com.intellij.psi.util.PsiUtil.setModifierProperty(owner, modifier, true);
    }
  }

  public static int getArgumentIndex(@NotNull GrCall call, @NotNull PsiElement argument) {
    GrArgumentList argumentList = call.getArgumentList();
    if (argumentList == null) return -1;

    GrExpression[] expressionArguments = argumentList.getExpressionArguments();

    for (int i = 0; i < expressionArguments.length; i++) {
      if (argument.equals(expressionArguments[i])) {
        int res = i;

        if (argumentList.getNamedArguments().length > 0) {
          res++; // first argument is map defined by named arguments
        }

        return res;
      }
    }

    if (argument instanceof GrClosableBlock) {
      GrClosableBlock[] closureArgs = call.getClosureArguments();

      for (int i = 0; i < closureArgs.length; i++) {
        if (argument.equals(closureArgs[i])) {
          int res = i + expressionArguments.length;

          if (argumentList.getNamedArguments().length > 0) {
            res++; // first argument is map defined by named arguments
          }

          return res;
        }
      }

    }

    return -1;
  }

  /**
   * Returns all arguments passed to method. First argument is null if Named Arguments is present.
   */
  public static GrExpression[] getAllArguments(@NotNull GrCall call) {
    GrArgumentList argumentList = call.getArgumentList();
    if (argumentList == null) return GrExpression.EMPTY_ARRAY;

    GrClosableBlock[] closureArguments = call.getClosureArguments();
    GrExpression[] expressionArguments = argumentList.getExpressionArguments();
    GrNamedArgument[] namedArguments = argumentList.getNamedArguments();

    int length = expressionArguments.length + closureArguments.length;
    int k = 0;
    if (namedArguments.length > 0) {
      length++;
      k = 1;
    }

    GrExpression[] res = new GrExpression[length];
    for (GrExpression expressionArgument : expressionArguments) {
      res[k++] = expressionArgument;
    }

    for (GrClosableBlock closureArgument : closureArguments) {
      res[k++] = closureArgument;
    }

    return res;
  }

  public static GrNamedArgument[] getFirstMapNamedArguments(@NotNull GrCall grCall) {
    GrNamedArgument[] res = grCall.getNamedArguments();
    if (res.length > 0) return res;

    GrExpression[] arguments = grCall.getExpressionArguments();
    if (arguments.length == 0) return GrNamedArgument.EMPTY_ARRAY;

    PsiElement firstArg = arguments[0];

    if (!(firstArg instanceof GrListOrMap)) return GrNamedArgument.EMPTY_ARRAY;

    return ((GrListOrMap)firstArg).getNamedArguments();
  }

  public static boolean isExpressionStatement(@NotNull PsiElement expr) {
    if (!(expr instanceof GrStatement)) return false;

    final PsiElement parent = expr.getParent();
    if (parent instanceof GrControlFlowOwner || parent instanceof GrCaseSection) return true;
    if (parent instanceof GrLabeledStatement) return true;
    if (parent instanceof GrIfStatement &&
        (expr == ((GrIfStatement)parent).getThenBranch() || expr == ((GrIfStatement)parent).getElseBranch())) {
      return true;
    }

    if (parent instanceof GrWhileStatement && expr == ((GrWhileStatement)parent).getBody()) {
      return true;
    }
    return false;
  }

  @Nullable
  public static GrMethodCall getMethodCallByNamedParameter(GrNamedArgument namedArgument) {
    GrCall res = getCallByNamedParameter(namedArgument);
    if (res instanceof GrMethodCall) return (GrMethodCall)res;

    return null;
  }

  @Nullable
  public static GrCall getCallByNamedParameter(GrNamedArgument namedArgument) {
    PsiElement parent = namedArgument.getParent();

    PsiElement eMethodCall;

    if (parent instanceof GrArgumentList) {
      eMethodCall = parent.getParent();
    }
    else {
      if (!(parent instanceof GrListOrMap)) return null;

      PsiElement eArgumentList = parent.getParent();
      if (!(eArgumentList instanceof GrArgumentList)) return null;

      GrArgumentList argumentList = (GrArgumentList)eArgumentList;

      if (argumentList.getNamedArguments().length > 0) return null;
      if (argumentList.getExpressionArgumentIndex((GrListOrMap)parent) != 0) return null;

      eMethodCall = eArgumentList.getParent();
    }

    if (!(eMethodCall instanceof GrCall)) return null;

    return (GrCall)eMethodCall;
  }

  public static String getAnnoAttributeValue(@NotNull PsiAnnotation annotation, final String attributeName, String defaultValue) {
    PsiAnnotationMemberValue value = annotation.findAttributeValue(attributeName);
    if (value instanceof GrExpression) {
      Object o = GroovyConstantExpressionEvaluator.evaluate((GrExpression)value);
      if (o instanceof String) {
        return (String)o;
      }
    }
    return defaultValue;
  }

  public static boolean getAnnoAttributeValue(@NotNull PsiAnnotation annotation, final String attributeName, boolean defaultValue) {
    PsiAnnotationMemberValue value = annotation.findAttributeValue(attributeName);
    if (value instanceof GrExpression) {
      Object o = GroovyConstantExpressionEvaluator.evaluate((GrExpression)value);
      if (o instanceof Boolean) {
        return (Boolean)o;
      }
    }
    return defaultValue;
  }

  public static boolean isExpressionUsed(PsiElement expr) {
    while (expr.getParent() instanceof GrParenthesizedExpression) expr = expr.getParent();

    final PsiElement parent = expr.getParent();
    if (parent instanceof GrBinaryExpression ||
        parent instanceof GrUnaryExpression ||
        parent instanceof GrConditionalExpression ||
        parent instanceof GrAssignmentExpression ||
        parent instanceof GrInstanceOfExpression ||
        parent instanceof GrSafeCastExpression ||
        parent instanceof GrTupleExpression ||
        parent instanceof GrArgumentList ||
        parent instanceof GrReturnStatement ||
        parent instanceof GrAssertStatement ||
        parent instanceof GrThrowStatement ||
        parent instanceof GrSwitchStatement ||
        parent instanceof GrVariable) {
      return true;
    }
    return isReturnStatement(expr);
  }

  public static boolean isReturnStatement(@NotNull PsiElement statement) {
    final GrControlFlowOwner controlFlowOwner = ControlFlowUtils.findControlFlowOwner(statement);
    if (controlFlowOwner instanceof GrOpenBlock) {
      final PsiElement controlFlowOwnerParent = controlFlowOwner.getParent();
      if (controlFlowOwnerParent instanceof GrMethod && ((GrMethod)controlFlowOwnerParent).isConstructor()) {
        return false;
      }
      else if (controlFlowOwnerParent instanceof PsiMethod && ((PsiMethod)controlFlowOwnerParent).getReturnType() == PsiType.VOID) {
        return false;
      }
    }
    //noinspection SuspiciousMethodCalls
    return ControlFlowUtils.collectReturns(controlFlowOwner, true).contains(statement);
  }

  @Nullable
  public static PsiClass getContainingNotInnerClass(@Nullable PsiElement element) {
    PsiClass domainClass = PsiTreeUtil.getParentOfType(element, PsiClass.class);
    if (domainClass == null) return null;

    while (true) {
      PsiClass c = domainClass.getContainingClass();
      if (c == null) return domainClass;
      domainClass = c;
    }
  }

  @NotNull
  public static ResolveResult getAccessObjectClass(GrExpression expression) {
    if (isThisOrSuperRef(expression)) return GroovyResolveResult.EMPTY_RESULT;
    PsiType type = expression.getType();
    if (type instanceof PsiClassType) {
      return ((PsiClassType)type).resolveGenerics();
    }
    if (type == null && expression instanceof GrReferenceExpression) {
      GroovyResolveResult resolveResult = ((GrReferenceExpression)expression).advancedResolve();
      if (resolveResult.getElement() instanceof PsiClass) {
        return resolveResult;
      }
    }
    return GroovyResolveResult.EMPTY_RESULT;
  }

  public static boolean isReferenceWithoutQualifier(@Nullable PsiElement element, @NotNull String name) {
    if (!(element instanceof GrReferenceExpression)) return false;

    GrReferenceExpression ref = (GrReferenceExpression)element;

    return !ref.isQualified() && name.equals(ref.getReferenceName());
  }

  public static boolean isProperty(@NotNull GrField field) {
    final PsiClass clazz = field.getContainingClass();
    if (clazz == null) return false;
    if (clazz.isInterface() && !GrTraitUtil.isTrait(clazz)) return false;
    final GrModifierList modifierList = field.getModifierList();
    return modifierList == null || !modifierList.hasExplicitVisibilityModifiers();
  }

  public static boolean isConstructorHasRequiredParameters(@NotNull PsiMethod constructor) {
    LOG.assertTrue(constructor.isConstructor());
    final PsiParameter[] parameters = constructor.getParameterList().getParameters();
    for (PsiParameter parameter : parameters) {
      if (!(parameter instanceof GrParameter && ((GrParameter)parameter).isOptional())) return true;
    }
    return false;
  }

  public static boolean isInMethodCallContext(PsiElement context) {
    return getArgumentsList(context) != null;
  }

  @NotNull
  public static List getValidImportStatements(final GroovyFile file) {
    final List oldImports = new ArrayList();
    for (GrImportStatement statement : file.getImportStatements()) {
      if (!ErrorUtil.containsError(statement)) {
        oldImports.add(statement);
      }
    }
    return oldImports;
  }

  public static boolean isCompileStatic(PsiElement e) {
    PsiMember containingMember = PsiTreeUtil.getParentOfType(e, PsiMember.class, false, GrAnnotation.class);
    return containingMember != null && GroovyPsiManager.getInstance(containingMember.getProject()).isCompileStatic(containingMember);
  }

  @Nullable
  public static PsiType extractIteratedType(GrForInClause forIn) {
    GrExpression iterated = forIn.getIteratedExpression();
    if (iterated == null) return null;
    return ClosureParameterEnhancer.findTypeForIteration(iterated, forIn);
  }

  public static boolean isThisReference(@Nullable PsiElement expression) {
    return isThisOrSuperRef(expression, GroovyTokenTypes.kTHIS, false);
  }

  public static boolean isSuperReference(@Nullable PsiElement expression) {
    return isThisOrSuperRef(expression, GroovyTokenTypes.kSUPER, true);
  }

  private static boolean isThisOrSuperRef(PsiElement expression, IElementType token, boolean superClassAccepted) {
    if (!(expression instanceof GrReferenceExpression)) return false;
    GrReferenceExpression ref = (GrReferenceExpression)expression;

    PsiElement nameElement = ref.getReferenceNameElement();
    if (nameElement == null) return false;

    IElementType type = nameElement.getNode().getElementType();
    if (type != token) return false;

    GrExpression qualifier = ref.getQualifier();
    if (qualifier == null) {
      return true;
    }
    else {
      PsiElement resolved = ref.resolve();
      if (resolved instanceof PsiClass) {
        if (hasEnclosingInstanceInScope(((PsiClass)resolved), ref, superClassAccepted)) return true;
        if (superClassAccepted && GrTraitUtil.isTrait((PsiClass)resolved) && scopeClassImplementsTrait(((PsiClass)resolved), ref)) return true;
      }
      return false;
    }
  }

  public static boolean scopeClassImplementsTrait(@NotNull final PsiClass trait, @NotNull final PsiElement place) {
    GrTypeDefinition scopeClass = PsiTreeUtil.getParentOfType(place, GrTypeDefinition.class, true);
    return scopeClass != null && ContainerUtil.find(scopeClass.getSuperTypes(), new Condition() {
      @Override
      public boolean value(PsiClassType type) {
        return place.getManager().areElementsEquivalent(type.resolve(), trait);
      }
    }) != null;
  }

  public static boolean isThisOrSuperRef(@Nullable PsiElement qualifier) {
    return qualifier instanceof GrReferenceExpression && (isThisReference(qualifier) || isSuperReference(qualifier));
  }

  public static boolean isInstanceThisRef(PsiElement qualifier) {
    if (isThisReference(qualifier)) {
      GrReferenceExpression ref = (GrReferenceExpression)qualifier;

      PsiElement resolved = ref.resolve();
      if (resolved == null) return false;

      return hasEnclosingInstanceInScope((PsiClass)resolved, qualifier, false);
    }
    return false;
  }

  public static boolean isLineFeed(@Nullable PsiElement e) {
    return e != null &&
           PsiImplUtil.isWhiteSpaceOrNls(e) &&
           (e.getText().indexOf('\n') >= 0 || e.getText().indexOf('\r') >= 0);
  }

  public static boolean isSingleBindingVariant(GroovyResolveResult[] candidates) {
    return candidates.length == 1 && candidates[0].getElement() instanceof GrBindingVariable;
  }

  @Nullable
  public static GrConstructorInvocation getConstructorInvocation(@NotNull GrMethod constructor) {
    assert constructor.isConstructor();

    final GrOpenBlock body = constructor.getBlock();
    if (body == null) return null;

    final GrStatement[] statements = body.getStatements();
    if (statements.length > 0 && statements[0] instanceof GrConstructorInvocation) {
      return ((GrConstructorInvocation)statements[0]);
    }
    else {
      return null;
    }
  }

  public static boolean isDGMMethod(@Nullable PsiElement element) {
    if (!(element instanceof PsiMethod)) return false;

    final PsiMethod method = element instanceof GrGdkMethod ? ((GrGdkMethod)element).getStaticMethod() : (PsiMethod)element;
    final PsiClass aClass = method.getContainingClass();
    if (aClass == null) return false;

    final String qname = aClass.getQualifiedName();
    return GroovyCommonClassNames.GROOVY_EXTENSION_CLASSES.contains(qname);
  }

  public static boolean isVoidMethodCall(@Nullable GrExpression expression) {
    if (expression instanceof GrMethodCall && PsiType.NULL.equals(expression.getType())) {
      final GroovyResolveResult resolveResult = ((GrMethodCall)expression).advancedResolve();
      final PsiType[] args = getArgumentTypes(((GrMethodCall)expression).getInvokedExpression(), true);
      return PsiType.VOID.equals(ResolveUtil.extractReturnTypeFromCandidate(resolveResult, expression, args));
    }

    return false;
  }

  public static boolean isVoidMethod(@NotNull PsiMethod method) {
    if (PsiType.VOID.equals(method.getReturnType())) {
      return true;
    }

    if (method instanceof GrMethod && ((GrMethod)method).getReturnTypeElementGroovy() == null) {
      GrOpenBlock block = ((GrMethod)method).getBlock();
      if (block != null && isBlockReturnVoid(block)) {
        return true;
      }
    }

    return false;
  }

  public static boolean isBlockReturnVoid(@NotNull final GrCodeBlock block) {
    return CachedValuesManager.getCachedValue(block, new CachedValueProvider() {
      @Nullable
      @Override
      public Result compute() {
        return Result.create(ControlFlowUtils.visitAllExitPoints(block, new ControlFlowUtils.ExitPointVisitor() {
          @Override
          public boolean visitExitPoint(Instruction instruction, @Nullable GrExpression returnValue) {
            return returnValue == null || !(returnValue instanceof GrLiteral);
          }
        }), PsiModificationTracker.MODIFICATION_COUNT);
      }
    });
  }

  public static boolean checkPsiElementsAreEqual(PsiElement l, PsiElement r) {
    if (!l.getText().equals(r.getText())) return false;
    if (l.getNode().getElementType() != r.getNode().getElementType()) return false;

    final PsiElement[] lChildren = l.getChildren();
    final PsiElement[] rChildren = r.getChildren();

    if (lChildren.length != rChildren.length) return false;

    for (int i = 0; i < rChildren.length; i++) {
      if (!checkPsiElementsAreEqual(lChildren[i], rChildren[i])) return false;
    }
    return true;
  }

  public static boolean isCall(GrReferenceExpression referenceExpression) {
    return referenceExpression.getParent() instanceof GrCall;
  }

  public static boolean isLocalVariable(@Nullable PsiElement variable) {
    return variable instanceof GrVariable && !(variable instanceof GrField || variable instanceof GrParameter);
  }

  public static boolean isLocalOrParameter(@Nullable PsiElement variable) {
    return variable instanceof GrVariable && !(variable instanceof GrField);
  }

  @Nullable
  public static PsiElement getPreviousNonWhitespaceToken(PsiElement e) {
    PsiElement next = PsiTreeUtil.prevLeaf(e);
    while (next != null && next.getNode().getElementType() == TokenType.WHITE_SPACE) next = PsiTreeUtil.prevLeaf(next);
    return next;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy