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