blob: d291d39cbae3205c7ef22d48f4ae586537b665e1 [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 org.intellij.plugins.intelliLang.inject.groovy;
import com.intellij.lang.injection.MultiHostInjector;
import com.intellij.lang.injection.MultiHostRegistrar;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import org.intellij.plugins.intelliLang.Configuration;
import org.intellij.plugins.intelliLang.inject.InjectorUtils;
import org.intellij.plugins.intelliLang.inject.LanguageInjectionSupport;
import org.intellij.plugins.intelliLang.inject.config.BaseInjection;
import org.intellij.plugins.intelliLang.inject.java.JavaLanguageInjectionSupport;
import org.intellij.plugins.intelliLang.util.AnnotationUtilEx;
import org.intellij.plugins.intelliLang.util.PsiUtilEx;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrAssignmentExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author Max Medvedev
*/
public class GrConcatenationInjector implements MultiHostInjector {
@Override
public void getLanguagesToInject(@NotNull MultiHostRegistrar registrar, @NotNull PsiElement context) {
assert context instanceof GrLiteral;
final GrLiteral literal = (GrLiteral)context;
processInPlace(registrar, literal);
}
public static void processInPlace(MultiHostRegistrar registrar, GrLiteral literal) {
BaseInjection injection = findLanguageParams(literal, Configuration.getInstance());
if (injection != null) {
LanguageInjectionSupport support = InjectorUtils.findInjectionSupport(GroovyLanguageInjectionSupport.GROOVY_SUPPORT_ID);
InjectorUtils.registerInjectionSimple(literal, injection, support, registrar);
}
}
public static BaseInjection findLanguageParams(PsiElement place, Configuration configuration) {
PsiElement parent = place.getParent();
if (parent instanceof GrAssignmentExpression && ((GrAssignmentExpression)parent).getRValue() == place) {
final GrExpression lvalue = ((GrAssignmentExpression)parent).getLValue();
if (lvalue instanceof GrReferenceExpression) {
final PsiElement resolved = ((GrReferenceExpression)lvalue).resolve();
if (resolved instanceof PsiModifierListOwner) {
return getLanguageParams((PsiModifierListOwner)resolved, configuration);
}
}
}
else if (parent instanceof GrVariable) {
return getLanguageParams((PsiModifierListOwner)parent, configuration);
}
else if (parent instanceof GrArgumentList) {
final PsiElement pparent = parent.getParent();
if (pparent instanceof GrCall) {
final GrCall call = (GrCall)pparent;
final GroovyResolveResult result = call.advancedResolve();
if (result.getElement() != null) {
final Map<GrExpression, Pair<PsiParameter, PsiType>> map =
GrClosureSignatureUtil
.mapArgumentsToParameters(result, place, false, false, call.getNamedArguments(), call.getExpressionArguments(), call.getClosureArguments());
if (map != null) {
final Pair<PsiParameter, PsiType> pair = map.get(place);
return getLanguageParams(pair.first, configuration);
}
}
}
}
return null;
}
@Nullable
private static BaseInjection getLanguageParams(PsiModifierListOwner annotationOwner, Configuration configuration) {
final Pair<String, ? extends Set<String>> pair = Configuration.getInstance().getAdvancedConfiguration().getLanguageAnnotationPair();
final PsiAnnotation[] annotations = getAnnotationFrom(annotationOwner, pair, true, true);
if (annotations.length > 0) {
String prefix = StringUtil.notNullize(AnnotationUtilEx.calcAnnotationValue(annotations, "prefix"));
String suffix = StringUtil.notNullize(AnnotationUtilEx.calcAnnotationValue(annotations, "suffix"));
String id = StringUtil.notNullize(AnnotationUtilEx.calcAnnotationValue(annotations, "value"));
if (!StringUtil.isEmpty(id)) {
BaseInjection injection = new BaseInjection(GroovyLanguageInjectionSupport.GROOVY_SUPPORT_ID);
injection.setPrefix(prefix);
injection.setSuffix(suffix);
injection.setInjectedLanguageId(id);
return injection;
}
}
if (annotationOwner instanceof PsiParameter && annotationOwner.getParent() instanceof PsiParameterList &&annotationOwner.getParent().getParent() instanceof PsiMethod) {
List<BaseInjection> injections = configuration.getInjections(JavaLanguageInjectionSupport.JAVA_SUPPORT_ID);
for (BaseInjection injection : injections) {
if (injection.acceptsPsiElement(annotationOwner)) {
return injection;
}
}
}
return null;
}
@NotNull
public static PsiAnnotation[] getAnnotationFrom(PsiModifierListOwner owner,
Pair<String, ? extends Set<String>> annotationName,
boolean allowIndirect,
boolean inHierarchy) {
if (!isLanguageAnnotationTargetGroovy(owner)) return PsiAnnotation.EMPTY_ARRAY;
return AnnotationUtilEx.getAnnotationsFromImpl(owner, annotationName, allowIndirect, inHierarchy);
}
private static boolean isLanguageAnnotationTargetGroovy(PsiModifierListOwner owner) {
return owner instanceof GrMethod && ((GrMethod)owner).getReturnTypeElementGroovy() == null ||
owner instanceof GrVariable && ((GrVariable)owner).getTypeElementGroovy() == null ||
PsiUtilEx.isLanguageAnnotationTarget(owner);
}
@NotNull
@Override
public List<? extends Class<? extends PsiElement>> elementsToInjectIn() {
return Collections.singletonList(GrLiteral.class);
}
}