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 }