001    /*
002     * Copyright 2010-2013 JetBrains s.r.o.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.jetbrains.jet.lang.resolve.java;
018    
019    import com.google.common.collect.Lists;
020    import com.intellij.core.CoreJavaFileManager;
021    import com.intellij.openapi.components.ServiceManager;
022    import com.intellij.openapi.progress.ProgressIndicatorProvider;
023    import com.intellij.openapi.project.Project;
024    import com.intellij.psi.PsiClass;
025    import com.intellij.psi.PsiElementFinder;
026    import com.intellij.psi.PsiPackage;
027    import com.intellij.psi.impl.JavaPsiFacadeImpl;
028    import com.intellij.psi.impl.file.impl.JavaFileManager;
029    import com.intellij.psi.search.GlobalSearchScope;
030    import org.jetbrains.annotations.NotNull;
031    import org.jetbrains.annotations.Nullable;
032    
033    import java.util.List;
034    
035    /**
036     * TODO Temporary class until {@link JavaPsiFacadeImpl} hacked.
037     *
038     * @see JavaPsiFacadeImpl
039     */
040    public class JavaPsiFacadeKotlinHacks {
041        public interface KotlinFinderMarker {}
042    
043        private final JavaFileManager javaFileManager;
044        private final List<PsiElementFinder> extensionPsiElementFinders;
045        private final boolean isCoreJavaFileManager;
046    
047        public JavaPsiFacadeKotlinHacks(@NotNull Project project) {
048            this.javaFileManager = findJavaFileManager(project);
049            this.isCoreJavaFileManager = javaFileManager instanceof CoreJavaFileManager;
050            this.extensionPsiElementFinders = Lists.newArrayList();
051            for (PsiElementFinder finder : project.getExtensions(PsiElementFinder.EP_NAME)) {
052                if (!(finder instanceof KotlinFinderMarker)) {
053                    this.extensionPsiElementFinders.add(finder);
054                }
055            }
056        }
057    
058        @NotNull
059        private static JavaFileManager findJavaFileManager(@NotNull Project project) {
060            JavaFileManager javaFileManager = ServiceManager.getService(project, JavaFileManager.class);
061            if (javaFileManager != null) {
062                return javaFileManager;
063            }
064            throw new IllegalStateException("JavaFileManager component is not found in project");
065        }
066    
067        @Nullable
068        public PsiPackage findPackage(@NotNull String qualifiedName) {
069            PsiPackage psiPackage = javaFileManager.findPackage(qualifiedName);
070            if (psiPackage != null) {
071                return psiPackage;
072            }
073    
074            for (PsiElementFinder finder : extensionPsiElementFinders) {
075                psiPackage = finder.findPackage(qualifiedName);
076                if (psiPackage != null) {
077                    return psiPackage;
078                }
079            }
080            return null;
081        }
082    
083        public PsiClass findClass(@NotNull String qualifiedName, @NotNull GlobalSearchScope scope) {
084            ProgressIndicatorProvider.checkCanceled(); // We hope this method is being called often enough to cancel daemon processes smoothly
085    
086            PsiClass aClass = javaFileManager.findClass(qualifiedName, scope);
087            if (aClass != null) {
088                //TODO: (module refactoring) CoreJavaFileManager should check scope
089                if (!isCoreJavaFileManager || scope.contains(aClass.getContainingFile().getOriginalFile().getVirtualFile())) {
090                    return aClass;
091                }
092            }
093    
094            for (PsiElementFinder finder : extensionPsiElementFinders) {
095                aClass = finder.findClass(qualifiedName, scope);
096                if (aClass != null) {
097                    return aClass;
098                }
099            }
100    
101            return null;
102        }
103    }