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

org.jetbrains.plugins.groovy.lang.psi.util.GroovyImportUtil 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.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashSet;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement;
import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
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.impl.GroovyImportHelper;
import org.jetbrains.plugins.groovy.lang.resolve.processors.ClassHint;
import org.jetbrains.plugins.groovy.lang.resolve.processors.ClassResolverProcessor;

import java.util.Map;
import java.util.Set;

public class GroovyImportUtil {
  public static void processFile(@Nullable final PsiFile file,
                                 @Nullable final Set importedClasses,
                                 @Nullable final Set staticallyImportedMembers,
                                 @Nullable final Set usedImports,
                                 @Nullable final Set unresolvedOnDemandImports,
                                 @Nullable final Set implicitlyImported,
                                 @Nullable final Set innerClasses,
                                 @Nullable final Map aliased,
                                 @Nullable final Map annotations) {
    if (!(file instanceof GroovyFile)) return;

    final Set unresolvedReferenceNames = ContainerUtil.newLinkedHashSet();

    file.accept(new PsiRecursiveElementWalkingVisitor() {
      @Override
      public void visitElement(PsiElement element) {
        super.visitElement(element);
        if (element instanceof GrReferenceElement) {
          visitRefElement((GrReferenceElement)element);
        }
      }

      private void visitRefElement(GrReferenceElement refElement) {
        final String refName = refElement.getReferenceName();

        if ("super".equals(refName)) return;

        final GroovyResolveResult[] resolveResults = refElement.multiResolve(false);
        if (resolveResults.length == 0 && refName != null) {
          if (PsiTreeUtil.getParentOfType(refElement, GrImportStatement.class) == null) {
            unresolvedReferenceNames.add(refName);
          }
        }

        for (GroovyResolveResult resolveResult : resolveResults) {
          final PsiElement context = resolveResult.getCurrentFileResolveContext();
          final PsiElement resolved = resolveResult.getElement();
          if (resolved == null) return;

          if (context instanceof GrImportStatement) {
            final GrImportStatement importStatement = (GrImportStatement)context;

            if (usedImports != null && isImportUsed(refElement, resolved)) {
              usedImports.add(importStatement);
            }
            if (GroovyImportHelper.isImplicitlyImported(resolved, refName, (GroovyFile)file)) {
              addImplicitClass(resolved);
            }

            if (!importStatement.isAliasedImport() && !isAnnotatedImport(importStatement)) {
              String importedName = null;
              if (importStatement.isOnDemand()) {

                if (importStatement.isStatic()) {
                  if (resolved instanceof PsiMember) {
                    final PsiMember member = (PsiMember)resolved;
                    final PsiClass clazz = member.getContainingClass();
                    if (clazz != null) {
                      final String classQName = clazz.getQualifiedName();
                      if (classQName != null) {
                        final String name = member.getName();
                        if (name != null) {
                          importedName = classQName + "." + name;
                        }
                      }
                    }
                  }
                }
                else {
                  importedName = getTargetQualifiedName(resolved);
                }
              }
              else {
                final GrCodeReferenceElement importReference = importStatement.getImportReference();
                if (importReference != null) {
                  importedName = PsiUtil.getQualifiedReferenceText(importReference);
                }
              }

              if (importedName == null) return;

              final String importRef = getImportReferenceText(importStatement);

              if (importStatement.isAliasedImport()) {
                if (aliased != null) {
                  aliased.put(importRef, importedName);
                }
                return;
              }

              if (importStatement.isStatic()) {
                if (staticallyImportedMembers != null) {
                  staticallyImportedMembers.add(importedName);
                }
              }
              else {
                if (importedClasses != null) {
                  importedClasses.add(importedName);
                }
                if (resolved instanceof PsiClass && ((PsiClass)resolved).getContainingClass() != null && innerClasses != null) {
                  innerClasses.add(importedName);
                }
              }
            }
          }
          else if (context == null && !(refElement.getParent() instanceof GrImportStatement) && refElement.getQualifier() == null) {
            addImplicitClass(resolved);
          }
        }
      }

      private void addImplicitClass(PsiElement element) {
        final String qname = getTargetQualifiedName(element);
        if (qname != null) {
          if (implicitlyImported != null) {
            implicitlyImported.add(qname);
          }
          if (importedClasses != null) {
            importedClasses.add(qname);
          }
        }
      }

      /**
       * checks if import for implicitly imported class is needed
       */
      private boolean isImportUsed(GrReferenceElement refElement, PsiElement resolved) {
        if (GroovyImportHelper.isImplicitlyImported(resolved, refElement.getReferenceName(), (GroovyFile)file)) {
          final ClassResolverProcessor processor =
            new ClassResolverProcessor(refElement.getReferenceName(), refElement, ClassHint.RESOLVE_KINDS_CLASS);
          GroovyImportHelper
            .processImports(ResolveState.initial(), null, refElement, processor, ((GroovyFile)file).getImportStatements(), true);
          if (!processor.hasCandidates()) {
            return false;
          }
        }
        return true;
      }
    });

    final Set importsToCheck = ContainerUtil.newLinkedHashSet(PsiUtil.getValidImportStatements((GroovyFile)file));
    for (GrImportStatement anImport : importsToCheck) {
      if (usedImports != null && usedImports.contains(anImport)) continue;

      final GrCodeReferenceElement ref = anImport.getImportReference();
      assert ref != null : "invalid import!";

      if (ref.resolve() == null) {
        if (anImport.isOnDemand()) {
          if (usedImports != null) {
            usedImports.add(anImport);
          }
          if (unresolvedOnDemandImports != null) {
            unresolvedOnDemandImports.add(anImport);
          }
        }
        else {
          String importedName = anImport.getImportedName();
          if (importedName != null && unresolvedReferenceNames.contains(importedName)) {
            if (usedImports != null) {
              usedImports.add(anImport);
            }

            final String symbolName = getImportReferenceText(anImport);

            if (anImport.isAliasedImport()) {
              if (aliased != null) {
                aliased.put(symbolName, importedName);
              }
            }
            else {
              if (anImport.isStatic()) {
                if (staticallyImportedMembers != null) {
                  staticallyImportedMembers.add(symbolName);
                }
              }
              else {
                if (importedClasses != null) {
                  importedClasses.add(symbolName);
                }
              }
            }
          }
        }
      }
    }

    if (annotations != null) {
      ((GroovyFile)file).acceptChildren(new GroovyElementVisitor() {
        @Override
        public void visitImportStatement(GrImportStatement importStatement) {
          final String annotationText = importStatement.getAnnotationList().getText();
          if (!StringUtil.isEmptyOrSpaces(annotationText)) {
            final String importRef = getImportReferenceText(importStatement);
            annotations.put(importRef, annotationText);
          }
        }
      });
    }
  }

  @Nullable
  private static String getTargetQualifiedName(PsiElement element) {
    if (element instanceof PsiClass) {
      return ((PsiClass)element).getQualifiedName();
    }
    if (element instanceof PsiMethod && ((PsiMethod)element).isConstructor()) {
      return ((PsiMethod)element).getContainingClass().getQualifiedName();
    }
    return null;
  }

  public static boolean isAnnotatedImport(GrImportStatement anImport) {
    return !StringUtil.isEmptyOrSpaces(anImport.getAnnotationList().getText());
  }

  @Nullable
  public static String getImportReferenceText(GrImportStatement statement) {
    GrCodeReferenceElement importReference = statement.getImportReference();
    if (importReference != null) {
      return importReference.getClassNameText();
    }
    return null;
  }

  public static Set findUsedImports(GroovyFile file) {
    Set usedImports = new HashSet();
    processFile(file, null, null, usedImports, null, null, null, null, null);
    return usedImports;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy