public AddModuleDependencyFix(
      Module currentModule, VirtualFile classVFile, PsiClass[] classes, PsiReference reference) {
    final PsiElement psiElement = reference.getElement();
    final Project project = psiElement.getProject();
    final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
    final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();

    for (PsiClass aClass : classes) {
      if (!facade.getResolveHelper().isAccessible(aClass, psiElement, aClass)) continue;
      PsiFile psiFile = aClass.getContainingFile();
      if (psiFile == null) continue;
      VirtualFile virtualFile = psiFile.getVirtualFile();
      if (virtualFile == null) continue;
      final Module classModule = fileIndex.getModuleForFile(virtualFile);
      if (classModule != null
          && classModule != currentModule
          && !ModuleRootManager.getInstance(currentModule).isDependsOn(classModule)) {
        myModules.add(classModule);
      }
    }
    myCurrentModule = currentModule;
    myClassVFile = classVFile;
    myClasses = classes;
    myReference = reference;
  }
 @Override
 public Icon getIcon() {
   Icon icon = myIcon;
   if (icon == null) {
     PsiElement psiElement = getElement();
     myIcon = icon = psiElement != null && psiElement.isValid() ? psiElement.getIcon(0) : null;
   }
   return icon;
 }
 @NotNull
 private static Set<VirtualFile> getLocalScopeFiles(@NotNull LocalSearchScope scope) {
   Set<VirtualFile> files = new LinkedHashSet<VirtualFile>();
   for (PsiElement element : scope.getScope()) {
     PsiFile file = element.getContainingFile();
     if (file != null) {
       ContainerUtil.addIfNotNull(files, file.getVirtualFile());
     }
   }
   return files;
 }
 @Override
 public boolean isValid() {
   PsiElement element = getElement();
   if (element == null || !element.isValid()) {
     return false;
   }
   for (UsageInfo usageInfo : getMergedInfos()) {
     if (usageInfo.getSegment() == null) return false;
   }
   return true;
 }
 private static List<PsiClass> filterAllowedDependencies(PsiElement element, PsiClass[] classes) {
   DependencyValidationManager dependencyValidationManager =
       DependencyValidationManager.getInstance(element.getProject());
   PsiFile fromFile = element.getContainingFile();
   List<PsiClass> result = new ArrayList<PsiClass>();
   for (PsiClass psiClass : classes) {
     if (dependencyValidationManager.getViolatorDependencyRule(
             fromFile, psiClass.getContainingFile())
         == null) {
       result.add(psiClass);
     }
   }
   return result;
 }
  @NotNull
  private TextChunk[] initChunks() {
    PsiFile psiFile = getPsiFile();
    Document document =
        psiFile == null ? null : PsiDocumentManager.getInstance(getProject()).getDocument(psiFile);
    TextChunk[] chunks;
    if (document == null) {
      // element over light virtual file
      PsiElement element = getElement();
      chunks = new TextChunk[] {new TextChunk(new TextAttributes(), element.getText())};
    } else {
      chunks = ChunkExtractor.extractChunks(psiFile, this);
    }

    myTextChunks = new SoftReference<TextChunk[]>(chunks);
    return chunks;
  }
    public void beforePropertyChange(@NotNull final PsiTreeChangeEvent event) {
      if (event.getPropertyName().equals(PsiTreeChangeEvent.PROP_FILE_NAME)
          || event.getPropertyName().equals(PsiTreeChangeEvent.PROP_DIRECTORY_NAME)) {
        final PsiElement psiElement = event.getChild();
        if (psiElement instanceof PsiFile || psiElement instanceof PsiDirectory) {
          final Module module = ModuleUtil.findModuleForPsiElement(psiElement);
          if (module == null) return;
          final String url =
              ((PsiDirectory) psiElement.getParent()).getVirtualFile().getUrl()
                  + "/"
                  + event.getNewValue();
          final AbstractUrl childUrl =
              psiElement instanceof PsiFile
                  ? new PsiFileUrl(url)
                  : new DirectoryUrl(url, module.getName());

          for (String listName : myName2FavoritesRoots.keySet()) {
            final List<TreeItem<Pair<AbstractUrl, String>>> roots =
                myName2FavoritesRoots.get(listName);
            iterateTreeItems(
                roots,
                new Consumer<TreeItem<Pair<AbstractUrl, String>>>() {
                  @Override
                  public void consume(TreeItem<Pair<AbstractUrl, String>> item) {
                    final Pair<AbstractUrl, String> root = item.getData();
                    final Object[] path = root.first.createPath(myProject);
                    if (path == null || path.length < 1 || path[0] == null) {
                      return;
                    }
                    final Object element = path[path.length - 1];
                    if (element == psiElement && psiElement instanceof PsiFile) {
                      item.setData(Pair.create(childUrl, root.second));
                    } else {
                      item.setData(root);
                    }
                  }
                });
          }
        }
      }
    }
