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 MyDelegatingGlobalSearchScope();
067 javaFacade = KotlinJavaPsiFacade.getInstance(project);
068 }
069
070 public class MyDelegatingGlobalSearchScope extends DelegatingGlobalSearchScope {
071 public MyDelegatingGlobalSearchScope() {
072 super(JavaClassFinderImpl.this.baseScope);
073 }
074
075 public GlobalSearchScope getBaseScope() {
076 return myBaseScope;
077 }
078
079 @Override
080 public boolean contains(@NotNull VirtualFile file) {
081 return myBaseScope.contains(file) && (file.isDirectory() || file.getFileType() != KotlinFileType.INSTANCE);
082 }
083
084 //NOTE: expected by class finder to be not null
085 @NotNull
086 @Override
087 public Project getProject() {
088 return project;
089 }
090
091 @Override
092 public String toString() {
093 return "JCFI: " + baseScope;
094 }
095 }
096
097 @Nullable
098 @Override
099 public JavaClass findClass(@NotNull ClassId classId) {
100 PsiClass psiClass = javaFacade.findClass(classId, javaSearchScope);
101 if (psiClass == null) return null;
102
103 JavaClassImpl javaClass = new JavaClassImpl(psiClass);
104 FqName fqName = classId.asSingleFqName();
105 if (!fqName.equals(javaClass.getFqName())) {
106 throw new IllegalStateException("Requested " + fqName + ", got " + javaClass.getFqName());
107 }
108
109 if (psiClass instanceof KtLightClassMarker) {
110 throw new IllegalStateException("Kotlin light classes should not be found by JavaPsiFacade, resolving: " + fqName);
111 }
112
113 return javaClass;
114 }
115
116 @Nullable
117 @Override
118 public JavaPackage findPackage(@NotNull FqName fqName) {
119 PsiPackage psiPackage = javaFacade.findPackage(fqName.asString(), javaSearchScope);
120 return psiPackage == null ? null : new JavaPackageImpl(psiPackage, javaSearchScope);
121 }
122
123 @Nullable
124 @Override
125 public Set<String> knownClassNamesInPackage(@NotNull FqName packageFqName) {
126 return javaFacade.knownClassNamesInPackage(packageFqName);
127 }
128 }