Add API allowing to register a language extension for a group of languages matching a certain criteria

This commit is contained in:
Dmitry Jemerov
2017-02-08 12:59:29 +01:00
parent 1fcdc74573
commit 30189353d4
3 changed files with 82 additions and 14 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2017 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.
@@ -21,12 +21,12 @@ package com.intellij.lang;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.KeyedExtensionCollector;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@@ -55,20 +55,33 @@ public class LanguageExtension<T> extends KeyedExtensionCollector<T, Language> {
T cached = l.getUserData(IN_LANGUAGE_CACHE);
if (cached != null) return cached;
List<T> extensions = forKey(l);
T result;
if (extensions.isEmpty()) {
Language base = l.getBaseLanguage();
result = base == null ? myDefaultImplementation : forLanguage(base);
}
else {
result = extensions.get(0);
}
T result = findForLanguage(l);
if (result == null) return null;
result = l.putUserDataIfAbsent(IN_LANGUAGE_CACHE, result);
return result;
}
protected T findForLanguage(@NotNull Language l) {
List<T> extensions = forKey(l);
if (!extensions.isEmpty()) {
return extensions.get(0);
}
Language base = l.getBaseLanguage();
if (base != null) {
return forLanguage(base);
}
for (MetaLanguage metaLanguage: MetaLanguage.all()) {
if (metaLanguage.matchesLanguage(l)) {
T result = forLanguage(metaLanguage);
if (result != null) break;
}
}
return myDefaultImplementation;
}
/**
* @see #allForLanguageOrAny(Language)
*/
@@ -86,9 +99,17 @@ public class LanguageExtension<T> extends KeyedExtensionCollector<T, Language> {
@NotNull
public List<T> allForLanguageOrAny(@NotNull Language l) {
List<T> providers = allForLanguage(l);
if (l == Language.ANY) return providers;
return ContainerUtil.concat(providers, allForLanguage(Language.ANY));
List<T> providers = new ArrayList<T>(allForLanguage(l));
if (l != Language.ANY) {
providers.addAll(allForLanguage(Language.ANY));
}
if (!(l instanceof MetaLanguage)) {
for (MetaLanguage metaLanguage : MetaLanguage.all()) {
providers.addAll(allForLanguage(metaLanguage));
}
}
return providers;
}
protected T getDefaultImplementation() {
@@ -108,6 +129,9 @@ public class LanguageExtension<T> extends KeyedExtensionCollector<T, Language> {
key = key.getBaseLanguage();
}
allowed.add("any");
for (MetaLanguage metaLanguage : MetaLanguage.all()) {
allowed.add(metaLanguage.getID());
}
return allowed;
}
@@ -0,0 +1,43 @@
/*
* Copyright 2000-2017 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 com.intellij.lang;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.extensions.Extensions;
import org.jetbrains.annotations.NotNull;
/**
* Allows to register a language extension for a group of languages defined by a certain criterion.
* To use this, specify the ID of a meta-language in the "language" attribute of an extension in plugin.xml.
*
* @author yole
*/
public abstract class MetaLanguage extends Language {
public static final ExtensionPointName<MetaLanguage> EP_NAME = ExtensionPointName.create("com.intellij.metaLanguage");
protected MetaLanguage(@NotNull String ID) {
super(ID);
}
public static MetaLanguage[] all() {
return Extensions.getExtensions(EP_NAME);
}
/**
* Checks if the given language matches the criterion of this meta-language.
*/
public abstract boolean matchesLanguage(Language language);
}
@@ -901,6 +901,7 @@
interface="com.intellij.execution.testframework.sm.runner.history.ImportTestOutputExtension"/>
<extensionPoint name="sdkEditorAdditionalOptionsProvider" interface="com.intellij.openapi.SdkEditorAdditionalOptionsProvider"/>
<extensionPoint name="metaLanguage" interface="com.intellij.lang.MetaLanguage"/>
</extensionPoints>
</idea-plugin>