Exemple #8
0
  @Nullable
  public VirtualFile findAppDirectory(@Nullable PsiElement element) {
    if (element == null) return null;

    PsiFile containingFile = element.getContainingFile().getOriginalFile();
    VirtualFile file = containingFile.getVirtualFile();
    if (file == null) return null;

    ProjectFileIndex index =
        ProjectRootManager.getInstance(containingFile.getProject()).getFileIndex();

    VirtualFile root = index.getContentRootForFile(file);
    if (root == null) return null;

    return root.findChild(getApplicationDirectoryName());
  }
  public static void addJarsToRoots(
      @NotNull final List<String> jarPaths,
      @Nullable final String libraryName,
      @NotNull final Module module,
      @Nullable final PsiElement location) {
    final Boolean isAdded =
        provideFix(
            new Function<MissingDependencyFixProvider, Boolean>() {
              @Override
              public Boolean fun(MissingDependencyFixProvider provider) {
                return provider.addJarsToRoots(jarPaths, libraryName, module, location);
              }
            });
    if (Boolean.TRUE.equals(isAdded)) return;

    List<String> urls =
        ContainerUtil.map(
            jarPaths,
            new Function<String, String>() {
              @Override
              public String fun(String path) {
                return refreshAndConvertToUrl(path);
              }
            });
    boolean inTests = false;
    if (location != null) {
      final VirtualFile vFile = location.getContainingFile().getVirtualFile();
      if (vFile != null
          && ModuleRootManager.getInstance(module).getFileIndex().isInTestSourceContent(vFile)) {
        inTests = true;
      }
    }
    ModuleRootModificationUtil.addModuleLibrary(
        module,
        libraryName,
        urls,
        Collections.<String>emptyList(),
        inTests ? DependencyScope.TEST : DependencyScope.COMPILE);
  }
  @Override
  @NotNull
  public AnnotationPlace chooseAnnotationsPlace(@NotNull final PsiElement element) {
    if (!element.isPhysical()) return AnnotationPlace.IN_CODE; // element just created
    if (!element.getManager().isInProject(element)) return AnnotationPlace.EXTERNAL;
    final Project project = myPsiManager.getProject();
    final PsiFile containingFile = element.getContainingFile();
    final VirtualFile virtualFile = containingFile.getVirtualFile();
    LOG.assertTrue(virtualFile != null);
    final List<OrderEntry> entries =
        ProjectRootManager.getInstance(project).getFileIndex().getOrderEntriesForFile(virtualFile);
    if (!entries.isEmpty()) {
      for (OrderEntry entry : entries) {
        if (!(entry instanceof ModuleOrderEntry)) {
          if (AnnotationOrderRootType.getUrls(entry).length > 0) {
            return AnnotationPlace.EXTERNAL;
          }
          break;
        }
      }
    }
    final MyExternalPromptDialog dialog =
        ApplicationManager.getApplication().isUnitTestMode()
                || ApplicationManager.getApplication().isHeadlessEnvironment()
            ? null
            : new MyExternalPromptDialog(project);
    if (dialog != null && dialog.isToBeShown()) {
      final PsiElement highlightElement =
          element instanceof PsiNameIdentifierOwner
              ? ((PsiNameIdentifierOwner) element).getNameIdentifier()
              : element.getNavigationElement();
      LOG.assertTrue(highlightElement != null);
      final Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor();
      final List<RangeHighlighter> highlighters = new ArrayList<RangeHighlighter>();
      final boolean highlight =
          editor != null
              && editor.getDocument()
                  == PsiDocumentManager.getInstance(project).getDocument(containingFile);
      try {
        if (highlight) { // do not highlight for batch inspections
          final EditorColorsManager colorsManager = EditorColorsManager.getInstance();
          final TextAttributes attributes =
              colorsManager.getGlobalScheme().getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES);
          final TextRange textRange = highlightElement.getTextRange();
          HighlightManager.getInstance(project)
              .addRangeHighlight(
                  editor,
                  textRange.getStartOffset(),
                  textRange.getEndOffset(),
                  attributes,
                  true,
                  highlighters);
          final LogicalPosition logicalPosition =
              editor.offsetToLogicalPosition(textRange.getStartOffset());
          editor.getScrollingModel().scrollTo(logicalPosition, ScrollType.CENTER);
        }

        dialog.show();
        if (dialog.getExitCode() == 2) {
          return AnnotationPlace.EXTERNAL;
        } else if (dialog.getExitCode() == 1) {
          return AnnotationPlace.NOWHERE;
        }

      } finally {
        if (highlight) {
          HighlightManager.getInstance(project)
              .removeSegmentHighlighter(editor, highlighters.get(0));
        }
      }
    } else if (dialog != null) {
      dialog.close(DialogWrapper.OK_EXIT_CODE);
    }
    return AnnotationPlace.IN_CODE;
  }
  @Nullable
  public static List<LocalQuickFix> registerFixes(
      @NotNull final QuickFixActionRegistrar registrar, @NotNull final PsiReference reference) {
    final PsiElement psiElement = reference.getElement();
    @NonNls
    final String shortReferenceName = reference.getRangeInElement().substring(psiElement.getText());

    Project project = psiElement.getProject();
    PsiFile containingFile = psiElement.getContainingFile();
    if (containingFile == null) return null;

    final VirtualFile classVFile = containingFile.getVirtualFile();
    if (classVFile == null) return null;

    final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
    final Module currentModule = fileIndex.getModuleForFile(classVFile);
    if (currentModule == null) return null;

    final List<LocalQuickFix> providedFixes =
        findFixes(
            new Function<MissingDependencyFixProvider, List<LocalQuickFix>>() {
              @Override
              public List<LocalQuickFix> fun(MissingDependencyFixProvider provider) {
                return provider.registerFixes(registrar, reference);
              }
            });
    if (providedFixes != null) {
      return providedFixes;
    }

    List<LocalQuickFix> result = new ArrayList<LocalQuickFix>();
    JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
    String fullReferenceText = reference.getCanonicalText();
    for (ExternalLibraryResolver resolver : ExternalLibraryResolver.EP_NAME.getExtensions()) {
      final ExternalClassResolveResult resolveResult =
          resolver.resolveClass(shortReferenceName, isReferenceToAnnotation(psiElement));
      OrderEntryFix fix = null;
      if (resolveResult != null
          && psiFacade.findClass(
                  resolveResult.getQualifiedClassName(),
                  currentModule.getModuleWithDependenciesAndLibrariesScope(true))
              == null) {
        fix =
            new AddExternalLibraryToDependenciesQuickFix(
                currentModule,
                resolveResult.getLibrary(),
                reference,
                resolveResult.getQualifiedClassName());
      } else if (!fullReferenceText.equals(shortReferenceName)) {
        ExternalLibraryDescriptor descriptor = resolver.resolvePackage(fullReferenceText);
        if (descriptor != null) {
          fix =
              new AddExternalLibraryToDependenciesQuickFix(
                  currentModule, descriptor, reference, null);
        }
      }
      if (fix != null) {
        registrar.register(fix);
        result.add(fix);
      }
    }
    if (!result.isEmpty()) {
      return result;
    }

    Set<Object> librariesToAdd = new THashSet<Object>();
    final JavaPsiFacade facade = JavaPsiFacade.getInstance(psiElement.getProject());
    PsiClass[] classes =
        PsiShortNamesCache.getInstance(project)
            .getClassesByName(shortReferenceName, GlobalSearchScope.allScope(project));
    List<PsiClass> allowedDependencies = filterAllowedDependencies(psiElement, classes);
    if (allowedDependencies.isEmpty()) {
      return result;
    }
    classes = allowedDependencies.toArray(new PsiClass[allowedDependencies.size()]);
    OrderEntryFix moduleDependencyFix =
        new AddModuleDependencyFix(currentModule, classVFile, classes, reference);

    final PsiClass[] finalClasses = classes;
    final OrderEntryFix finalModuleDependencyFix = moduleDependencyFix;
    final OrderEntryFix providedModuleDependencyFix =
        provideFix(
            new Function<MissingDependencyFixProvider, OrderEntryFix>() {
              @Override
              public OrderEntryFix fun(MissingDependencyFixProvider provider) {
                return provider.getAddModuleDependencyFix(
                    reference, finalModuleDependencyFix, currentModule, classVFile, finalClasses);
              }
            });
    moduleDependencyFix = ObjectUtils.notNull(providedModuleDependencyFix, moduleDependencyFix);

    registrar.register(moduleDependencyFix);
    result.add(moduleDependencyFix);
    for (final PsiClass aClass : classes) {
      if (!facade.getResolveHelper().isAccessible(aClass, psiElement, aClass)) continue;
      PsiFile psiFile = aClass.getContainingFile();
      if (psiFile == null) continue;
      VirtualFile virtualFile = psiFile.getVirtualFile();
      if (virtualFile == null) continue;
      ModuleFileIndex moduleFileIndex = ModuleRootManager.getInstance(currentModule).getFileIndex();
      for (OrderEntry orderEntry : fileIndex.getOrderEntriesForFile(virtualFile)) {
        if (orderEntry instanceof LibraryOrderEntry) {
          final LibraryOrderEntry libraryEntry = (LibraryOrderEntry) orderEntry;
          final Library library = libraryEntry.getLibrary();
          if (library == null) continue;
          VirtualFile[] files = library.getFiles(OrderRootType.CLASSES);
          if (files.length == 0) continue;
          final VirtualFile jar = files[0];

          if (jar == null
              || libraryEntry.isModuleLevel() && !librariesToAdd.add(jar)
              || !librariesToAdd.add(library)) continue;
          OrderEntry entryForFile = moduleFileIndex.getOrderEntryForFile(virtualFile);
          if (entryForFile != null
              && !(entryForFile instanceof ExportableOrderEntry
                  && ((ExportableOrderEntry) entryForFile).getScope() == DependencyScope.TEST
                  && !ModuleRootManager.getInstance(currentModule)
                      .getFileIndex()
                      .isInTestSourceContent(classVFile))) {
            continue;
          }
          final OrderEntryFix platformFix =
              new OrderEntryFix() {
                @Override
                @NotNull
                public String getText() {
                  return QuickFixBundle.message(
                      "orderEntry.fix.add.library.to.classpath", libraryEntry.getPresentableName());
                }

                @Override
                @NotNull
                public String getFamilyName() {
                  return QuickFixBundle.message("orderEntry.fix.family.add.library.to.classpath");
                }

                @Override
                public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
                  return !project.isDisposed()
                      && !currentModule.isDisposed()
                      && libraryEntry.isValid();
                }

                @Override
                public void invoke(
                    @NotNull final Project project, @Nullable final Editor editor, PsiFile file) {
                  OrderEntryUtil.addLibraryToRoots(libraryEntry, currentModule);
                  if (editor != null) {
                    DumbService.getInstance(project)
                        .withAlternativeResolveEnabled(
                            new Runnable() {
                              @Override
                              public void run() {
                                new AddImportAction(project, reference, editor, aClass).execute();
                              }
                            });
                  }
                }
              };

          final OrderEntryFix providedFix =
              provideFix(
                  new Function<MissingDependencyFixProvider, OrderEntryFix>() {
                    @Override
                    public OrderEntryFix fun(MissingDependencyFixProvider provider) {
                      return provider.getAddLibraryToClasspathFix(
                          reference, platformFix, currentModule, libraryEntry, aClass);
                    }
                  });
          final OrderEntryFix fix = ObjectUtils.notNull(providedFix, platformFix);
          registrar.register(fix);
          result.add(fix);
        }
      }
    }
    return result;
  }