From 0a240adbb9fc7d445622a64377e3da26d1622cb4 Mon Sep 17 00:00:00 2001 From: greg Date: Mon, 13 Oct 2008 17:00:16 +0400 Subject: [PATCH] intelliLang injector redesign p1 --- .../intelliLang/inject/CustomLanguageInjector.java | 77 +++++++++++++++------- .../inject/CustomLanguageInjectorExtension.java | 4 +- .../intelliLang/inject/InjectLanguageAction.java | 16 +++-- .../inject/config/MethodParameterInjection.java | 10 ++- 4 files changed, 70 insertions(+), 37 deletions(-) diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/CustomLanguageInjector.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/CustomLanguageInjector.java index 5a1e4de520..05585f564c 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/CustomLanguageInjector.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/CustomLanguageInjector.java @@ -22,21 +22,24 @@ import com.intellij.lang.injection.MultiHostInjector; import com.intellij.lang.injection.MultiHostRegistrar; import com.intellij.openapi.components.ProjectComponent; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.*; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.extensions.Extensions; import com.intellij.psi.*; import com.intellij.psi.filters.TrueFilter; import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry; import com.intellij.psi.search.LocalSearchScope; import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.tree.IElementType; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.PsiUtil; import com.intellij.psi.xml.*; import com.intellij.util.NullableFunction; import com.intellij.util.PairProcessor; import com.intellij.util.containers.ContainerUtil; import com.intellij.xml.util.XmlUtil; +import gnu.trove.THashSet; import org.intellij.plugins.intelliLang.Configuration; import org.intellij.plugins.intelliLang.inject.config.MethodParameterInjection; import org.intellij.plugins.intelliLang.inject.config.XmlAttributeInjection; @@ -89,8 +92,7 @@ public final class CustomLanguageInjector implements ProjectComponent { private void getInjectedLanguage(final PsiElement place, final PairProcessor>> processor) { // optimization - if (place instanceof PsiLiteralExpression && !isStringLiteral(place) || - place instanceof PsiReferenceExpression && !myInjectionConfiguration.isResolveReferences()) return; + if (place instanceof PsiLiteralExpression && !isStringLiteral(place)) return; synchronized (myTempPlaces) { for (Iterator, InjectedLanguage>> it = myTempPlaces.iterator(); it.hasNext();) { @@ -266,12 +268,45 @@ public final class CustomLanguageInjector implements ProjectComponent { } private void processLiteralExpressionInjections(final PsiExpression place, final PairProcessor>> processor) { - if (!processAnnotationInjections(place, processor)) { - final Pair, PsiMethod> info = MethodParameterInjection.getParameterInfo(place); - final Collection injections = info == null? null : getMethodCache().get(info.first); + final PsiElement topBlock = PsiUtil.getTopLevelEnclosingCodeBlock(place, null); + final LocalSearchScope searchScope = new LocalSearchScope(new PsiElement[]{topBlock instanceof PsiCodeBlock? topBlock : place.getContainingFile()}, "", true); + final LinkedList places = new LinkedList(); + places.add(place); + while (!places.isEmpty()) { + final PsiExpression curPlace = places.removeFirst(); + final PsiModifierListOwner owner = AnnotationUtilEx.getAnnotatedElementFor(curPlace, AnnotationUtilEx.LookupType.PREFER_CONTEXT); + if (owner == null) continue; + if (processAnnotationInjections(place, owner, processor)) return; // annotated element + + final PsiMethod psiMethod; + final Trinity trin; + if (owner instanceof PsiParameter) { + psiMethod = PsiTreeUtil.getParentOfType(owner, PsiMethod.class, false); + if (psiMethod == null) continue; + trin = Trinity.create(psiMethod.getName(), psiMethod.getParameterList().getParametersCount(), + psiMethod.getParameterList().getParameterIndex((PsiParameter)owner)); + } + else if (owner instanceof PsiMethod) { + psiMethod = (PsiMethod)owner; + trin = Trinity.create(psiMethod.getName(), psiMethod.getParameterList().getParametersCount(), -1); + } + else if (owner instanceof PsiVariable) { + final PsiVariable variable = (PsiVariable)owner; + for (PsiReference psiReference : ReferencesSearch.search(variable, searchScope).findAll()) { + final PsiElement element = psiReference.getElement(); + if (element instanceof PsiExpression) { + places.add((PsiExpression)element); + } + } + continue; + } + else { + continue; + } + final Collection injections = getMethodCache().get(trin); if (injections == null) return; for (MethodParameterInjection injection : injections) { - if (injection.isApplicable(info.second)) { + if (injection.isApplicable(psiMethod)) { processInjection(place, injection.getInjectedLanguageId(), injection.getPrefix(), injection.getSuffix(), processor); return; } @@ -302,19 +337,15 @@ public final class CustomLanguageInjector implements ProjectComponent { return tmpMap; } - private boolean processAnnotationInjections(final PsiExpression psiExpression, final PairProcessor>> processor) { - final PsiModifierListOwner element = - AnnotationUtilEx.getAnnotatedElementFor(psiExpression, AnnotationUtilEx.LookupType.PREFER_CONTEXT); - if (element != null) { - final PsiAnnotation[] annotations = - AnnotationUtilEx.getAnnotationFrom(element, myInjectionConfiguration.getLanguageAnnotationPair(), true); - if (annotations.length > 0) { - final String id = AnnotationUtilEx.calcAnnotationValue(annotations, "value"); - final String prefix = AnnotationUtilEx.calcAnnotationValue(annotations, "prefix"); - final String suffix = AnnotationUtilEx.calcAnnotationValue(annotations, "suffix"); - processInjection(psiExpression, id, prefix, suffix, processor); - return true; - } + private boolean processAnnotationInjections(final PsiExpression psiExpression, final PsiModifierListOwner annoElement, final PairProcessor>> processor) { + final PsiAnnotation[] annotations = + AnnotationUtilEx.getAnnotationFrom(annoElement, myInjectionConfiguration.getLanguageAnnotationPair(), true); + if (annotations.length > 0) { + final String id = AnnotationUtilEx.calcAnnotationValue(annotations, "value"); + final String prefix = AnnotationUtilEx.calcAnnotationValue(annotations, "prefix"); + final String suffix = AnnotationUtilEx.calcAnnotationValue(annotations, "suffix"); + processInjection(psiExpression, id, prefix, suffix, processor); + return true; } return false; } @@ -414,12 +445,12 @@ public final class CustomLanguageInjector implements ProjectComponent { @NotNull public List> elementsToInjectIn() { - final ArrayList> elements = new ArrayList>(); + final THashSet> elements = new THashSet>(); for (CustomLanguageInjectorExtension o : Extensions.getExtensions(CustomLanguageInjectorExtension.EP_NAME)) { o.elementsToInjectIn(elements); } - elements.addAll(Arrays.asList(XmlTag.class, PsiLiteralExpression.class, XmlAttributeValue.class, PsiReferenceExpression.class)); - return elements; + elements.addAll(Arrays.asList(PsiLiteralExpression.class, XmlTag.class, XmlAttributeValue.class)); + return Arrays.>asList(elements.toArray(new Class[elements.size()])); } public void getLanguagesToInject(@NotNull final MultiHostRegistrar registrar, @NotNull PsiElement host) { diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/CustomLanguageInjectorExtension.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/CustomLanguageInjectorExtension.java index 09b59ff838..c40b7c6c68 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/CustomLanguageInjectorExtension.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/CustomLanguageInjectorExtension.java @@ -9,8 +9,8 @@ import com.intellij.psi.PsiLanguageInjectionHost; import com.intellij.util.PairProcessor; import org.intellij.plugins.intelliLang.Configuration; +import java.util.Collection; import java.util.List; -import java.util.ArrayList; /** * @author Gregory.Shrago @@ -20,5 +20,5 @@ public interface CustomLanguageInjectorExtension { void getInjectedLanguage(final Configuration configuration, final PsiElement place, final PairProcessor>> processor); - void elementsToInjectIn(final ArrayList> result); + void elementsToInjectIn(final Collection> result); } diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java index fb79f7f8eb..772f65b1eb 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java @@ -141,7 +141,7 @@ public class InjectLanguageAction implements IntentionAction { if (parent instanceof PsiConditionalExpression && ((PsiConditionalExpression)parent).getCondition() != target) continue; break; } - if (parent instanceof PsiReturnStatement) { + if (parent instanceof PsiReturnStatement || parent instanceof PsiMethod) { return doInjectInJavaMethod(project, findPsiMethod(parent), -1, languageId); } else if (parent instanceof PsiExpressionList && parent.getParent() instanceof PsiMethodCallExpression) { @@ -185,13 +185,17 @@ public class InjectLanguageAction implements IntentionAction { final String languageId) { if (psiMethod == null) return false; if (parameterIndex < -1) return false; - final PsiModifierList modifiers = psiMethod.getModifierList(); - if (modifiers.hasModifierProperty(PsiModifier.PRIVATE) || modifiers.hasModifierProperty(PsiModifier.PACKAGE_LOCAL)) { - return doAddLanguageAnnotation(project, parameterIndex >0? psiMethod.getParameterList().getParameters()[parameterIndex - 1] : psiMethod, - languageId); + final PsiModifierList methodModifiers = psiMethod.getModifierList(); + if (methodModifiers.hasModifierProperty(PsiModifier.PRIVATE) || methodModifiers.hasModifierProperty(PsiModifier.PACKAGE_LOCAL)) { + return doAddLanguageAnnotation(project, parameterIndex >0? psiMethod.getParameterList().getParameters()[parameterIndex - 1] : psiMethod, languageId); } final PsiClass containingClass = psiMethod.getContainingClass(); assert containingClass != null; + final PsiModifierList classModifiers = containingClass.getModifierList(); + if (classModifiers != null && (classModifiers.hasModifierProperty(PsiModifier.PRIVATE) || classModifiers.hasModifierProperty(PsiModifier.PACKAGE_LOCAL))) { + return doAddLanguageAnnotation(project, parameterIndex >0? psiMethod.getParameterList().getParameters()[parameterIndex - 1] : psiMethod, languageId); + } + final String className = containingClass.getQualifiedName(); assert className != null; final MethodParameterInjection injection = new MethodParameterInjection(); @@ -218,7 +222,7 @@ public class InjectLanguageAction implements IntentionAction { first = ((PsiMethodCallExpression)parent.getParent()).resolveMethod(); } else { - first = PsiTreeUtil.getParentOfType(parent, PsiMethod.class, true); + first = PsiTreeUtil.getParentOfType(parent, PsiMethod.class, false); } if (first == null || first.getContainingClass() == null) return null; final LinkedList methods = new LinkedList(); diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/MethodParameterInjection.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/MethodParameterInjection.java index 9754151be2..29e57a2e08 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/MethodParameterInjection.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/MethodParameterInjection.java @@ -47,15 +47,13 @@ public class MethodParameterInjection extends BaseInjection