001    /*
002     * Copyright 2010-2015 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.kotlin.load.java;
018    
019    import com.intellij.openapi.project.Project;
020    import com.intellij.openapi.vfs.VirtualFile;
021    import com.intellij.psi.PsiClass;
022    import com.intellij.psi.PsiPackage;
023    import com.intellij.psi.search.DelegatingGlobalSearchScope;
024    import com.intellij.psi.search.GlobalSearchScope;
025    import org.jetbrains.annotations.NotNull;
026    import org.jetbrains.annotations.Nullable;
027    import org.jetbrains.kotlin.idea.JetFileType;
028    import org.jetbrains.kotlin.load.java.structure.JavaClass;
029    import org.jetbrains.kotlin.load.java.structure.JavaPackage;
030    import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl;
031    import org.jetbrains.kotlin.load.java.structure.impl.JavaPackageImpl;
032    import org.jetbrains.kotlin.name.ClassId;
033    import org.jetbrains.kotlin.name.FqName;
034    import org.jetbrains.kotlin.resolve.jvm.JavaClassFinderPostConstruct;
035    import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade;
036    
037    import javax.annotation.PostConstruct;
038    import javax.inject.Inject;
039    
040    public class JavaClassFinderImpl implements JavaClassFinder {
041        private Project project;
042        private GlobalSearchScope baseScope;
043    
044        private GlobalSearchScope javaSearchScope;
045        private KotlinJavaPsiFacade javaFacade;
046    
047        @Inject
048        public void setProject(@NotNull Project project) {
049            this.project = project;
050        }
051    
052        @Inject
053        public void setScope(@NotNull GlobalSearchScope scope) {
054            this.baseScope = scope;
055        }
056    
057        @Inject
058        public void setComponentPostConstruct(@NotNull JavaClassFinderPostConstruct finderPostConstruct) {
059            // Only activate post create
060        }
061    
062        @PostConstruct
063        public void initialize() {
064            javaSearchScope = new DelegatingGlobalSearchScope(baseScope) {
065                @Override
066                public boolean contains(@NotNull VirtualFile file) {
067                    return myBaseScope.contains(file) && (file.isDirectory() || file.getFileType() != JetFileType.INSTANCE);
068                }
069    
070                //NOTE: expected by class finder to be not null
071                @NotNull
072                @Override
073                public Project getProject() {
074                    return project;
075                }
076    
077                @Override
078                public String toString() {
079                    return "JCFI: " + baseScope;
080                }
081            };
082    
083            javaFacade = KotlinJavaPsiFacade.getInstance(project);
084        }
085    
086        @Nullable
087        @Override
088        public JavaClass findClass(@NotNull ClassId classId) {
089            PsiClass psiClass = javaFacade.findClass(classId, javaSearchScope);
090            if (psiClass == null) return null;
091    
092            JavaClassImpl javaClass = new JavaClassImpl(psiClass);
093            FqName fqName = classId.asSingleFqName();
094            if (!fqName.equals(javaClass.getFqName())) {
095                throw new IllegalStateException("Requested " + fqName + ", got " + javaClass.getFqName());
096            }
097    
098            if (javaClass.getOriginKind() == JavaClass.OriginKind.KOTLIN_LIGHT_CLASS) {
099                throw new IllegalStateException("Kotlin light classes should not be found by JavaPsiFacade, resolving: " + fqName);
100            }
101    
102            return javaClass;
103        }
104    
105        @Nullable
106        @Override
107        public JavaPackage findPackage(@NotNull FqName fqName) {
108            PsiPackage psiPackage = javaFacade.findPackage(fqName.asString(), javaSearchScope);
109            return psiPackage == null ? null : new JavaPackageImpl(psiPackage, javaSearchScope);
110        }
111    }