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 }