package org.intellij.plugins.markdown.injection;
import com.intellij.lang.Language;
import com.intellij.lang.LanguageParserDefinitions;
import com.intellij.lang.injection.MultiHostInjector;
import com.intellij.lang.injection.MultiHostRegistrar;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import org.intellij.plugins.markdown.lang.psi.impl.MarkdownCodeFenceContentImpl;
import org.intellij.plugins.markdown.lang.psi.impl.MarkdownCodeFenceImpl;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.List;
public class CodeFenceInjector implements MultiHostInjector {
@Override
public void getLanguagesToInject(@NotNull MultiHostRegistrar registrar, @NotNull PsiElement context) {
if (!(context instanceof MarkdownCodeFenceImpl)) {
return;
}
if (PsiTreeUtil.findChildOfType(context, MarkdownCodeFenceContentImpl.class) == null) {
return;
}
final Language language = findLangForInjection(((MarkdownCodeFenceImpl)context));
if (language == null || LanguageParserDefinitions.INSTANCE.forLanguage(language) == null) {
return;
}
registrar.startInjecting(language);
final List<MarkdownCodeFenceContentImpl> list = PsiTreeUtil.getChildrenOfTypeAsList(context, MarkdownCodeFenceContentImpl.class);
for (int i = 0; i < list.size(); i++) {
final MarkdownCodeFenceContentImpl content = list.get(i);
final boolean includeEol = (i + 1 < list.size());
final TextRange rangeInHost = TextRange.from(content.getStartOffsetInParent(),
content.getTextLength() + (includeEol ? 1 : 0));
registrar.addPlace(null, null, ((MarkdownCodeFenceImpl)context), rangeInHost);
}
registrar.doneInjecting();
}
@NotNull
@Override
public List<? extends Class<? extends PsiElement>> elementsToInjectIn() {
return Collections.singletonList(MarkdownCodeFenceImpl.class);
}
@Nullable
protected Language findLangForInjection(@NotNull MarkdownCodeFenceImpl element) {
final String fenceLanguage = element.getFenceLanguage();
if (fenceLanguage == null) {
return null;
}
return guessLanguageByFenceLang(fenceLanguage);
}
@Nullable
private static Language guessLanguageByFenceLang(@NotNull String langName) {
return LanguageGuesser.INSTANCE.guessLanguage(langName);
}
}