package com.intellij.lang.javascript.flex;
import com.intellij.injected.editor.VirtualFileWindow;
import com.intellij.javascript.flex.FlexApplicationComponent;
import com.intellij.lang.javascript.ActionScriptFileType;
import com.intellij.lang.javascript.JavaScriptFileType;
import com.intellij.lang.javascript.TypeScriptFileType;
import com.intellij.lang.javascript.library.JSCorePredefinedLibrariesProvider;
import com.intellij.lang.javascript.psi.resolve.JSElementResolveScopeProvider;
import com.intellij.lang.javascript.psi.resolve.JSInheritanceUtil;
import com.intellij.lang.javascript.psi.resolve.JSResolveUtil;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiCodeFragment;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.ResolveScopeManager;
import com.intellij.psi.search.GlobalSearchScope;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class ActionScriptResolveScopeProvider extends JSElementResolveScopeProvider {
@Override
public GlobalSearchScope getResolveScope(@NotNull VirtualFile file, Project project) {
return getResolveScope(file, project, true);
}
@Nullable
private GlobalSearchScope getResolveScope(@NotNull VirtualFile file, Project project, boolean checkApplicable) {
if (file instanceof VirtualFileWindow) {
file = ((VirtualFileWindow)file).getDelegate();
}
if (checkApplicable && !isApplicable(file)) return null;
final ProjectFileIndex projectFileIndex = ProjectRootManager.getInstance(project).getFileIndex();
final Module module = projectFileIndex.getModuleForFile(file);
if (module != null) {
boolean includeTests = projectFileIndex.isInTestSourceContent(file) || !projectFileIndex.isInSourceContent(file);
final GlobalSearchScope moduleScope = GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module, includeTests);
// TODO [Konstantin.Ulitin] add package and swc file types
//final GlobalSearchScope fileTypesScope =
// GlobalSearchScope.getScopeRestrictedByFileTypes(moduleScope, ActionScriptFileType.INSTANCE,
// FlexApplicationComponent.SWF_FILE_TYPE, FlexApplicationComponent.MXML);
final GlobalSearchScope fileTypesScope =
moduleScope.intersectWith(GlobalSearchScope.notScope(
GlobalSearchScope.getScopeRestrictedByFileTypes(
moduleScope, TypeScriptFileType.INSTANCE, JavaScriptFileType.INSTANCE
)
));
return fileTypesScope.union(GlobalSearchScope.filesScope(project, JSCorePredefinedLibrariesProvider.getActionScriptPredefinedLibraryFiles()));
}
return null;
}
@NotNull
@Override
public GlobalSearchScope getElementResolveScope(@NotNull PsiElement element) {
final GlobalSearchScope tempScope = JSInheritanceUtil.getEnforcedScope();
if (tempScope != null) {
return tempScope;
}
PsiElement explicitContext = JSResolveUtil.getContext(element);
if (explicitContext != null) element = explicitContext;
if (element instanceof PsiCodeFragment) {
final GlobalSearchScope forced = ((PsiCodeFragment)element).getForcedResolveScope();
if (forced != null) return forced;
}
final PsiFile containingFile = element.getContainingFile();
if (containingFile == null) return getProjectScopeIncludingPredefines(element.getProject());
final PsiFile psiFile = containingFile.getOriginalFile();
VirtualFile file = psiFile.getVirtualFile();
final Project project = psiFile.getProject();
if (file == null) return getProjectScopeIncludingPredefines(project);
final GlobalSearchScope scope = isApplicable(file) ? ResolveScopeManager.getInstance(project).getDefaultResolveScope(file) : null;
if (scope != null) {
if (ProjectFileIndex.SERVICE.getInstance(project).isInLibraryClasses(file) && !scope.contains(file)) {
// safe but not 100% correct fix for IDEA-157606
// The problem happens when ModuleA -> ModuleB -> lib.swc and we calculate resolve scope for file from lib.swc. FlexOrderEnumerationHandler filters our 'ModuleB -> lib.swc' dependency because it is initialized with ModuleA. Oh, LibraryRuntimeClasspathScope computation is so complicated...
return scope.union(GlobalSearchScope.fileScope(project, file));
}
return scope;
}
final GlobalSearchScope fileResolveScope = getResolveScope(file, project, false);
return fileResolveScope != null ? fileResolveScope : getProjectScopeIncludingPredefines(project);
}
@Override
protected boolean isApplicable(@NotNull final VirtualFile file) {
return file.getFileType() == ActionScriptFileType.INSTANCE || file.getFileType() == FlexApplicationComponent.MXML ||
file.getFileType() == FlexApplicationComponent.SWF_FILE_TYPE;
}
}