blob: 3508873df641d706d6a8260e091e1c792be297db [file] [log] [blame]
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi.impl.source;
import com.intellij.openapi.util.Comparing;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.impl.light.LightClassReference;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.SmartList;
import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* @author max
*/
public class PsiClassReferenceType extends PsiClassType.Stub {
@NotNull
private final PsiJavaCodeReferenceElement myReference;
public PsiClassReferenceType(@NotNull PsiJavaCodeReferenceElement reference, LanguageLevel level) {
this(reference, level, collectAnnotations(reference));
}
public PsiClassReferenceType(@NotNull PsiJavaCodeReferenceElement reference, LanguageLevel level, @NotNull PsiAnnotation[] annotations) {
super(level, annotations);
myReference = reference;
}
private static PsiAnnotation[] collectAnnotations(PsiJavaCodeReferenceElement reference) {
List<PsiAnnotation> result = null;
for (PsiElement child = reference.getFirstChild(); child != null; child = child.getNextSibling()) {
if (child instanceof PsiAnnotation) {
if (result == null) result = new SmartList<PsiAnnotation>();
result.add((PsiAnnotation)child);
}
}
return result == null ? PsiAnnotation.EMPTY_ARRAY : result.toArray(new PsiAnnotation[result.size()]);
}
@Override
public boolean isValid() {
return myReference.isValid();
}
@Override
public boolean equalsToText(@NotNull String text) {
return Comparing.equal(text, getCanonicalText());
}
@Override
@NotNull
public GlobalSearchScope getResolveScope() {
return myReference.getResolveScope();
}
@Override
@NotNull
public LanguageLevel getLanguageLevel() {
if (myLanguageLevel != null) return myLanguageLevel;
return PsiUtil.getLanguageLevel(myReference);
}
@NotNull
@Override
public PsiClassType setLanguageLevel(@NotNull final LanguageLevel languageLevel) {
if (languageLevel.equals(myLanguageLevel)) return this;
return new PsiClassReferenceType(myReference, languageLevel, getAnnotations());
}
@Override
public PsiClass resolve() {
return resolveGenerics().getElement();
}
private static class DelegatingClassResolveResult implements PsiClassType.ClassResolveResult {
private final JavaResolveResult myDelegate;
private DelegatingClassResolveResult(@NotNull JavaResolveResult delegate) {
myDelegate = delegate;
}
@NotNull
@Override
public PsiSubstitutor getSubstitutor() {
return myDelegate.getSubstitutor();
}
@Override
public boolean isValidResult() {
return myDelegate.isValidResult();
}
@Override
public boolean isAccessible() {
return myDelegate.isAccessible();
}
@Override
public boolean isStaticsScopeCorrect() {
return myDelegate.isStaticsScopeCorrect();
}
@Override
public PsiElement getCurrentFileResolveScope() {
return myDelegate.getCurrentFileResolveScope();
}
@Override
public boolean isPackagePrefixPackageReference() {
return myDelegate.isPackagePrefixPackageReference();
}
@Override
public PsiClass getElement() {
final PsiElement element = myDelegate.getElement();
return element instanceof PsiClass ? (PsiClass)element : null;
}
}
@Override
@NotNull
public ClassResolveResult resolveGenerics() {
PsiUtilCore.ensureValid(myReference);
final JavaResolveResult result = myReference.advancedResolve(false);
return result.getElement() == null ? ClassResolveResult.EMPTY : new DelegatingClassResolveResult(result);
}
@Override
@NotNull
public PsiClassType rawType() {
PsiElement resolved = myReference.resolve();
if (resolved instanceof PsiClass) {
PsiClass aClass = (PsiClass)resolved;
if (!PsiUtil.typeParametersIterable(aClass).iterator().hasNext()) return this;
PsiManager manager = myReference.getManager();
final PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
final PsiSubstitutor rawSubstitutor = factory.createRawSubstitutor(aClass);
return factory.createType(aClass, rawSubstitutor, getLanguageLevel(), getAnnotations());
}
String qualifiedName = myReference.getQualifiedName();
String name = myReference.getReferenceName();
if (name == null) name = "";
LightClassReference reference = new LightClassReference(myReference.getManager(), name, qualifiedName, myReference.getResolveScope());
return new PsiClassReferenceType(reference, null, getAnnotations());
}
@Override
public String getClassName() {
return myReference.getReferenceName();
}
@Override
@NotNull
public PsiType[] getParameters() {
return myReference.getTypeParameters();
}
@NotNull
public PsiClassType createImmediateCopy() {
ClassResolveResult resolveResult = resolveGenerics();
PsiClass element = resolveResult.getElement();
return element == null ? this : new PsiImmediateClassType(element, resolveResult.getSubstitutor());
}
@NotNull
@Override
public String getPresentableText() {
String presentableText = PsiNameHelper.getPresentableText(myReference);
PsiAnnotation[] annotations = getAnnotations();
if (annotations.length == 0) return presentableText;
StringBuilder sb = new StringBuilder();
PsiNameHelper.appendAnnotations(sb, annotations, false);
sb.append(presentableText);
return sb.toString();
}
@NotNull
@Override
public String getCanonicalText(boolean annotated) {
return getText(annotated);
}
@NotNull
@Override
public String getInternalCanonicalText() {
return getText(true);
}
private String getText(boolean annotated) {
if (myReference instanceof PsiJavaCodeReferenceElementImpl) {
PsiAnnotation[] annotations = getAnnotations();
if (!annotated || annotations.length == 0) annotations = null;
PsiJavaCodeReferenceElementImpl impl = (PsiJavaCodeReferenceElementImpl)myReference;
return impl.getCanonicalText(annotated, annotations, impl.getContainingFile());
}
return myReference.getCanonicalText();
}
@NotNull
public PsiJavaCodeReferenceElement getReference() {
return myReference;
}
}