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