001 /* 002 * Copyright 2010-2013 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.jet.lang.resolve.java; 018 019 import com.intellij.openapi.project.Project; 020 import com.intellij.openapi.util.Comparing; 021 import com.intellij.openapi.vfs.VirtualFile; 022 import com.intellij.psi.PsiClass; 023 import com.intellij.psi.PsiPackage; 024 import com.intellij.psi.search.DelegatingGlobalSearchScope; 025 import com.intellij.psi.search.GlobalSearchScope; 026 import org.jetbrains.annotations.NotNull; 027 import org.jetbrains.annotations.Nullable; 028 import org.jetbrains.jet.lang.resolve.java.structure.JavaClass; 029 import org.jetbrains.jet.lang.resolve.java.structure.JavaPackage; 030 import org.jetbrains.jet.lang.resolve.java.structure.impl.JavaClassImpl; 031 import org.jetbrains.jet.lang.resolve.java.structure.impl.JavaPackageImpl; 032 import org.jetbrains.jet.lang.resolve.name.FqName; 033 import org.jetbrains.jet.plugin.JetFileType; 034 035 import javax.annotation.PostConstruct; 036 import javax.inject.Inject; 037 038 public class JavaClassFinderImpl implements JavaClassFinder { 039 @NotNull 040 private Project project; 041 042 private GlobalSearchScope javaSearchScope; 043 private JavaPsiFacadeKotlinHacks javaFacade; 044 045 @Inject 046 public void setProject(@NotNull Project project) { 047 this.project = project; 048 } 049 050 @PostConstruct 051 public void initialize() { 052 javaSearchScope = new DelegatingGlobalSearchScope(GlobalSearchScope.allScope(project)) { 053 @Override 054 public boolean contains(VirtualFile file) { 055 return myBaseScope.contains(file) && file.getFileType() != JetFileType.INSTANCE; 056 } 057 058 @Override 059 public int compare(VirtualFile file1, VirtualFile file2) { 060 // TODO: this is a hackish workaround for the following problem: 061 // since we are working with the allScope(), if the same class FqName 062 // to be on the class path twice, because it is included into different libraries 063 // (e.g. junit-4.0.jar is used as a separate library and as a part of idea_full) 064 // the two libraries are attached to different modules, the parent compare() 065 // can't tell which one comes first, so they can come in random order 066 // To fix this, we sort additionally by the full path, to make the ordering deterministic 067 // TODO: Delete this hack when proper scopes are used 068 int compare = super.compare(file1, file2); 069 if (compare == 0) { 070 return Comparing.compare(file1.getPath(), file2.getPath()); 071 } 072 return compare; 073 } 074 }; 075 javaFacade = new JavaPsiFacadeKotlinHacks(project); 076 } 077 078 @Nullable 079 @Override 080 public JavaClass findClass(@NotNull FqName fqName) { 081 PsiClass psiClass = javaFacade.findClass(fqName.asString(), javaSearchScope); 082 if (psiClass == null) return null; 083 084 JavaClassImpl javaClass = new JavaClassImpl(psiClass); 085 086 if (!fqName.equals(javaClass.getFqName())) { 087 throw new IllegalStateException("Requested " + fqName + ", got " + javaClass.getFqName()); 088 } 089 090 if (javaClass.getOriginKind() == JavaClass.OriginKind.KOTLIN_LIGHT_CLASS) { 091 throw new IllegalStateException("Kotlin light classes should not be found by JavaPsiFacade, resolving: " + fqName); 092 } 093 094 return javaClass; 095 } 096 097 @Nullable 098 @Override 099 public JavaPackage findPackage(@NotNull FqName fqName) { 100 PsiPackage psiPackage = javaFacade.findPackage(fqName.asString()); 101 return psiPackage == null ? null : new JavaPackageImpl(psiPackage); 102 } 103 }