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; }
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; }
@Nullable protected VirtualFile findCoreJar(@Nullable Module module) { if (module == null) return null; JavaPsiFacade javaFacade = JavaPsiFacade.getInstance(module.getProject()); for (PsiClass aClass : javaFacade.findClasses( getSomeFrameworkClass(), GlobalSearchScope.moduleWithLibrariesScope(module))) { VirtualFile virtualFile = aClass.getContainingFile().getVirtualFile(); if (virtualFile != null && virtualFile.getFileSystem() instanceof JarFileSystem) { VirtualFile localFile = PathUtil.getLocalFile(virtualFile); if (isCoreJar(localFile)) { return localFile; } } } return null; }
public static void addAvailableSystemScripts( final Collection<String> result, @NotNull Module module) { VirtualFile scriptRoot = null; GlobalSearchScope searchScope = GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module, false); for (PsiClass aClass : JavaPsiFacade.getInstance(module.getProject()).findClasses("CreateApp_", searchScope)) { PsiClass superClass = aClass.getSuperClass(); if (superClass != null && GroovyCommonClassNames.GROOVY_LANG_SCRIPT.equals(superClass.getQualifiedName())) { PsiFile psiFile = aClass.getContainingFile(); if (psiFile != null) { VirtualFile file = psiFile.getVirtualFile(); if (file != null && file.getFileSystem() instanceof ArchiveFileSystem) { VirtualFile parent = file.getParent(); if (parent != null && parent.findChild("Console.class") != null) { scriptRoot = parent; break; } } } } } if (scriptRoot == null) return; Pattern scriptPattern = Pattern.compile("([A-Za-z0-9]+)_?\\.class"); for (VirtualFile file : scriptRoot.getChildren()) { Matcher matcher = scriptPattern.matcher(file.getName()); if (matcher.matches()) { result.add(GroovyNamesUtil.camelToSnake(matcher.group(1))); } } }
@NotNull private List<Pair<PsiClass, VirtualFile>> doFindClasses( @NotNull String qName, @NotNull final GlobalSearchScope scope) { final Collection<PsiClass> classes = JavaFullClassNameIndex.getInstance().get(qName.hashCode(), myManager.getProject(), scope); if (classes.isEmpty()) return Collections.emptyList(); List<Pair<PsiClass, VirtualFile>> result = new ArrayList<>(classes.size()); for (PsiClass aClass : classes) { final String qualifiedName = aClass.getQualifiedName(); if (qualifiedName == null || !qualifiedName.equals(qName)) continue; PsiFile file = aClass.getContainingFile(); if (file == null) { throw new AssertionError("No file for class: " + aClass + " of " + aClass.getClass()); } final boolean valid = file.isValid(); VirtualFile vFile = file.getVirtualFile(); if (!valid) { LOG.error( "Invalid file " + file + "; virtualFile:" + vFile + (vFile != null && !vFile.isValid() ? " (invalid)" : "") + "; id=" + (vFile == null ? 0 : ((VirtualFileWithId) vFile).getId()), new PsiInvalidElementAccessException(aClass)); continue; } if (!hasAcceptablePackage(vFile)) continue; result.add(Pair.create(aClass, vFile)); } return result; }
@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; }