@NotNull private static MultiMap<String, GoImportSpec> collectImportsWithSameString( @NotNull Collection<GoImportSpec> importsWithSameName) { MultiMap<String, GoImportSpec> importsWithSameString = MultiMap.create(); for (PsiElement duplicateCandidate : importsWithSameName) { GoImportSpec importSpec = getImportSpec(duplicateCandidate); if (importSpec != null) { importsWithSameString.putValue(importSpec.getPath(), importSpec); } } return importsWithSameString; }
@NotNull private ExistingImportData cachedImportData( @NotNull GoNamedElement element, @Nullable ExistingImportData existingValue) { if (existingValue != null) return existingValue; GoFile declarationFile = element.getContainingFile(); String importPath = declarationFile.getImportPath(); GoImportSpec existingImport = myImportedPackages.get(importPath); boolean exists = existingImport != null; boolean isDot = exists && existingImport.isDot(); String alias = existingImport != null ? existingImport.getAlias() : null; return new ExistingImportData(exists, isDot, alias, importPath); }
@NotNull public static Set<PsiElement> findRedundantImportIdentifiers( @NotNull MultiMap<String, GoImportSpec> importMap) { Set<PsiElement> importIdentifiersToDelete = ContainerUtil.newLinkedHashSet(); for (PsiElement importEntry : importMap.values()) { GoImportSpec importSpec = getImportSpec(importEntry); if (importSpec != null) { String localPackageName = importSpec.getLocalPackageName(); if (!StringUtil.isEmpty(localPackageName)) { if (Comparing.equal(importSpec.getAlias(), localPackageName)) { importIdentifiersToDelete.add(importSpec.getIdentifier()); } } } } return importIdentifiersToDelete; }
@NotNull private static Set<String> sortMatching( @NotNull PrefixMatcher matcher, @NotNull Collection<String> names, @NotNull GoFile file) { ProgressManager.checkCanceled(); String prefix = matcher.getPrefix(); if (prefix.isEmpty()) return ContainerUtil.newLinkedHashSet(names); Set<String> packagesWithAliases = ContainerUtil.newHashSet(); for (Map.Entry<String, Collection<GoImportSpec>> entry : file.getImportMap().entrySet()) { for (GoImportSpec spec : entry.getValue()) { String alias = spec.getAlias(); if (spec.isDot() || alias != null) { packagesWithAliases.add(entry.getKey()); break; } } } List<String> sorted = ContainerUtil.newArrayList(); for (String name : names) { if (matcher.prefixMatches(name) || packagesWithAliases.contains(substringBefore(name, '.'))) { sorted.add(name); } } ProgressManager.checkCanceled(); Collections.sort(sorted, String.CASE_INSENSITIVE_ORDER); ProgressManager.checkCanceled(); LinkedHashSet<String> result = new LinkedHashSet<String>(); for (String name : sorted) { if (matcher.isStartMatch(name)) { result.add(name); } } ProgressManager.checkCanceled(); result.addAll(sorted); return result; }
private static boolean hasImportUsers(@NotNull GoImportSpec spec) { //noinspection SynchronizationOnLocalVariableOrMethodParameter synchronized (spec) { List<PsiElement> list = spec.getUserData(GoReferenceBase.IMPORT_USERS); if (list != null) { for (PsiElement e : list) { if (e.isValid()) { return true; } ProgressManager.checkCanceled(); } } } return false; }
public static MultiMap<String, GoImportSpec> filterUnusedImports( @NotNull PsiFile file, @NotNull MultiMap<String, GoImportSpec> importMap) { MultiMap<String, GoImportSpec> result = MultiMap.create(); result.putAllValues(importMap); result.remove("_"); // imports for side effects are always used Collection<GoImportSpec> implicitImports = ContainerUtil.newArrayList(result.get(".")); for (GoImportSpec importEntry : implicitImports) { GoImportSpec spec = getImportSpec(importEntry); if (spec != null && spec.isDot() && hasImportUsers(spec)) { result.remove(".", importEntry); } } file.accept( new GoRecursiveVisitor() { @Override public void visitTypeReferenceExpression(@NotNull GoTypeReferenceExpression o) { GoTypeReferenceExpression lastQualifier = o.getQualifier(); if (lastQualifier != null) { GoTypeReferenceExpression previousQualifier; while ((previousQualifier = lastQualifier.getQualifier()) != null) { lastQualifier = previousQualifier; } markAsUsed(lastQualifier.getIdentifier(), lastQualifier.getReference()); } } @Override public void visitReferenceExpression(@NotNull GoReferenceExpression o) { GoReferenceExpression lastQualifier = o.getQualifier(); if (lastQualifier != null) { GoReferenceExpression previousQualifier; while ((previousQualifier = lastQualifier.getQualifier()) != null) { lastQualifier = previousQualifier; } markAsUsed(lastQualifier.getIdentifier(), lastQualifier.getReference()); } } private void markAsUsed(@NotNull PsiElement qualifier, @NotNull PsiReference reference) { String qualifierText = qualifier.getText(); if (!result.containsKey(qualifierText)) { // already marked return; } PsiElement resolve = reference.resolve(); if (!(resolve instanceof PsiDirectory || resolve instanceof GoImportSpec || resolve instanceof PsiDirectoryContainer)) { return; } Collection<String> qualifiersToDelete = ContainerUtil.newHashSet(); for (GoImportSpec spec : result.get(qualifierText)) { for (Map.Entry<String, Collection<GoImportSpec>> entry : result.entrySet()) { for (GoImportSpec importSpec : entry.getValue()) { if (importSpec == spec) { qualifiersToDelete.add(entry.getKey()); } } } } for (String qualifierToDelete : qualifiersToDelete) { result.remove(qualifierToDelete); } } }); return result; }
public static MultiMap<String, GoImportSpec> filterUnusedImports( @NotNull PsiFile file, @NotNull final MultiMap<String, GoImportSpec> importMap) { final MultiMap<String, GoImportSpec> result = MultiMap.create(); result.putAllValues(importMap); result.remove("_"); // imports for side effects are always used Collection<GoImportSpec> implicitImports = ContainerUtil.newArrayList(result.get(".")); for (GoImportSpec importEntry : implicitImports) { GoImportSpec spec = getImportSpec(importEntry); if (spec != null && spec.isDot()) { List<? extends PsiElement> list = spec.getUserData(GoReference.IMPORT_USERS); if (list != null) { for (PsiElement e : list) { if (e.isValid()) { result.remove(".", importEntry); } } } } } file.accept( new GoRecursiveVisitor() { @Override public void visitTypeReferenceExpression(@NotNull GoTypeReferenceExpression o) { GoTypeReferenceExpression lastQualifier = o.getQualifier(); if (lastQualifier != null) { GoTypeReferenceExpression previousQualifier; while ((previousQualifier = lastQualifier.getQualifier()) != null) { lastQualifier = previousQualifier; } markAsUsed(lastQualifier.getIdentifier()); } } @Override public void visitReferenceExpression(@NotNull GoReferenceExpression o) { GoReferenceExpression lastQualifier = o.getQualifier(); if (lastQualifier != null) { GoReferenceExpression previousQualifier; while ((previousQualifier = lastQualifier.getQualifier()) != null) { lastQualifier = previousQualifier; } markAsUsed(lastQualifier.getIdentifier()); } } private void markAsUsed(@NotNull PsiElement qualifier) { Collection<String> qualifiersToDelete = ContainerUtil.newHashSet(); for (GoImportSpec spec : result.get(qualifier.getText())) { for (Map.Entry<String, Collection<GoImportSpec>> entry : result.entrySet()) { for (GoImportSpec importSpec : entry.getValue()) { if (importSpec == spec) { qualifiersToDelete.add(entry.getKey()); } } } } for (String qualifierToDelete : qualifiersToDelete) { result.remove(qualifierToDelete); } } }); return result; }