/* * Copyright 2013 Guidewire Software, Inc. */ package gw.plugin.ij.intentions; import com.intellij.codeInsight.daemon.impl.quickfix.ImportClassFixBase; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiMember; import com.intellij.psi.util.ClassUtil; import gw.lang.reflect.IDefaultTypeLoader; import gw.lang.reflect.IType; import gw.lang.reflect.ITypeLoader; import gw.lang.reflect.TypeSystem; import gw.lang.reflect.gs.GosuClassTypeLoader; import gw.lang.reflect.module.IModule; import gw.plugin.ij.completion.handlers.filter.CompletionFilter; import gw.plugin.ij.completion.handlers.filter.CompletionFilterExtensionPointBean; import gw.plugin.ij.lang.psi.api.types.IGosuCodeReferenceElement; import gw.plugin.ij.lang.psi.impl.CustomPsiClassCache; import gw.plugin.ij.util.GosuModuleUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; public class GosuAddMissingUsesFix extends ImportClassFixBase<IGosuCodeReferenceElement, IGosuCodeReferenceElement> { private final IGosuCodeReferenceElement ref; public GosuAddMissingUsesFix(@NotNull IGosuCodeReferenceElement ref) { super(ref, ref); this.ref = ref; } @Override public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiFile file) { return true; } @Override protected String getReferenceName(@NotNull IGosuCodeReferenceElement reference) { return reference.getReferenceName(); } @Nullable @Override protected PsiElement getReferenceNameElement(IGosuCodeReferenceElement reference) { return null; } @Override protected boolean hasTypeParameters(@NotNull IGosuCodeReferenceElement reference) { return reference.getTypeArguments().length > 0; } @Override protected boolean isAccessible(PsiMember psiMember, IGosuCodeReferenceElement iGosuCodeReferenceElement) { return true; } @NotNull @Override protected String getQualifiedName(@NotNull IGosuCodeReferenceElement reference) { return reference.getCanonicalText(); } @Override protected boolean isQualified(@NotNull IGosuCodeReferenceElement reference) { return reference.getQualifier() != null; } @Override protected boolean hasUnresolvedImportWhichCanImport(PsiFile psiFile, String name) { // if (!(psiFile instanceof IGosuFile)) return false; // final IGosuUsesStatement[] importStatements = ((IGosuFile)psiFile).getUsesStatements(); // for (IGosuUsesStatement importStatement : importStatements) { n // final IGosuCodeReferenceElement importReference = importStatement.getImportReference(); // if (importReference == null || importReference.resolve() != null) { // continue; // } // return true; // } return false; } @NotNull @Override public List<PsiClass> getClassesToImport() { List<PsiClass> classes = new ArrayList<>(); classes.addAll(super.getClassesToImport()); IModule ctxModule = GosuModuleUtil.findModuleForPsiElement(ref); if (ctxModule == null) { ctxModule = TypeSystem.getGlobalModule(); } String referenceName = ref.getReferenceName(); Set<String> fqns = new HashSet<>(); for (PsiClass pc : classes) { fqns.add(pc.getQualifiedName()); } for (IModule module : ctxModule.getModuleTraversalList()) { for (ITypeLoader loader : module.getModuleTypeLoader().getTypeLoaderStack()) { if (!(loader instanceof GosuClassTypeLoader || loader instanceof IDefaultTypeLoader)) { TypeSystem.pushModule(module); try { for (CharSequence typeName : loader.getAllTypeNames()) { String fqn = typeName.toString(); if (!fqns.add(fqn)) { continue; } String simpleName = ClassUtil.extractClassName(fqn); if (simpleName.equals(referenceName)) { IType type = TypeSystem.getByFullNameIfValid(fqn, loader.getModule()); if (type != null) { PsiClass psiClass = CustomPsiClassCache.instance().getPsiClass(type); if (psiClass != null) { classes.add(psiClass); } } } } } finally { TypeSystem.popModule(module); } } } } filter(classes); return classes; } private void filter(List<PsiClass> classes) { for (Iterator<PsiClass> it = classes.iterator(); it.hasNext();) { PsiClass cl = it.next(); List<CompletionFilter> filters = CompletionFilterExtensionPointBean.getFilters(); for (CompletionFilter filter : filters) { if (!filter.allowsImportInsertion(cl.getQualifiedName())) { it.remove(); } } } } }