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.jetAsJava.JetJavaMirrorMarker;
029 import org.jetbrains.jet.lang.resolve.name.FqName;
030 import org.jetbrains.jet.plugin.JetFileType;
031
032 import javax.annotation.PostConstruct;
033 import javax.inject.Inject;
034
035 public class PsiClassFinderImpl implements PsiClassFinder {
036 @NotNull
037 private Project project;
038
039 private GlobalSearchScope javaSearchScope;
040 private JavaPsiFacadeKotlinHacks javaFacade;
041
042 @Inject
043 public void setProject(@NotNull Project project) {
044 this.project = project;
045 }
046
047 @PostConstruct
048 public void initialize() {
049 javaSearchScope = new DelegatingGlobalSearchScope(GlobalSearchScope.allScope(project)) {
050 @Override
051 public boolean contains(VirtualFile file) {
052 return myBaseScope.contains(file) && file.getFileType() != JetFileType.INSTANCE;
053 }
054
055 @Override
056 public int compare(VirtualFile file1, VirtualFile file2) {
057 // TODO: this is a hackish workaround for the following problem:
058 // since we are working with the allScope(), if the same class FqName
059 // to be on the class path twice, because it is included into different libraries
060 // (e.g. junit-4.0.jar is used as a separate library and as a part of idea_full)
061 // the two libraries are attached to different modules, the parent compare()
062 // can't tell which one comes first, so they can come in random order
063 // To fix this, we sort additionally by the full path, to make the ordering deterministic
064 // TODO: Delete this hack when proper scopes are used
065 int compare = super.compare(file1, file2);
066 if (compare == 0) {
067 return Comparing.compare(file1.getPath(), file2.getPath());
068 }
069 return compare;
070 }
071 };
072 javaFacade = new JavaPsiFacadeKotlinHacks(project);
073 }
074
075 @Override
076 @Nullable
077 public PsiClass findPsiClass(@NotNull FqName qualifiedName) {
078 PsiClass original = javaFacade.findClass(qualifiedName.asString(), javaSearchScope);
079
080 if (original != null) {
081 String classQualifiedName = original.getQualifiedName();
082 FqName actualQualifiedName = classQualifiedName != null ? new FqName(classQualifiedName) : null;
083 if (!qualifiedName.equals(actualQualifiedName)) {
084 throw new IllegalStateException("requested " + qualifiedName + ", got " + actualQualifiedName);
085 }
086 }
087
088 if (original instanceof JetJavaMirrorMarker) {
089 throw new IllegalStateException("JetJavaMirrorMaker is not possible in resolve.java, resolving: " + qualifiedName);
090 }
091
092 return original;
093 }
094
095 @Override
096 @Nullable
097 public PsiPackage findPsiPackage(@NotNull FqName qualifiedName) {
098 return javaFacade.findPackage(qualifiedName.asString());
099 }
100 }