package de.espend.idea.android.annotator; import com.intellij.lang.annotation.Annotation; import com.intellij.lang.annotation.AnnotationHolder; import com.intellij.lang.annotation.Annotator; import com.intellij.psi.*; import com.intellij.psi.impl.source.PsiClassReferenceType; import com.intellij.psi.impl.source.tree.java.PsiIdentifierImpl; import com.intellij.psi.util.PsiTreeUtil; import de.espend.idea.android.action.write.InflateLocalVariableAction; import de.espend.idea.android.action.write.InflateThisExpressionAction; import de.espend.idea.android.utils.AndroidUtils; import de.espend.idea.android.utils.JavaPsiUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public class InflateViewAnnotator implements Annotator { @Override public void annotate(@NotNull PsiElement psiElement, @NotNull AnnotationHolder annotationHolder) { InflateContainer inflateContainer = matchInflate(psiElement); if(inflateContainer == null) { return; } Annotation inflateLocal = annotationHolder.createWeakWarningAnnotation(psiElement, null); inflateLocal.setHighlightType(null); inflateLocal.registerFix(new InflateLocalVariableAction(inflateContainer.getPsiLocalVariable(), inflateContainer.getXmlFile())); Annotation inflateThis = annotationHolder.createWeakWarningAnnotation(psiElement, null); inflateThis.setHighlightType(null); inflateThis.registerFix(new InflateThisExpressionAction(inflateContainer.getPsiLocalVariable(), inflateContainer.getXmlFile())); } @Nullable public static InflateContainer matchInflate(@Nullable PsiElement psiElement) { if(!(psiElement instanceof PsiIdentifierImpl)) { return null; } // View "rootView" = inflater.inflate(R.layout.fragment_main, container, false); PsiElement psiLocalVariable = psiElement.getParent(); if(psiLocalVariable instanceof PsiLocalVariable) { return matchInflate((PsiLocalVariable) psiLocalVariable); } return null; } @Nullable public static InflateContainer matchInflate(PsiLocalVariable psiLocalVariable) { PsiType psiType = psiLocalVariable.getType(); if(psiType instanceof PsiClassReferenceType) { PsiMethodCallExpression psiMethodCallExpression = PsiTreeUtil.findChildOfType(psiLocalVariable, PsiMethodCallExpression.class); if(psiMethodCallExpression != null) { PsiMethod psiMethod = psiMethodCallExpression.resolveMethod(); // @TODO: replace "inflate"; resolve method and check nethod calls if(psiMethod != null && psiMethod.getName().equals("inflate")) { PsiExpression[] expressions = psiMethodCallExpression.getArgumentList().getExpressions(); if(expressions.length > 0 && expressions[0] instanceof PsiReferenceExpression) { PsiFile xmlFile = AndroidUtils.findXmlResource((PsiReferenceExpression) expressions[0]); if(xmlFile != null) { return new InflateContainer(xmlFile, ((PsiLocalVariable) psiLocalVariable)); } } } } } return null; } public static class InflateContainer { final private PsiFile xmlFile; final private PsiLocalVariable psiLocalVariable; public InflateContainer(PsiFile xmlFile, PsiLocalVariable psiLocalVariable) { this.xmlFile = xmlFile; this.psiLocalVariable = psiLocalVariable; } public PsiLocalVariable getPsiLocalVariable() { return psiLocalVariable; } public PsiFile getXmlFile() { return xmlFile; } } }