/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2014-2014 AS3Boyan
* Copyright 2014-2014 Elias Ku
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.plugins.haxe.util;
import com.intellij.openapi.util.Condition;
import com.intellij.plugins.haxe.lang.psi.*;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Created by fedorkorotkov.
*/
public class HaxeImportUtil {
public static List<HaxeImportStatementRegular> findUnusedImports(PsiFile file) {
final List<HaxeClass> classesInFile = getReferencedClasses(file);
List<HaxeImportStatementRegular> filteredUsefulImports = new ArrayList<HaxeImportStatementRegular>();
List<HaxeImportStatementRegular> allImportStatements = UsefulPsiTreeUtil.getAllImportStatements(file);
final List<HaxeImportStatementRegular> usefulImportStatements = ContainerUtil.findAll(allImportStatements, new Condition<HaxeImportStatementRegular>() {
@Override
public boolean value(HaxeImportStatementRegular statement) {
final HaxeImportStatementRegular regularImport = statement;
if(regularImport != null) {
final HaxeReferenceExpression referenceExpression = regularImport.getReferenceExpression();
if (null == referenceExpression) {
// It's an incomplete statement. It can't be useful.
return false;
}
if (referenceExpression.resolve() == null) {
// don't know for sure
return true;
}
}
for (HaxeClass haxeClass : classesInFile) {
if (UsefulPsiTreeUtil.importStatementForClass(statement, haxeClass)) {
return true;
}
}
return false;
}
});
for (int i = 0; i < usefulImportStatements.size(); i++) {
boolean alreadyAdded = false;
for (int j = 0; j < filteredUsefulImports.size(); j++) {
if (usefulImportStatements.get(i).getReferenceExpression().getText().equals(
filteredUsefulImports.get(j).getReferenceExpression().getText())) {
alreadyAdded = true;
break;
}
}
if (!alreadyAdded) {
filteredUsefulImports.add(usefulImportStatements.get(i));
}
}
List<HaxeImportStatementRegular> uselessImportStatements = new ArrayList<HaxeImportStatementRegular>(allImportStatements);
uselessImportStatements.removeAll(filteredUsefulImports);
return uselessImportStatements;
}
public static List<HaxeClass> getReferencedClasses(PsiFile file) {
final List<HaxeClass> classesInFile = new ArrayList<HaxeClass>();
file.acceptChildren(new HaxeRecursiveVisitor() {
@Override
public void visitElement(PsiElement element) {
super.visitElement(element);
if (element instanceof HaxeReference) {
HaxeClass haxeClass = ((HaxeReference)element).resolveHaxeClass().getHaxeClass();
if (haxeClass != null) {
classesInFile.add(haxeClass);
}
}
}
@Override
public void visitImportStatementRegular(@NotNull HaxeImportStatementRegular o) {
// stop
}
@Override
public void visitImportStatementWithInSupport(@NotNull HaxeImportStatementWithInSupport o) {
// stop
}
@Override
public void visitImportStatementWithWildcard(@NotNull HaxeImportStatementWithWildcard o) {
// stop
}
});
return classesInFile;
}
public static List<HaxeImportStatementWithInSupport> findUnusedInImports(PsiFile file) {
final List<String> referencesInFile = new ArrayList<String>();
file.acceptChildren(new HaxeRecursiveVisitor() {
@Override
public void visitElement(PsiElement element) {
super.visitElement(element);
if (element instanceof HaxeReference) {
referencesInFile.add(element.getText());
}
}
@Override
public void visitImportStatementRegular(@NotNull HaxeImportStatementRegular o) {
// stop
}
@Override
public void visitImportStatementWithInSupport(@NotNull HaxeImportStatementWithInSupport o) {
// stop
}
@Override
public void visitImportStatementWithWildcard(@NotNull HaxeImportStatementWithWildcard o) {
// stop
}
});
List<HaxeImportStatementWithInSupport> filteredUsefulImports = new ArrayList<HaxeImportStatementWithInSupport>();
List<HaxeImportStatementWithInSupport> allImportStatementWithInSupports = UsefulPsiTreeUtil.getAllInImportStatements(file);
List<HaxeImportStatementWithInSupport> usefulImportStatementWithInSupports =
ContainerUtil.findAll(allImportStatementWithInSupports, new Condition<HaxeImportStatementWithInSupport>() {
@Override
public boolean value(HaxeImportStatementWithInSupport importStatementWithInSupport) {
return referencesInFile.contains(importStatementWithInSupport.getIdentifier().getText());
}
});
for (int i = 0; i < usefulImportStatementWithInSupports.size(); i++) {
boolean alreadyAdded = false;
for (int j = 0; j < filteredUsefulImports.size(); j++) {
if (usefulImportStatementWithInSupports.get(i).getReferenceExpression().getText().equals(
filteredUsefulImports.get(j).getReferenceExpression().getText())
&& usefulImportStatementWithInSupports.get(i).getIdentifier().getText().equals(
filteredUsefulImports.get(j).getIdentifier().getText())) {
alreadyAdded = true;
break;
}
}
if (!alreadyAdded) {
filteredUsefulImports.add(usefulImportStatementWithInSupports.get(i));
}
}
List<HaxeImportStatementWithInSupport> uselessImportStatements = new ArrayList<HaxeImportStatementWithInSupport>(allImportStatementWithInSupports);
uselessImportStatements.removeAll(filteredUsefulImports);
return uselessImportStatements;
}
public static List<HaxeImportStatementWithWildcard> findUnusedInImportsWithWildcards(PsiFile file) {
final List<HaxeClass> classesInFile = new ArrayList<HaxeClass>();
final List<HaxeReference> referenceList = new ArrayList<HaxeReference>();
file.acceptChildren(new HaxeRecursiveVisitor() {
@Override
public void visitElement(PsiElement element) {
super.visitElement(element);
if (element instanceof HaxeReference) {
HaxeReference reference = (HaxeReference)element;
HaxeClass haxeClass = reference.resolveHaxeClass().getHaxeClass();
if (haxeClass != null) {
classesInFile.add(haxeClass);
}
referenceList.add(reference);
}
}
@Override
public void visitImportStatementRegular(@NotNull HaxeImportStatementRegular o) {
// stop
}
@Override
public void visitImportStatementWithInSupport(@NotNull HaxeImportStatementWithInSupport o) {
// stop
}
@Override
public void visitImportStatementWithWildcard(@NotNull HaxeImportStatementWithWildcard o) {
// stop
}
});
List<HaxeClass> alreadyImportedClassList = getAlreadyImportedClasses(file, classesInFile);
classesInFile.removeAll(alreadyImportedClassList);
List<HaxeImportStatementWithWildcard> filteredUsefulImports = new ArrayList<HaxeImportStatementWithWildcard>();
List<HaxeImportStatementWithWildcard> allImportStatementsWithWildcard = UsefulPsiTreeUtil.getAllImportStatementsWithWildcard(file);
List<HaxeImportStatementWithWildcard> usefulImportStatementWithInSupports =
ContainerUtil.findAll(allImportStatementsWithWildcard, new Condition<HaxeImportStatementWithWildcard>() {
@Override
public boolean value(HaxeImportStatementWithWildcard importStatementWithInSupport) {
String qName = UsefulPsiTreeUtil.getQNameForImportStatementWithWildcardType(importStatementWithInSupport);
boolean wildcardForType = UsefulPsiTreeUtil
.isImportStatementWildcardForType(qName);
if (wildcardForType) {
HaxeClass haxeClass = HaxeResolveUtil.findClassByQName(qName, importStatementWithInSupport.getContext());
if (haxeClass != null) {
for (HaxeReference reference : referenceList) {
String referenceText = reference.getText();
HaxeNamedComponent namedSubComponent = HaxeResolveUtil.findNamedSubComponent(haxeClass, referenceText);
if (namedSubComponent != null && namedSubComponent.isStatic()) {
return true;
}
}
}
}
else {
List<HaxeClass>
classesForImportStatementWithWildcard = UsefulPsiTreeUtil.getClassesForImportStatementWithWildcard(importStatementWithInSupport);
return !classesInFile.isEmpty() && !Collections.disjoint(classesInFile, classesForImportStatementWithWildcard);
}
return false;
}
});
for (int i = 0; i < usefulImportStatementWithInSupports.size(); i++) {
boolean alreadyAdded = false;
for (int j = 0; j < filteredUsefulImports.size(); j++) {
if (usefulImportStatementWithInSupports.get(i).getReferenceExpression().getText().equals(
filteredUsefulImports.get(j).getReferenceExpression().getText())) {
alreadyAdded = true;
break;
}
}
if (!alreadyAdded) {
filteredUsefulImports.add(usefulImportStatementWithInSupports.get(i));
}
}
List<HaxeImportStatementWithWildcard> uselessImportStatements = new ArrayList<HaxeImportStatementWithWildcard>(allImportStatementsWithWildcard);
uselessImportStatements.removeAll(filteredUsefulImports);
return uselessImportStatements;
}
public static List<HaxeClass> getAlreadyImportedClasses(PsiFile file, List<HaxeClass> classesInFile) {
List<HaxeImportStatementRegular> importStatements = UsefulPsiTreeUtil.getAllImportStatements(file);
List<HaxeClass> alreadyImportedClassList = new ArrayList<HaxeClass>();
for (HaxeImportStatementRegular importStatementRegular : importStatements) {
HaxeReferenceExpression referenceExpression = importStatementRegular.getReferenceExpression();
if (referenceExpression != null) {
PsiElement psiElement = referenceExpression.resolve();
if (psiElement != null) {
for (HaxeClass haxeClass : classesInFile) {
if (haxeClass.getContainingFile() == psiElement.getContainingFile()) {
if (!alreadyImportedClassList.contains(haxeClass)) {
alreadyImportedClassList.add(haxeClass);
}
}
}
}
}
}
return alreadyImportedClassList;
}
public static List<HaxeClass> getClassesUsedFromImportStatementWithWildcard(PsiFile file, HaxeImportStatementWithWildcard importStatementWithWildcard) {
List<HaxeClass>
classesForImportStatementWithWildcard = UsefulPsiTreeUtil.getClassesForImportStatementWithWildcard(importStatementWithWildcard);
final List<HaxeClass> referencedClasses = getReferencedClasses(file);
List<HaxeClass> alreadyImportedClasses = getAlreadyImportedClasses(file, referencedClasses);
referencedClasses.removeAll(alreadyImportedClasses);
classesForImportStatementWithWildcard.removeAll(alreadyImportedClasses);
List<HaxeClass> classesUsedClassesFromImportStatementWithWildcard =
ContainerUtil.findAll(classesForImportStatementWithWildcard, new Condition<HaxeClass>() {
@Override
public boolean value(HaxeClass haxeClass) {
return referencedClasses.contains(haxeClass);
}
});
return classesUsedClassesFromImportStatementWithWildcard;
}
}