/* * Copyright 2013 Guidewire Software, Inc. */ package gw.plugin.ij.lang.psi.impl; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiClassType; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementFactory; import com.intellij.psi.PsiNameHelper; import com.intellij.psi.PsiSubstitutor; import com.intellij.psi.PsiType; import com.intellij.psi.PsiTypeParameter; import com.intellij.psi.search.GlobalSearchScope; import gw.plugin.ij.lang.psi.api.IGosuResolveResult; import gw.plugin.ij.lang.psi.api.expressions.IGosuReferenceExpression; import gw.plugin.ij.util.JavaPsiFacadeUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Arrays; public class GosuClassReferenceType extends PsiClassType { private final IGosuReferenceExpression myReferenceElement; public GosuClassReferenceType(IGosuReferenceExpression referenceElement) { super(LanguageLevel.JDK_1_5); myReferenceElement = referenceElement; } public GosuClassReferenceType(IGosuReferenceExpression referenceElement, LanguageLevel languageLevel) { super(languageLevel); myReferenceElement = referenceElement; } @Nullable public PsiClass resolve() { PsiElement psiElement = myReferenceElement.resolve(); return psiElement instanceof PsiClass ? (PsiClass) psiElement : null; //## todo: use this // ResolveResult[] results = multiResolve(); // if( results.length == 1 ) // { // PsiElement only = results[0].getElement(); // return only instanceof PsiClass ? (PsiClass)only : null; // } // // return null; } //reference resolve is cached @NotNull private IGosuResolveResult[] multiResolve() { return (IGosuResolveResult[]) myReferenceElement.multiResolve(false); } @Nullable public String getClassName() { return myReferenceElement.getReferenceName(); } @NotNull public PsiType[] getParameters() { return myReferenceElement.getTypeArguments(); } @NotNull public ClassResolveResult resolveGenerics() { return new ClassResolveResult() { public PsiClass getElement() { return resolve(); } public PsiSubstitutor getSubstitutor() { final IGosuResolveResult[] results = multiResolve(); if (results.length != 1) { return PsiSubstitutor.UNKNOWN; } return results[0].getSubstitutor().putAll( (PsiClass) results[0].getElement(), GosuClassReferenceType.this.getParameters()); } public boolean isPackagePrefixPackageReference() { return false; } public boolean isAccessible() { final IGosuResolveResult[] results = multiResolve(); for (IGosuResolveResult result : results) { if (result.isAccessible()) { return true; } } return false; } public boolean isStaticsScopeCorrect() { return true; //TODO } @Nullable public PsiElement getCurrentFileResolveScope() { return null; //TODO??? } public boolean isValidResult() { return isStaticsScopeCorrect() && isAccessible(); } }; } @NotNull public PsiClassType rawType() { final PsiClass clazz = resolve(); if (clazz != null) { final PsiElementFactory factory = JavaPsiFacadeUtil.getElementFactory(clazz.getProject()); return factory.createType(clazz, factory.createRawSubstitutor(clazz)); } return this; } public String getPresentableText() { if( Arrays.asList( myReferenceElement.getTypeArguments() ).contains( null ) ) { return myReferenceElement.getReferenceName(); } return PsiNameHelper.getPresentableText(myReferenceElement.getReferenceName(), myReferenceElement.getTypeArguments()); } @Nullable public String getCanonicalText() { PsiClass resolved = resolve(); if (resolved == null) { return null; } if (resolved instanceof PsiTypeParameter) { return resolved.getName(); } final String qName = resolved.getQualifiedName(); if (isRaw()) { return qName; } final PsiType[] typeArgs = myReferenceElement.getTypeArguments(); if (typeArgs.length == 0) { return qName; } StringBuilder builder = new StringBuilder(); builder.append(qName).append("<"); for (int i = 0; i < typeArgs.length; i++) { if (i > 0) { builder.append(", "); } final String typeArgCanonical = typeArgs[i].getCanonicalText(); if (typeArgCanonical != null) { builder.append(typeArgCanonical); } else { return null; } } builder.append(">"); return builder.toString(); } @Nullable public String getInternalCanonicalText() { return getCanonicalText(); } public boolean isValid() { return myReferenceElement.isValid(); } public boolean equalsToText(@NotNull @NonNls String text) { return text.endsWith(getPresentableText()) && //optimization text.equals(getCanonicalText()); } @NotNull public GlobalSearchScope getResolveScope() { return myReferenceElement.getResolveScope(); } @NotNull public LanguageLevel getLanguageLevel() { return myLanguageLevel; } @NotNull public PsiClassType setLanguageLevel(final LanguageLevel languageLevel) { return new GosuClassReferenceType(myReferenceElement, languageLevel); } }