package org.intellij.plugins.markdown.injection;
import com.intellij.lang.Language;
import com.intellij.lexer.EmbeddedTokenTypesProvider;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.util.ClearableLazyValue;
import com.intellij.openapi.util.NotNullLazyValue;
import com.intellij.util.containers.HashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import java.util.*;
public enum LanguageGuesser {
INSTANCE;
private NotNullLazyValue<List<EmbeddedTokenTypesProvider>> embeddedTokenTypeProviders =
new NotNullLazyValue<List<EmbeddedTokenTypesProvider>>() {
@NotNull
@Override
protected List<EmbeddedTokenTypesProvider> compute() {
return Arrays.asList(Extensions.getExtensions(EmbeddedTokenTypesProvider.EXTENSION_POINT_NAME));
}
};
private ClearableLazyValue<List<CodeFenceLanguageProvider>> codeFenceLanguageProviders =
new ClearableLazyValue<List<CodeFenceLanguageProvider>>() {
@NotNull
@Override
protected List<CodeFenceLanguageProvider> compute() {
return Arrays.asList(Extensions.getExtensions(CodeFenceLanguageProvider.EP_NAME));
}
};
private NotNullLazyValue<Map<String, Language>> langIdToLanguage = new NotNullLazyValue<Map<String, Language>>() {
@NotNull
@Override
protected Map<String, Language> compute() {
final HashMap<String, Language> result = new HashMap<>();
for (Language language : Language.getRegisteredLanguages()) {
if (language.getID().isEmpty()) {
continue;
}
result.put(language.getID().toLowerCase(Locale.US), language);
}
final Language javascriptLanguage = result.get("javascript");
if (javascriptLanguage != null) {
result.put("js", javascriptLanguage);
}
return result;
}
};
@NotNull
public Map<String, Language> getLangToLanguageMap() {
return Collections.unmodifiableMap(langIdToLanguage.getValue());
}
@NotNull
public List<CodeFenceLanguageProvider> getCodeFenceLanguageProviders() {
return codeFenceLanguageProviders.getValue();
}
@TestOnly
public void resetCodeFenceLanguageProviders() {
codeFenceLanguageProviders.drop();
}
@Nullable
public Language guessLanguage(@NotNull String languageName) {
for (CodeFenceLanguageProvider provider : codeFenceLanguageProviders.getValue()) {
final Language languageByProvider = provider.getLanguageByInfoString(languageName);
if (languageByProvider != null) {
return languageByProvider;
}
}
final Language languageFromMap = langIdToLanguage.getValue().get(languageName.toLowerCase(Locale.US));
if (languageFromMap != null) {
return languageFromMap;
}
for (EmbeddedTokenTypesProvider provider : embeddedTokenTypeProviders.getValue()) {
if (provider.getName().equalsIgnoreCase(languageName)) {
return provider.getElementType().getLanguage();
}
}
return null;
}
}