@Nullable
 @Override
 public RefEntity getReference(final String type, final String fqName) {
   for (RefManagerExtension extension : myExtensions.values()) {
     final RefEntity refEntity = extension.getReference(type, fqName);
     if (refEntity != null) return refEntity;
   }
   if (SmartRefElementPointer.FILE.equals(type)) {
     return RefFileImpl.fileFromExternalName(this, fqName);
   }
   if (SmartRefElementPointer.MODULE.equals(type)) {
     return RefModuleImpl.moduleFromName(this, fqName);
   }
   if (SmartRefElementPointer.PROJECT.equals(type)) {
     return getRefProject();
   }
   if (SmartRefElementPointer.DIR.equals(type)) {
     String url =
         VfsUtilCore.pathToUrl(PathMacroManager.getInstance(getProject()).expandPath(fqName));
     VirtualFile vFile = VirtualFileManager.getInstance().findFileByUrl(url);
     if (vFile != null) {
       final PsiDirectory dir = PsiManager.getInstance(getProject()).findDirectory(vFile);
       return getReference(dir);
     }
   }
   return null;
 }
 private boolean belongsToScope(final PsiElement psiElement, final boolean ignoreScope) {
   if (psiElement == null || !psiElement.isValid()) return false;
   if (psiElement instanceof PsiCompiledElement) return false;
   final PsiFile containingFile =
       ApplicationManager.getApplication()
           .runReadAction(
               new Computable<PsiFile>() {
                 @Override
                 public PsiFile compute() {
                   return psiElement.getContainingFile();
                 }
               });
   if (containingFile == null) {
     return false;
   }
   for (RefManagerExtension extension : myExtensions.values()) {
     if (!extension.belongsToScope(psiElement)) return false;
   }
   final Boolean inProject =
       ApplicationManager.getApplication()
           .runReadAction(
               new Computable<Boolean>() {
                 @Override
                 public Boolean compute() {
                   return psiElement.getManager().isInProject(psiElement);
                 }
               });
   return inProject.booleanValue()
       && (ignoreScope || getScope() == null || getScope().contains(psiElement));
 }
  @Override
  public void resolveEntryPoints(@NotNull final RefManager manager) {
    if (!myResolved) {
      myResolved = true;
      cleanup();
      validateEntryPoints();

      ApplicationManager.getApplication()
          .runReadAction(
              () -> {
                for (SmartRefElementPointer entryPoint : myPersistentEntryPoints.values()) {
                  if (entryPoint.resolve(manager)) {
                    RefEntity refElement = entryPoint.getRefElement();
                    ((RefElementImpl) refElement).setEntry(true);
                    ((RefElementImpl) refElement).setPermanentEntry(entryPoint.isPersistent());
                  }
                }

                for (ClassPattern pattern : myPatterns) {
                  final RefEntity refClass =
                      manager.getReference(RefJavaManager.CLASS, pattern.pattern);
                  if (refClass != null) {
                    for (RefMethod constructor : ((RefClass) refClass).getConstructors()) {
                      ((RefMethodImpl) constructor).setEntry(true);
                      ((RefMethodImpl) constructor).setPermanentEntry(true);
                    }
                  }
                }
              });
    }
  }
 private static boolean copyOneClass(Map<PsiFile, PsiClass[]> classes) {
   if (classes.size() == 1) {
     final PsiClass[] psiClasses = classes.values().iterator().next();
     return psiClasses != null && psiClasses.length == 1;
   }
   return false;
 }
 @NotNull
 @Override
 public RefEntity getRefinedElement(@NotNull RefEntity ref) {
   for (RefManagerExtension extension : myExtensions.values()) {
     ref = extension.getRefinedElement(ref);
   }
   return ref;
 }
 @Override
 public boolean isValid() {
   Collection<PsiType> substitutorValues = mySubstitutionMap.values();
   for (PsiType type : substitutorValues) {
     if (type != null && !type.isValid()) return false;
   }
   return true;
 }
 private void releaseAllEditors() {
   for (final Editor editor : myEditors.values()) {
     if (!editor.isDisposed()) {
       EditorFactory.getInstance().releaseEditor(editor);
     }
   }
   myEditors.clear();
 }
 @Override
 public void cleanup() {
   purgeTemporaryEntryPoints();
   Collection<SmartRefElementPointer> entries = myPersistentEntryPoints.values();
   for (SmartRefElementPointer entry : entries) {
     entry.freeReference();
   }
 }
 @Override
 public boolean forbidToClone(PsiElement[] elements, boolean fromUpdate) {
   final Map<PsiFile, PsiClass[]> fileMap =
       convertToTopLevelClasses(elements, fromUpdate, null, null);
   if (fileMap != null && fileMap.size() == 1) {
     final PsiClass[] psiClasses = fileMap.values().iterator().next();
     return psiClasses != null && psiClasses.length > 1;
   }
   return true;
 }
 public static PsiField[] getAllFields(GrTypeDefinition grType) {
   Map<String, CandidateInfo> fieldsMap = CollectClassMembersUtil.getAllFields(grType);
   return ContainerUtil.map2Array(
       fieldsMap.values(),
       PsiField.class,
       new Function<CandidateInfo, PsiField>() {
         public PsiField fun(CandidateInfo entry) {
           return (PsiField) entry.getElement();
         }
       });
 }
 @Nullable
 private static Map<PsiFile, PsiClass[]> convertToTopLevelClasses(
     final PsiElement[] elements,
     final boolean fromUpdate,
     String relativePath,
     Map<PsiFile, String> relativeMap) {
   final Map<PsiFile, PsiClass[]> result = new HashMap<PsiFile, PsiClass[]>();
   for (PsiElement element : elements) {
     final PsiElement navigationElement = element.getNavigationElement();
     LOG.assertTrue(navigationElement != null, element);
     final PsiFile containingFile = navigationElement.getContainingFile();
     if (!(containingFile instanceof PsiClassOwner
         && ProjectRootsUtil.isOutsideSourceRoot(containingFile))) {
       PsiClass[] topLevelClasses = getTopLevelClasses(element);
       if (topLevelClasses == null) {
         if (element instanceof PsiDirectory) {
           if (!fromUpdate) {
             final String name = ((PsiDirectory) element).getName();
             final String path =
                 relativePath != null
                     ? (relativePath.length() > 0 ? (relativePath + "/") : "") + name
                     : null;
             final Map<PsiFile, PsiClass[]> map =
                 convertToTopLevelClasses(element.getChildren(), fromUpdate, path, relativeMap);
             if (map == null) return null;
             for (Map.Entry<PsiFile, PsiClass[]> entry : map.entrySet()) {
               fillResultsMap(result, entry.getKey(), entry.getValue());
             }
           }
           continue;
         }
         if (!(element instanceof PsiFileSystemItem)) return null;
       }
       fillResultsMap(result, containingFile, topLevelClasses);
       if (relativeMap != null) {
         relativeMap.put(containingFile, relativePath);
       }
     }
   }
   if (result.isEmpty()) {
     return null;
   } else {
     boolean hasClasses = false;
     for (PsiClass[] classes : result.values()) {
       if (classes != null) {
         hasClasses = true;
         break;
       }
     }
     return hasClasses ? result : null;
   }
 }
  @Override
  public Element export(
      @NotNull RefEntity refEntity, @NotNull final Element element, final int actualLine) {
    refEntity = getRefinedElement(refEntity);

    Element problem = new Element("problem");

    if (refEntity instanceof RefElement) {
      final RefElement refElement = (RefElement) refEntity;
      final SmartPsiElementPointer pointer = refElement.getPointer();
      PsiFile psiFile = pointer.getContainingFile();
      if (psiFile == null) return null;

      Element fileElement = new Element("file");
      Element lineElement = new Element("line");
      final VirtualFile virtualFile = psiFile.getVirtualFile();
      LOG.assertTrue(virtualFile != null);
      fileElement.addContent(virtualFile.getUrl());

      if (actualLine == -1) {
        final Document document =
            PsiDocumentManager.getInstance(pointer.getProject()).getDocument(psiFile);
        LOG.assertTrue(document != null);
        final Segment range = pointer.getRange();
        lineElement.addContent(
            String.valueOf(
                range != null ? document.getLineNumber(range.getStartOffset()) + 1 : -1));
      } else {
        lineElement.addContent(String.valueOf(actualLine));
      }

      problem.addContent(fileElement);
      problem.addContent(lineElement);

      appendModule(problem, refElement.getModule());
    } else if (refEntity instanceof RefModule) {
      final RefModule refModule = (RefModule) refEntity;
      final VirtualFile moduleFile = refModule.getModule().getModuleFile();
      final Element fileElement = new Element("file");
      fileElement.addContent(moduleFile != null ? moduleFile.getUrl() : refEntity.getName());
      problem.addContent(fileElement);
      appendModule(problem, refModule);
    }

    for (RefManagerExtension extension : myExtensions.values()) {
      extension.export(refEntity, problem);
    }

    new SmartRefElementPointerImpl(refEntity, true).writeExternal(problem);
    element.addContent(problem);
    return problem;
  }
 @Override
 public void iterate(@NotNull RefVisitor visitor) {
   for (RefElement refElement : getSortedElements()) {
     refElement.accept(visitor);
   }
   if (myModules != null) {
     for (RefModule refModule : myModules.values()) {
       refModule.accept(visitor);
     }
   }
   for (RefManagerExtension extension : myExtensions.values()) {
     extension.iterate(visitor);
   }
 }
  public void cleanup() {
    myScope = null;
    myRefProject = null;
    synchronized (myRefTable) {
      myRefTable.clear();
      mySortedRefs = null;
    }
    myModules.clear();
    myContext = null;

    myGraphAnnotators.clear();
    for (RefManagerExtension extension : myExtensions.values()) {
      extension.cleanup();
    }
  }
  @NotNull
  @Override
  public RefElement[] getEntryPoints() {
    validateEntryPoints();
    List<RefElement> entries = new ArrayList<RefElement>();
    Collection<SmartRefElementPointer> collection = myPersistentEntryPoints.values();
    for (SmartRefElementPointer refElementPointer : collection) {
      final RefEntity elt = refElementPointer.getRefElement();
      if (elt instanceof RefElement) {
        entries.add((RefElement) elt);
      }
    }
    entries.addAll(myTemporaryEntryPoints);

    return entries.toArray(new RefElement[entries.size()]);
  }
  @Nullable
  public RefElement getReference(final PsiElement elem, final boolean ignoreScope) {
    if (ApplicationManager.getApplication()
        .runReadAction(
            new Computable<Boolean>() {
              @Override
              public Boolean compute() {
                return elem == null
                    || !elem.isValid()
                    || elem instanceof LightElement
                    || !(elem instanceof PsiDirectory) && !belongsToScope(elem, ignoreScope);
              }
            })) {
      return null;
    }

    return getFromRefTableOrCache(
        elem,
        () ->
            ApplicationManager.getApplication()
                .runReadAction(
                    new Computable<RefElementImpl>() {
                      @Override
                      @Nullable
                      public RefElementImpl compute() {
                        final RefManagerExtension extension = getExtension(elem.getLanguage());
                        if (extension != null) {
                          final RefElement refElement = extension.createRefElement(elem);
                          if (refElement != null) return (RefElementImpl) refElement;
                        }
                        if (elem instanceof PsiFile) {
                          return new RefFileImpl((PsiFile) elem, RefManagerImpl.this);
                        }
                        if (elem instanceof PsiDirectory) {
                          return new RefDirectoryImpl((PsiDirectory) elem, RefManagerImpl.this);
                        }
                        return null;
                      }
                    }),
        element -> {
          element.initialize();
          for (RefManagerExtension each : myExtensions.values()) {
            each.onEntityInitialized(element, elem);
          }
          fireNodeInitialized(element);
        });
  }
  @SuppressWarnings({"HardCodedStringLiteral"})
  public static void writeExternal(
      final Element element,
      final Map<String, SmartRefElementPointer> persistentEntryPoints,
      final JDOMExternalizableStringList additional_annotations) {
    Element entryPointsElement = new Element("entry_points");
    entryPointsElement.setAttribute(VERSION_ATTR, VERSION);
    for (SmartRefElementPointer entryPoint : persistentEntryPoints.values()) {
      assert entryPoint.isPersistent();
      entryPoint.writeExternal(entryPointsElement);
    }

    element.addContent(entryPointsElement);
    if (!additional_annotations.isEmpty()) {
      additional_annotations.writeExternal(element);
    }
  }
  @Override
  @Nullable
  public String getGroupName(final RefElement entity) {
    for (RefManagerExtension extension : myExtensions.values()) {
      final String groupName = extension.getGroupName(entity);
      if (groupName != null) return groupName;
    }

    final LinkedList<String> containingDirs = new LinkedList<>();
    RefEntity parent = entity.getOwner();
    while (parent != null && !(parent instanceof RefDirectory)) {
      parent = parent.getOwner();
    }
    while (parent instanceof RefDirectory) {
      containingDirs.addFirst(parent.getName());
      parent = parent.getOwner();
    }
    return containingDirs.isEmpty() ? null : StringUtil.join(containingDirs, File.separator);
  }
 @Nullable
 private static String normalizeRelativeMap(Map<PsiFile, String> relativeMap) {
   String vector = null;
   for (String relativePath : relativeMap.values()) {
     if (vector == null) {
       vector = relativePath;
     } else if (vector.startsWith(relativePath + "/")) {
       vector = relativePath;
     } else if (!relativePath.startsWith(vector + "/") && !relativePath.equals(vector)) {
       return null;
     }
   }
   if (vector != null) {
     for (PsiFile psiFile : relativeMap.keySet()) {
       final String path = relativeMap.get(psiFile);
       relativeMap.put(psiFile, path.equals(vector) ? "" : path.substring(vector.length() + 1));
     }
   }
   return vector;
 }
  @NotNull
  public List<RefElement> getSortedElements() {
    List<RefElement> answer;
    synchronized (myRefTable) {
      if (mySortedRefs != null) return mySortedRefs;

      answer = new ArrayList<>(myRefTable.values());
    }
    ReadAction.run(
        () ->
            ContainerUtil.quickSort(
                answer,
                (o1, o2) -> {
                  VirtualFile v1 = ((RefElementImpl) o1).getVirtualFile();
                  VirtualFile v2 = ((RefElementImpl) o2).getVirtualFile();
                  return (v1 != null ? v1.hashCode() : 0) - (v2 != null ? v2.hashCode() : 0);
                }));
    synchronized (myRefTable) {
      return mySortedRefs = Collections.unmodifiableList(answer);
    }
  }
 @Override
 @Nullable
 public String getType(final RefEntity ref) {
   for (RefManagerExtension extension : myExtensions.values()) {
     final String type = extension.getType(ref);
     if (type != null) return type;
   }
   if (ref instanceof RefFile) {
     return SmartRefElementPointer.FILE;
   }
   if (ref instanceof RefModule) {
     return SmartRefElementPointer.MODULE;
   }
   if (ref instanceof RefProject) {
     return SmartRefElementPointer.PROJECT;
   }
   if (ref instanceof RefDirectory) {
     return SmartRefElementPointer.DIR;
   }
   return null;
 }
  private void validateEntryPoints() {
    long count = PsiManager.getInstance(myProject).getModificationTracker().getModificationCount();
    if (count != myLastModificationCount) {
      myLastModificationCount = count;
      Collection<SmartRefElementPointer> collection = myPersistentEntryPoints.values();
      SmartRefElementPointer[] entries =
          collection.toArray(new SmartRefElementPointer[collection.size()]);
      for (SmartRefElementPointer entry : entries) {
        RefElement refElement = (RefElement) entry.getRefElement();
        if (refElement != null && !refElement.isValid()) {
          myPersistentEntryPoints.remove(entry.getFQName());
        }
      }

      final Iterator<RefElement> it = myTemporaryEntryPoints.iterator();
      while (it.hasNext()) {
        RefElement refElement = it.next();
        if (!refElement.isValid()) {
          it.remove();
        }
      }
    }
  }
 @NotNull
 public String getDisplayName() {
   final String className = getClassName();
   if (StringUtil.isEmpty(className)) return "<unnamed>";
   MethodInfo singleInfo = null;
   for (MethodInfo info : myParameterMap.values()) {
     if (info.isEnabled()) {
       if (singleInfo == null) {
         singleInfo = info;
       } else {
         singleInfo = null;
         break;
       }
     }
   }
   final String name =
       singleInfo != null
           ? StringUtil.getShortName(className) + "." + singleInfo.methodName
           : StringUtil.getShortName(className);
   return /*"["+getInjectedLanguageId()+"] " +*/ name
       + " ("
       + StringUtil.getPackageName(className)
       + ")";
 }
 public Collection<MethodInfo> getMethodInfos() {
   return myParameterMap.values();
 }
  public static boolean processDeclarations(
      @NotNull GrTypeDefinition grType,
      @NotNull PsiScopeProcessor processor,
      @NotNull ResolveState state,
      @Nullable PsiElement lastParent,
      @NotNull PsiElement place) {
    if (place instanceof GrCodeReferenceElement && lastParent instanceof GrModifierList) {
      final PsiElement possibleAnnotation =
          PsiTreeUtil.skipParentsOfType(place, GrCodeReferenceElement.class);
      if (possibleAnnotation instanceof GrAnnotation
          && possibleAnnotation.getParent() == lastParent) {
        return true; // don't process class members while resolving annotation which annotates
                     // current class
      }
    }

    for (final PsiTypeParameter typeParameter : grType.getTypeParameters()) {
      if (!processElement(processor, typeParameter, state)) return false;
    }

    NameHint nameHint = processor.getHint(NameHint.KEY);
    String name = nameHint == null ? null : nameHint.getName(state);
    ClassHint classHint = processor.getHint(ClassHint.KEY);
    final PsiSubstitutor substitutor = state.get(PsiSubstitutor.KEY);
    final PsiElementFactory factory = JavaPsiFacade.getElementFactory(place.getProject());

    boolean processInstanceMethods =
        (shouldProcessMethods(classHint) || shouldProcessProperties(classHint))
            && shouldProcessInstanceMembers(grType, lastParent);

    LanguageLevel level = PsiUtil.getLanguageLevel(place);
    if (shouldProcessProperties(classHint)) {
      Map<String, CandidateInfo> fieldsMap = CollectClassMembersUtil.getAllFields(grType);
      if (name != null) {
        CandidateInfo fieldInfo = fieldsMap.get(name);
        if (fieldInfo != null) {
          if (!processField(
              grType,
              processor,
              state,
              place,
              processInstanceMethods,
              substitutor,
              factory,
              level,
              fieldInfo)) {
            return false;
          }
        } else if (grType.isTrait() && lastParent != null) {
          PsiField field = findFieldByName(grType, name, false, true);
          if (field != null && field.hasModifierProperty(PsiModifier.PUBLIC)) {
            if (!processField(
                grType,
                processor,
                state,
                place,
                processInstanceMethods,
                substitutor,
                factory,
                level,
                new CandidateInfo(field, PsiSubstitutor.EMPTY))) {
              return false;
            }
          }
        }
      } else {
        for (CandidateInfo info : fieldsMap.values()) {
          if (!processField(
              grType,
              processor,
              state,
              place,
              processInstanceMethods,
              substitutor,
              factory,
              level,
              info)) {
            return false;
          }
        }
        if (grType.isTrait() && lastParent != null) {
          for (PsiField field : CollectClassMembersUtil.getFields(grType, true)) {
            if (field.hasModifierProperty(PsiModifier.PUBLIC)) {
              if (!processField(
                  grType,
                  processor,
                  state,
                  place,
                  processInstanceMethods,
                  substitutor,
                  factory,
                  level,
                  new CandidateInfo(field, PsiSubstitutor.EMPTY))) {
                return false;
              }
            }
          }
        }
      }
    }

    if (shouldProcessMethods(classHint)) {
      Map<String, List<CandidateInfo>> methodsMap =
          CollectClassMembersUtil.getAllMethods(grType, true);
      boolean isPlaceGroovy = place.getLanguage() == GroovyFileType.GROOVY_LANGUAGE;
      if (name == null) {
        for (List<CandidateInfo> list : methodsMap.values()) {
          for (CandidateInfo info : list) {
            if (!processMethod(
                grType,
                processor,
                state,
                place,
                processInstanceMethods,
                substitutor,
                factory,
                level,
                isPlaceGroovy,
                info)) {
              return false;
            }
          }
        }
      } else {
        List<CandidateInfo> byName = methodsMap.get(name);
        if (byName != null) {
          for (CandidateInfo info : byName) {
            if (!processMethod(
                grType,
                processor,
                state,
                place,
                processInstanceMethods,
                substitutor,
                factory,
                level,
                isPlaceGroovy,
                info)) {
              return false;
            }
          }
        }
      }
    }

    final GrTypeDefinitionBody body = grType.getBody();
    if (body != null) {
      if (shouldProcessClasses(classHint)) {
        for (PsiClass innerClass : getInnerClassesForResolve(grType, lastParent, place)) {
          final String innerClassName = innerClass.getName();
          if (nameHint != null && !innerClassName.equals(nameHint.getName(state))) {
            continue;
          }

          if (!processor.execute(innerClass, state)) {
            return false;
          }
        }
      }
    }

    return true;
  }
