IDEA-92972 general purpose comment-based injector

This commit is contained in:
Gregory.Shrago
2012-11-30 02:48:58 +04:00
parent d478dd3cbb
commit 35b07a29a5
4 changed files with 65 additions and 2 deletions
@@ -46,6 +46,9 @@ public class PsiCommentManipulator extends AbstractElementManipulator<PsiComment
if (text.startsWith("//")) return new TextRange(2, element.getTextLength());
if (text.startsWith("/**") && text.endsWith("*/")) return new TextRange(3, element.getTextLength()-2);
if (text.startsWith("/*") && text.endsWith("*/")) return new TextRange(2, element.getTextLength()-2);
if (text.startsWith("<!--") && text.endsWith("-->")) return new TextRange(4, element.getTextLength()-3);
if (text.startsWith("--")) return new TextRange(2, element.getTextLength());
if (text.startsWith("#")) return new TextRange(1, element.getTextLength());
return super.getRangeInElement(element);
}
}
@@ -34,6 +34,7 @@
<projectConfigurable instance="org.intellij.plugins.intelliLang.InjectionsSettingsUI"/>
<multiHostInjector implementation="org.intellij.plugins.intelliLang.inject.CommentLanguageInjector"/>
<multiHostInjector implementation="org.intellij.plugins.intelliLang.inject.TemporaryPlacesInjector"/>
<multiHostInjector implementation="org.intellij.plugins.intelliLang.inject.DefaultLanguageInjector" order="last"/>
@@ -0,0 +1,43 @@
package org.intellij.plugins.intelliLang.inject;
import com.intellij.lang.Language;
import com.intellij.lang.injection.MultiHostInjector;
import com.intellij.lang.injection.MultiHostRegistrar;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.Trinity;
import com.intellij.psi.*;
import org.intellij.plugins.intelliLang.inject.config.BaseInjection;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.List;
/**
* @author gregsh
*/
public class CommentLanguageInjector implements MultiHostInjector {
@NotNull
public List<? extends Class<? extends PsiElement>> elementsToInjectIn() {
return Collections.singletonList(PsiLanguageInjectionHost.class);
}
public void getLanguagesToInject(@NotNull final MultiHostRegistrar registrar, @NotNull final PsiElement context) {
PsiLanguageInjectionHost host = (PsiLanguageInjectionHost)context;
final ElementManipulator<PsiLanguageInjectionHost> manipulator = ElementManipulators.getManipulator(host);
if (manipulator == null) return;
PsiComment comment = InjectorUtils.findNearestComment(context);
if (comment == null) return;
String text = ElementManipulators.getValueText(comment).trim();
BaseInjection injection = InjectorUtils.detectInjectionFromText("comment", text);
if (injection == null) return;
InjectedLanguage injectedLanguage = InjectedLanguage.create(injection.getInjectedLanguageId(), injection.getPrefix(), injection.getSuffix(), false);
Language language = injectedLanguage != null ? injectedLanguage.getLanguage() : null;
if (language != null) {
Trinity<PsiLanguageInjectionHost, InjectedLanguage, TextRange> info =
Trinity.create(host, injectedLanguage, manipulator.getRangeInElement(host));
InjectorUtils.registerInjection(language, Collections.singletonList(info), context.getContainingFile(), registrar);
}
}
}
@@ -25,8 +25,7 @@ import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.Trinity;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiLanguageInjectionHost;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.tree.injected.MultiHostRegistrarImpl;
import com.intellij.psi.impl.source.tree.injected.Place;
import com.intellij.util.ArrayUtil;
@@ -219,4 +218,21 @@ public class InjectorUtils {
injection.setSuffix(suffix);
return injection;
}
@Nullable
public static PsiComment findNearestComment(PsiElement element) {
if (element instanceof PsiComment) return null;
PsiElement start = element;
for (int i=0; i<2 && start != null; i++) {
if (start instanceof PsiFile) return null;
for (PsiElement e = start.getPrevSibling(); e != null; e = e.getPrevSibling()) {
if (e instanceof PsiComment) return (PsiComment)e;
if (e instanceof PsiWhiteSpace) continue;
if (e instanceof PsiLanguageInjectionHost && StringUtil.isEmptyOrSpaces(e.getText())) continue;
break;
}
start = element.getParent();
}
return null;
}
}