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 }