Exemple #26
0
 public Collection<VirtualFile> getCommonPluginRoots(@NotNull Module module, boolean refresh) {
   Map<String, VirtualFile> result = new HashMap<String, VirtualFile>();
   collectCommonPluginRoots(result, module, refresh);
   return result.values();
 }
  @Nullable
  public static PsiElement doCopyClasses(
      final Map<PsiFile, PsiClass[]> fileToClasses,
      @Nullable HashMap<PsiFile, String> map,
      final String copyClassName,
      final PsiDirectory targetDirectory,
      final Project project)
      throws IncorrectOperationException {
    PsiElement newElement = null;
    final Map<PsiClass, PsiElement> oldToNewMap = new HashMap<PsiClass, PsiElement>();
    for (final PsiClass[] psiClasses : fileToClasses.values()) {
      if (psiClasses != null) {
        for (PsiClass aClass : psiClasses) {
          if (aClass instanceof SyntheticElement) {
            continue;
          }
          oldToNewMap.put(aClass, null);
        }
      }
    }
    final List<PsiFile> createdFiles = new ArrayList<PsiFile>(fileToClasses.size());
    int[] choice = fileToClasses.size() > 1 ? new int[] {-1} : null;
    List<PsiFile> files = new ArrayList<PsiFile>();
    for (final Map.Entry<PsiFile, PsiClass[]> entry : fileToClasses.entrySet()) {
      final PsiFile psiFile = entry.getKey();
      final PsiClass[] sources = entry.getValue();
      if (psiFile instanceof PsiClassOwner && sources != null) {
        final PsiFile createdFile =
            copy(
                psiFile,
                targetDirectory,
                copyClassName,
                map == null ? null : map.get(psiFile),
                choice);
        if (createdFile == null) return null;
        for (final PsiClass destination : ((PsiClassOwner) createdFile).getClasses()) {
          if (destination instanceof SyntheticElement) {
            continue;
          }
          PsiClass source = findByName(sources, destination.getName());
          if (source != null) {
            final PsiClass copy = copy(source, copyClassName);
            newElement = destination.replace(copy);
            oldToNewMap.put(source, newElement);
          } else {
            destination.delete();
          }
        }
        createdFiles.add(createdFile);
      } else {
        files.add(psiFile);
      }
    }

    for (PsiFile file : files) {
      try {
        PsiDirectory finalTarget = targetDirectory;
        final String relativePath = map != null ? map.get(file) : null;
        if (relativePath != null && !relativePath.isEmpty()) {
          finalTarget =
              buildRelativeDir(targetDirectory, relativePath).findOrCreateTargetDirectory();
        }
        final PsiFile fileCopy =
            CopyFilesOrDirectoriesHandler.copyToDirectory(
                file, getNewFileName(file, copyClassName), finalTarget, choice);
        if (fileCopy != null) {
          createdFiles.add(fileCopy);
        }
      } catch (IOException e) {
        throw new IncorrectOperationException(e.getMessage());
      }
    }

    final Set<PsiElement> rebindExpressions = new HashSet<PsiElement>();
    for (PsiElement element : oldToNewMap.values()) {
      if (element == null) {
        LOG.error(oldToNewMap.keySet());
        continue;
      }
      decodeRefs(element, oldToNewMap, rebindExpressions);
    }

    final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project);
    for (PsiFile psiFile : createdFiles) {
      if (psiFile instanceof PsiJavaFile) {
        codeStyleManager.removeRedundantImports((PsiJavaFile) psiFile);
      }
    }
    for (PsiElement expression : rebindExpressions) {
      codeStyleManager.shortenClassReferences(expression);
    }
    new OptimizeImportsProcessor(
            project, createdFiles.toArray(new PsiFile[createdFiles.size()]), null)
        .run();
    return newElement != null ? newElement : createdFiles.size() > 0 ? createdFiles.get(0) : null;
  }
 public static Collection<HierarchicalMethodSignature> getVisibleSignatures(PsiClass aClass) {
   Map<MethodSignature, HierarchicalMethodSignature> map = getSignaturesMap(aClass);
   return map.values();
 }
 public void doCopy(PsiElement[] elements, PsiDirectory defaultTargetDirectory) {
   FeatureUsageTracker.getInstance().triggerFeatureUsed("refactoring.copyClass");
   final HashMap<PsiFile, String> relativePathsMap = new HashMap<PsiFile, String>();
   final Map<PsiFile, PsiClass[]> classes =
       convertToTopLevelClasses(elements, false, "", relativePathsMap);
   assert classes != null;
   if (defaultTargetDirectory == null) {
     final PsiFile psiFile = classes.keySet().iterator().next();
     defaultTargetDirectory = psiFile.getContainingDirectory();
     LOG.assertTrue(defaultTargetDirectory != null, psiFile);
   } else {
     Project project = defaultTargetDirectory.getProject();
     VirtualFile sourceRootForFile =
         ProjectRootManager.getInstance(project)
             .getFileIndex()
             .getSourceRootForFile(defaultTargetDirectory.getVirtualFile());
     if (sourceRootForFile == null) {
       final List<PsiElement> files = new ArrayList<PsiElement>();
       for (int i = 0, elementsLength = elements.length; i < elementsLength; i++) {
         PsiFile containingFile = elements[i].getContainingFile();
         if (containingFile != null) {
           files.add(containingFile);
         } else if (elements[i] instanceof PsiDirectory) {
           files.add(elements[i]);
         }
       }
       CopyFilesOrDirectoriesHandler.copyAsFiles(
           files.toArray(new PsiElement[files.size()]), defaultTargetDirectory, project);
       return;
     }
   }
   Project project = defaultTargetDirectory.getProject();
   Object targetDirectory = null;
   String className = null;
   boolean openInEditor = true;
   if (copyOneClass(classes)) {
     final String commonPath =
         ArrayUtil.find(elements, classes.values().iterator().next()) == -1
             ? normalizeRelativeMap(relativePathsMap)
             : null;
     CopyClassDialog dialog =
         new CopyClassDialog(
             classes.values().iterator().next()[0], defaultTargetDirectory, project, false) {
           @Override
           protected String getQualifiedName() {
             if (commonPath != null && !commonPath.isEmpty()) {
               return StringUtil.getQualifiedName(
                   super.getQualifiedName(), commonPath.replaceAll("/", "."));
             }
             return super.getQualifiedName();
           }
         };
     dialog.setTitle(RefactoringBundle.message("copy.handler.copy.class"));
     dialog.show();
     if (dialog.isOK()) {
       openInEditor = dialog.openInEditor();
       targetDirectory = dialog.getTargetDirectory();
       className = dialog.getClassName();
       if (className == null || className.length() == 0) return;
     }
   } else {
     if (ApplicationManager.getApplication().isUnitTestMode()) {
       targetDirectory = defaultTargetDirectory;
     } else {
       defaultTargetDirectory =
           CopyFilesOrDirectoriesHandler.resolveDirectory(defaultTargetDirectory);
       if (defaultTargetDirectory == null) return;
       PsiElement[] files = PsiUtilCore.toPsiFileArray(classes.keySet());
       if (classes.keySet().size() == 1) {
         // do not choose a new name for a file when multiple classes exist in one file
         final PsiClass[] psiClasses = classes.values().iterator().next();
         if (psiClasses != null) {
           files = psiClasses;
         }
       }
       final CopyFilesOrDirectoriesDialog dialog =
           new CopyFilesOrDirectoriesDialog(files, defaultTargetDirectory, project, false);
       dialog.show();
       if (dialog.isOK()) {
         targetDirectory = dialog.getTargetDirectory();
         className = dialog.getNewName();
         openInEditor = dialog.openInEditor();
       }
     }
   }
   if (targetDirectory != null) {
     copyClassesImpl(
         className,
         project,
         classes,
         relativePathsMap,
         targetDirectory,
         defaultTargetDirectory,
         RefactoringBundle.message("copy.handler.copy.class"),
         false,
         openInEditor);
   }
 }