下面列出了com.intellij.psi.templateLanguages.OuterLanguageElement#com.intellij.lang.injection.MultiHostRegistrar 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
@Override
public void getLanguagesToInject(@NotNull MultiHostRegistrar registrar, @NotNull PsiElement context) {
if (context.getLanguage() == XMLLanguage.INSTANCE) return;
final Project project = context.getProject();
if (!FluidIndexUtil.hasFluid(project)) return;
final PsiElement parent = context.getParent();
if (context instanceof XmlAttributeValueImpl && parent instanceof XmlAttribute) {
final int length = context.getTextLength();
final String name = ((XmlAttribute) parent).getName();
if (isInjectableAttribute(project, length, name)) {
registrar
.startInjecting(FluidLanguage.INSTANCE)
.addPlace(null, null, (PsiLanguageInjectionHost) context, ElementManipulators.getValueTextRange(context))
.doneInjecting();
}
}
}
@Override
public void getLanguagesToInject(@NotNull MultiHostRegistrar registrar, @NotNull PsiElement psiElement) {
String productCode = INSTANCE.getBuild().getProductCode();
if (NutzCons.IDEA_VERSION.equals(productCode)) {
final Language SQL_LANGUAGE = Language.findLanguageByID("SQL");
if (DomUtil.isNutzSqlFile(psiElement.getContainingFile())) {
if (psiElement instanceof XmlTag) {
XmlTag tag = (XmlTag) psiElement;
if (SQL_TAG.equals(tag.getName())) {
registrarInjecting(SQL_LANGUAGE, registrar, DomUtil.findXmlTexts(psiElement.getChildren()), null, null);
}
// else if (EXP_TAG.equals(tag.getName())) {
// registrarInjecting(XMLLanguage.INSTANCE, registrar, DomUtil.findXmlTexts(psiElement.getChildren()), "<!--", "-->");
// }
}
}
}
}
@Override
public void getLanguagesToInject(@NotNull MultiHostRegistrar registrar, @NotNull PsiElement psiElement) {
String productCode = INSTANCE.getBuild().getProductCode();
if (NutzCons.IDEA_VERSION.equals(productCode)) {
//旗舰版才支持该功能
final Language SQL_LANGUAGE = Language.findLanguageByID("SQL");
if (psiElement.getParent() != null && psiElement.getParent().getParent() != null) {
PsiElement parent = psiElement.getParent().getParent().getParent();
if (parent != null && parent instanceof PsiAnnotation) {
String qualifiedName = ((PsiAnnotation) parent).getQualifiedName();
if (NutzCons.SQLS.contains(qualifiedName)) {
registrar.startInjecting(SQL_LANGUAGE);
registrar.addPlace(null, null, (PsiLanguageInjectionHost) psiElement, ElementManipulators.getValueTextRange(psiElement));
registrar.doneInjecting();
}
}
}
}
}
@Nonnull
@Override
public MultiHostRegistrar startInjecting(@Nonnull LanguageVersion languageVersion, @Nullable String extension) {
fileExtension = extension;
placeInfos = new SmartList<>();
if (!cleared) {
clear();
throw new IllegalStateException("Seems you haven't called doneInjecting()");
}
currentThread = Thread.currentThread();
if (LanguageParserDefinitions.INSTANCE.forLanguage(languageVersion.getLanguage()) == null) {
throw new UnsupportedOperationException("Cannot inject language '" + languageVersion.getLanguage() + "' because it has no ParserDefinition");
}
myLanguageVersion = languageVersion;
return this;
}
private void registrarInjecting(Language language, MultiHostRegistrar registrar, List<PsiElement> els, String prefix, String suffix) {
if (els.size() > 0) {
registrar.startInjecting(language);
els.forEach(el -> registrar.addPlace(prefix, suffix, (PsiLanguageInjectionHost) el, ElementManipulators.getValueTextRange(el)));
registrar.doneInjecting();
}
}
@Override
@RequiredReadAction
public void injectLanguages(@Nonnull MultiHostRegistrar registrar, @Nonnull PsiElement context)
{
ShaderCGScript cgScript = (ShaderCGScript) context;
PsiElement scriptBlock = cgScript.getScriptBlock();
if(scriptBlock == null)
{
return;
}
int startOffsetInParent = scriptBlock.getStartOffsetInParent();
registrar.startInjecting(CGLanguage.INSTANCE).addPlace(null, null, cgScript, new TextRange(startOffsetInParent, scriptBlock.getTextLength() + startOffsetInParent)).doneInjecting();
}
private void injectLanguage(@NotNull MultiHostRegistrar registrar, @NotNull StringLiteralExpressionImpl element, MethodLanguageInjection languageInjection) {
Language language = languageInjection.getLanguage();
if (language == null) {
return;
}
registrar.startInjecting(language)
.addPlace(languageInjection.getPrefix(), languageInjection.getSuffix(), element, element.getValueRange())
.doneInjecting();
}
@Override
@Nonnull
public MultiHostRegistrar addPlace(@NonNls @Nullable String prefix, @NonNls @Nullable String suffix, @Nonnull PsiLanguageInjectionHost host, @Nonnull TextRange rangeInsideHost) {
checkThreading();
if (myLanguageVersion == null) {
clear();
throw new IllegalStateException("Seems you haven't called startInjecting()");
}
if (!host.isValidHost()) {
throw new IllegalArgumentException(host + ".isValidHost() in " + host.getClass() + " returned false so you mustn't inject here.");
}
PsiFile containingFile = PsiUtilCore.getTemplateLanguageFile(host);
assert containingFile == myHostPsiFile : exceptionContext("Trying to inject into foreign file: " + containingFile, myLanguageVersion, myHostPsiFile, myHostVirtualFile, myHostDocument, placeInfos,
myDocumentManagerBase);
TextRange hostTextRange = host.getTextRange();
if (!hostTextRange.contains(rangeInsideHost.shiftRight(hostTextRange.getStartOffset()))) {
clear();
throw new IllegalArgumentException("rangeInsideHost must lie within host text range. rangeInsideHost:" + rangeInsideHost + "; host textRange:" + hostTextRange);
}
cleared = false;
String nnPrefix = StringUtil.isEmpty(prefix) ? "" : prefix; // intern empty strings too to reduce gc
String nnSuffix = StringUtil.isEmpty(suffix) ? "" : suffix; // intern empty strings too to reduce gc
PlaceInfo info = new PlaceInfo(nnPrefix, nnSuffix, host, rangeInsideHost);
placeInfos.add(info);
return this;
}
@Override
public void injectLanguages(@Nonnull final MultiHostRegistrar injectionPlacesRegistrar, @Nonnull PsiElement context) {
final PsiLanguageInjectionHost host = (PsiLanguageInjectionHost)context;
InjectedLanguagePlaces placesRegistrar =
(language, rangeInsideHost, prefix, suffix) -> injectionPlacesRegistrar.startInjecting(language).addPlace(prefix, suffix, host, rangeInsideHost).doneInjecting();
for (LanguageInjector injector : LanguageInjector.EXTENSION_POINT_NAME.getExtensionList()) {
injector.getLanguagesToInject(host, placesRegistrar);
}
}
/**
* @deprecated Use {@link MultiHostRegistrar#startInjecting(Language)} instead. to be removed in IDEA 2018.1
*/
//@ApiStatus.ScheduledForRemoval(inVersion = "2018.1")
@Deprecated
@Nonnull
@Override
public MultiHostRegistrar startInjecting(@Nonnull Language language) {
throw new IllegalStateException();
}
/**
* Start injecting the reference in {@code language} in this place.
* Unlike {@link MultiHostRegistrar#startInjecting(Language)} this method doesn't inject the full blown file in the other language.
* Instead, it just marks some range as a reference in some language.
* For example, you can inject file reference into string literal.
* After that, it won't be highlighted as an injected fragment but still can be subject to e.g. "Goto declaraion" action.
*/
public static void injectReference(@Nonnull MultiHostRegistrar registrar,
@Nonnull Language language,
@Nonnull String prefix,
@Nonnull String suffix,
@Nonnull PsiLanguageInjectionHost host,
@Nonnull TextRange rangeInsideHost) {
((InjectionRegistrarImpl)registrar).injectReference(LanguageVersionUtil.findDefaultVersion(language), prefix, suffix, host, rangeInsideHost);
}
private static void inject(@NotNull MultiHostRegistrar registrar, @NotNull PsiElement context, TextRange textRange) {
registrar.startInjecting(RTLanguage.INSTANCE)
.addPlace(null, null, (PsiLanguageInjectionHost) context, textRange)
.doneInjecting();
}
@Override
public void getLanguagesToInject(@NotNull MultiHostRegistrar registrar, @NotNull PsiElement context) {
if(GraphQLLanguageInjectionUtil.isJSGraphQLLanguageInjectionTarget(context)) {
final JSStringTemplateExpression template = (JSStringTemplateExpression)context;
final TextRange graphQlTextRange = GraphQLLanguageInjectionUtil.getGraphQLTextRange(template);
if(graphQlTextRange.isEmpty()) {
// all whitespace
return;
}
registrar.startInjecting(GraphQLLanguage.INSTANCE);
final StringBuilder sb = new StringBuilder();
final TextRange[] stringRanges = template.getStringRanges();
int stringIndex = 0;
boolean insideTemplate = false;
for (ASTNode astNode : template.getNode().getChildren(null)) {
if(astNode.getElementType() == JSTokenTypes.BACKQUOTE) {
insideTemplate = true;
continue;
}
if(astNode.getElementType() == JSTokenTypes.STRING_TEMPLATE_PART) {
registrar.addPlace(sb.toString(), "", (PsiLanguageInjectionHost) template, stringRanges[stringIndex]);
stringIndex++;
sb.setLength(0);
} else if(insideTemplate) {
sb.append(astNode.getText());
}
}
registrar.doneInjecting();
// update graphql config notifications
final VirtualFile virtualFile = context.getContainingFile().getVirtualFile();
if(virtualFile != null && !ApplicationManager.getApplication().isUnitTestMode()) {
EditorNotifications.getInstance(context.getProject()).updateNotifications(virtualFile);
}
}
}
private static void inject(@NotNull MultiHostRegistrar registrar, @NotNull PsiElement context, TextRange textRange) {
registrar.startInjecting(RTLanguage.INSTANCE)
.addPlace(null, null, (PsiLanguageInjectionHost) context, textRange)
.doneInjecting();
}
@Override
public void getLanguagesToInject(@NotNull MultiHostRegistrar registrar, @NotNull PsiElement element) {
if (!(element instanceof StringLiteralExpression) || !((PsiLanguageInjectionHost) element).isValidHost()) {
return;
}
if (!Symfony2ProjectComponent.isEnabled(element.getProject())) {
return;
}
final StringLiteralExpressionImpl expr = (StringLiteralExpressionImpl) element;
PsiElement parent = expr.getParent();
final boolean isParameter = parent instanceof ParameterList && expr.getPrevPsiSibling() == null; // 1st parameter
final boolean isAssignment = parent instanceof AssignmentExpression;
if (!isParameter && !isAssignment) {
return;
}
if (isParameter) {
parent = parent.getParent();
}
for (MethodLanguageInjection languageInjection : LANGUAGE_INJECTIONS) {
// $crawler->filter('...')
// $em->createQuery('...')
// JsonResponse::fromJsonString('...')
if (parent instanceof MethodReference) {
if (PhpElementsUtil.isMethodReferenceInstanceOf((MethodReference) parent, languageInjection.getSignatures())) {
injectLanguage(registrar, expr, languageInjection);
return;
}
}
// $dql = "...";
else if (parent instanceof AssignmentExpression) {
Language language = languageInjection.getLanguage();
if (language != null && LANGUAGE_ID_DQL.equals(language.getID())) {
PhpPsiElement variable = ((AssignmentExpression) parent).getVariable();
if (variable instanceof Variable) {
if (DQL_VARIABLE_NAME.equals(variable.getName())) {
injectLanguage(registrar, expr, languageInjection);
return;
}
}
}
}
}
}
@Override
public void injectLanguages(@Nonnull MultiHostRegistrar registrar, @Nonnull PsiElement context) {
ConcatenationInjectorManager manager = getInstance(myProject);
if (manager.myConcatenationInjectors.isEmpty()) {
return;
}
final PsiFile containingFile = ((InjectionRegistrarImpl)registrar).getHostPsiFile();
Project project = containingFile.getProject();
long modificationCount = PsiManager.getInstance(project).getModificationTracker().getModificationCount();
Pair<PsiElement, PsiElement[]> pair = computeAnchorAndOperands(context);
PsiElement anchor = pair.first;
PsiElement[] operands = pair.second;
Integer noInjectionTimestamp = anchor.getUserData(NO_CONCAT_INJECTION_TIMESTAMP);
InjectionResult result;
ParameterizedCachedValue<InjectionResult, PsiElement> data = null;
if (operands.length == 0 || noInjectionTimestamp != null && noInjectionTimestamp == modificationCount) {
result = null;
}
else {
data = anchor.getUserData(INJECTED_PSI_IN_CONCATENATION);
result = data == null ? null : data.getValue(context);
if (result == null || !result.isValid()) {
result = doCompute(containingFile, project, anchor, operands);
}
}
if (result != null) {
((InjectionRegistrarImpl)registrar).addToResults(result);
if (data == null) {
CachedValueProvider.Result<InjectionResult> cachedResult = CachedValueProvider.Result.create(result, manager);
data = CachedValuesManager.getManager(project).createParameterizedCachedValue(context1 -> {
PsiFile containingFile1 = context1.getContainingFile();
Project project1 = containingFile1.getProject();
Pair<PsiElement, PsiElement[]> pair1 = computeAnchorAndOperands(context1);
InjectionResult result1 = pair1.second.length == 0 ? null : doCompute(containingFile1, project1, pair1.first, pair1.second);
return result1 == null ? null : CachedValueProvider.Result.create(result1, manager);
}, false);
((PsiParameterizedCachedValue<InjectionResult, PsiElement>)data).setValue(cachedResult);
anchor.putUserData(INJECTED_PSI_IN_CONCATENATION, data);
if (anchor.getUserData(NO_CONCAT_INJECTION_TIMESTAMP) != null) {
anchor.putUserData(NO_CONCAT_INJECTION_TIMESTAMP, null);
}
}
}
else {
// cache no-injection flag
if (anchor.getUserData(INJECTED_PSI_IN_CONCATENATION) != null) {
anchor.putUserData(INJECTED_PSI_IN_CONCATENATION, null);
}
anchor.putUserData(NO_CONCAT_INJECTION_TIMESTAMP, (int)modificationCount);
}
}
@Override
public MultiHostRegistrar startInjecting(@Nonnull Language language) {
return startInjecting(LanguageVersionUtil.findDefaultVersion(language));
}
@Nonnull
@Override
public MultiHostRegistrar startInjecting(@Nonnull LanguageVersion languageVersion) {
return startInjecting(languageVersion, null);
}