001    /*
002     * Copyright 2010-2016 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.asJava.classes;
018    
019    import com.intellij.lang.Language;
020    import com.intellij.psi.PsiClass;
021    import com.intellij.psi.PsiElement;
022    import com.intellij.psi.PsiFile;
023    import com.intellij.psi.impl.light.AbstractLightClass;
024    import org.jetbrains.annotations.NotNull;
025    import org.jetbrains.annotations.Nullable;
026    import org.jetbrains.kotlin.asJava.finder.JavaElementFinder;
027    import org.jetbrains.kotlin.idea.KotlinLanguage;
028    import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind;
029    import org.jetbrains.kotlin.psi.KtClassOrObject;
030    import org.jetbrains.kotlin.psi.KtFile;
031    
032    /**
033     * This class serves as a workaround for usages of {@link JavaElementFinder#findClasses} which eventually only need names of files
034     * containing the class. When queried for a package class (e.g. test/TestPackage), {@code findClasses} along with a
035     * {@link KtLightClassForFacade} would also return multiple instances of this class for each file present in the package. The client
036     * code can make use of every file in the package then, since {@code getContainingFile} of these instances will represent the whole package.
037     * <p/>
038     * See {@link LineBreakpoint#findClassCandidatesInSourceContent} for the primary usage this was introduced
039     */
040    public class FakeLightClassForFileOfPackage extends AbstractLightClass implements KtLightClass {
041        private final KtLightClassForFacade delegate;
042        private final KtFile file;
043    
044        public FakeLightClassForFileOfPackage(@NotNull KtLightClassForFacade delegate, @NotNull KtFile file) {
045            super(delegate.getManager());
046            this.delegate = delegate;
047            this.file = file;
048        }
049    
050        @NotNull
051        @Override
052        public PsiClass getClsDelegate() {
053            return delegate;
054        }
055    
056        @Nullable
057        @Override
058        public KtClassOrObject getKotlinOrigin() {
059            return null;
060        }
061    
062        @Override
063        public PsiFile getContainingFile() {
064            return file;
065        }
066    
067        @Override
068        public boolean isValid() {
069            // This is intentionally false to prevent using this as a real class
070            return false;
071        }
072    
073        @NotNull
074        @Override
075        public PsiClass getDelegate() {
076            return delegate;
077        }
078    
079        @NotNull
080        @Override
081        public PsiElement copy() {
082            return new FakeLightClassForFileOfPackage(delegate, file);
083        }
084    
085        @Override
086        public String getText() {
087            return null;
088        }
089    
090        @NotNull
091        @Override
092        public Language getLanguage() {
093            return KotlinLanguage.INSTANCE;
094        }
095    
096        @Override
097        public boolean equals(Object obj) {
098            if (!(obj instanceof FakeLightClassForFileOfPackage)) return false;
099    
100            FakeLightClassForFileOfPackage other = (FakeLightClassForFileOfPackage) obj;
101            return file == other.file && delegate.equals(other.delegate);
102        }
103    
104        @Override
105        public int hashCode() {
106            return file.hashCode() * 31 + delegate.hashCode();
107        }
108    
109        @NotNull
110        @Override
111        public LightClassOriginKind getOriginKind() {
112            return LightClassOriginKind.SOURCE;
113        }
114    }