UastReferenceRegistrar: added a handy method uastLiteralHostReferenceProvider

This commit is contained in:
Nicolay Mitropolsky
2017-12-25 13:12:00 +03:00
parent 302ff1ce26
commit 1d164dc80a
2 changed files with 62 additions and 63 deletions
@@ -57,7 +57,6 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.devkit.DevKitBundle;
import org.jetbrains.idea.devkit.util.PsiUtil;
import org.jetbrains.uast.UElement;
import org.jetbrains.uast.ULiteralExpression;
import org.jetbrains.uast.UastContextKt;
import org.jetbrains.uast.UastLiteralUtils;
@@ -261,79 +260,68 @@ public class IconsReferencesContributor extends PsiReferenceContributor
registrar,
UastPatterns.literalExpression()
.filter(UastLiteralUtils::isStringLiteral)
.sourcePsiFilter(psi -> PsiUtil.isPluginProject(psi.getProject()))
.annotationParam(Presentation.class.getName(), "icon"),
new UastReferenceProvider() {
@NotNull
@Override
public PsiReference[] getReferencesByElement(@NotNull final UElement uElement, @NotNull ProcessingContext context) {
final PsiElement psi = uElement.getPsi();
if (psi == null || !PsiUtil.isPluginProject(psi.getProject())) return PsiReference.EMPTY_ARRAY;
UastReferenceRegistrar.uastLiteralReferenceProvider((uElement, referencePsiElement) -> new PsiReference[]{
new IconPsiReferenceBase(referencePsiElement) {
PsiElement referencePsiElement = UastLiteralUtils.getPsiLanguageInjectionHost((ULiteralExpression)uElement);
if (referencePsiElement == null) return PsiReference.EMPTY_ARRAY;
private UElement getUElement() {
return UastContextKt.toUElement(getElement());
}
return new PsiReference[]{
new IconPsiReferenceBase(referencePsiElement) {
@Override
public PsiElement resolve() {
final UElement uElement = getUElement();
if (uElement == null) return null;
private UElement getUElement() {
return UastContextKt.toUElement(getElement());
String value = UastLiteralUtils.getValueIfStringLiteral(uElement);
return resolveIconPath(value, getElement());
}
@Override
public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException {
PsiElement field = resolve();
PsiElement result = handleElement(field, newElementName);
if (result != null) {
return result;
}
return super.handleElementRename(newElementName);
}
@Override
public PsiElement resolve() {
final UElement uElement = getUElement();
if (uElement == null) return null;
String value = UastLiteralUtils.getValueIfStringLiteral(uElement);
return resolveIconPath(value, getElement());
}
@Override
public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException {
PsiElement field = resolve();
PsiElement result = handleElement(field, newElementName);
if (result != null) {
return result;
}
return super.handleElementRename(newElementName);
}
@Nullable
private PsiElement handleElement(PsiElement element, @Nullable String newElementName) {
if (element instanceof PsiField) {
PsiClass containingClass = ((PsiField)element).getContainingClass();
if (containingClass != null) {
String classQualifiedName = containingClass.getQualifiedName();
if (classQualifiedName != null) {
if (newElementName == null) {
newElementName = ((PsiField)element).getName();
}
if (classQualifiedName.startsWith("com.intellij.icons.")) {
return replace(newElementName, classQualifiedName, "com.intellij.icons.");
}
if (classQualifiedName.startsWith("icons.")) {
return replace(newElementName, classQualifiedName, "icons.");
}
@Nullable
private PsiElement handleElement(PsiElement element, @Nullable String newElementName) {
if (element instanceof PsiField) {
PsiClass containingClass = ((PsiField)element).getContainingClass();
if (containingClass != null) {
String classQualifiedName = containingClass.getQualifiedName();
if (classQualifiedName != null) {
if (newElementName == null) {
newElementName = ((PsiField)element).getName();
}
if (classQualifiedName.startsWith("com.intellij.icons.")) {
return replace(newElementName, classQualifiedName, "com.intellij.icons.");
}
if (classQualifiedName.startsWith("icons.")) {
return replace(newElementName, classQualifiedName, "icons.");
}
}
}
return null;
}
private PsiElement replace(String newElementName, String fqn, String packageName) {
String newValue = fqn.substring(packageName.length()) + "." + newElementName;
return ElementManipulators.getManipulator(getElement()).handleContentChange(getElement(), newValue);
}
@NotNull
@Override
public Object[] getVariants() {
return EMPTY_ARRAY;
}
return null;
}
};
}
}, PsiReferenceRegistrar.HIGHER_PRIORITY);
private PsiElement replace(String newElementName, String fqn, String packageName) {
String newValue = fqn.substring(packageName.length()) + "." + newElementName;
return ElementManipulators.getManipulator(getElement()).handleContentChange(getElement(), newValue);
}
@NotNull
@Override
public Object[] getVariants() {
return EMPTY_ARRAY;
}
}
}), PsiReferenceRegistrar.HIGHER_PRIORITY);
}
@@ -23,6 +23,8 @@ import com.intellij.patterns.ElementPatternCondition
import com.intellij.patterns.InitialPatternCondition
import com.intellij.util.ProcessingContext
import org.jetbrains.uast.UElement
import org.jetbrains.uast.ULiteralExpression
import org.jetbrains.uast.psiLanguageInjectionHost
import org.jetbrains.uast.toUElement
fun PsiReferenceRegistrar.registerUastReferenceProvider(pattern: (UElement, ProcessingContext) -> Boolean,
@@ -43,6 +45,15 @@ abstract class UastReferenceProvider {
}
fun uastLiteralReferenceProvider(provider: (ULiteralExpression, PsiLanguageInjectionHost) -> Array<PsiReference>) =
object : UastReferenceProvider() {
override fun getReferencesByElement(element: UElement, context: ProcessingContext): Array<PsiReference> {
val uLiteral = element as? ULiteralExpression ?: return PsiReference.EMPTY_ARRAY
val host = uLiteral.psiLanguageInjectionHost ?: return PsiReference.EMPTY_ARRAY
return provider(uLiteral, host)
}
}
private val cachedUElement = Key.create<UElement>("UastReferenceRegistrar.cachedUElement")
private fun getOrCreateCachedElement(element: PsiElement, context: ProcessingContext?): UElement? =