From 0409f037fd8a8f33af08b99afa900e12a5256485 Mon Sep 17 00:00:00 2001 From: Yuriy Artamonov Date: Thu, 9 Jan 2020 18:41:57 +0300 Subject: [PATCH] IntelliLang: support ignore-pattern option for disabling injection for host or string concatenation New tag in injection configs determines whether injection to host or concatenation must be ignored. If at least one place in concatenation is ignored then the entire concatenation must be ignored and language must not be injected. This option is useful in case the same place can contain different languages or template content that cannot be recognized as a valid language literal, e.g. SQL with optional Velocity templating. GitOrigin-RevId: 6fed7e959dc02fc1efc2ed044962caaa3179bfc9 --- .../inject/java/ConcatenationInjector.java | 14 +++-- .../inject/config/BaseInjection.java | 53 +++++++++++++++++-- .../intelliLang/inject/config/Injection.java | 6 +++ .../inject/xml/XmlLanguageInjector.java | 15 +++--- 4 files changed, 74 insertions(+), 14 deletions(-) diff --git a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/ConcatenationInjector.java b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/ConcatenationInjector.java index 9426b3111b06..caf88d00ac15 100644 --- a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/ConcatenationInjector.java +++ b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/ConcatenationInjector.java @@ -38,6 +38,8 @@ import org.jetbrains.annotations.Nullable; import java.util.*; +import static java.util.Collections.emptyList; + /** * @author cdr */ @@ -337,13 +339,13 @@ public final class ConcatenationInjector implements ConcatenationAwareInjector { @NotNull List> processInjectionWithContext(BaseInjection injection, boolean settingsAvailable) { Language language = InjectorUtils.getLanguage(injection); - if (language == null) return Collections.emptyList(); + if (language == null) return emptyList(); boolean separateFiles = !injection.isSingleFile() && StringUtil.isNotEmpty(injection.getValuePattern()); Ref unparsableRef = Ref.create(myUnparsable); List objects = ContextComputationProcessor.collectOperands(injection.getPrefix(), injection.getSuffix(), unparsableRef, myOperands); - if (objects.isEmpty()) return Collections.emptyList(); + if (objects.isEmpty()) return emptyList(); List> result = new ArrayList<>(); int len = objects.size(); for (int i = 0; i < len; i++) { @@ -351,7 +353,7 @@ public final class ConcatenationInjector implements ConcatenationAwareInjector { Object o = objects.get(i); if (o instanceof String) { curPrefix = (String)o; - if (i == len - 1) return Collections.emptyList(); // IDEADEV-26751 + if (i == len - 1) return emptyList(); // IDEADEV-26751 o = objects.get(++i); } String curSuffix = null; @@ -371,6 +373,10 @@ public final class ConcatenationInjector implements ConcatenationAwareInjector { } else { if (curHost instanceof PsiLiteralExpression) { + if (injection.isIgnoredPlace(curHost)) { + return emptyList(); + } + List textBlockInjectedArea = getTextBlockInjectedArea(curHost); List injectedArea = (textBlockInjectedArea == null) ? injection.getInjectedArea(curHost) : textBlockInjectedArea; for (int j = 0, injectedAreaSize = injectedArea.size(); j < injectedAreaSize; j++) { @@ -392,7 +398,7 @@ public final class ConcatenationInjector implements ConcatenationAwareInjector { } } if (result.isEmpty()) { - return Collections.emptyList(); + return emptyList(); } List> res = new ArrayList<>(); if (separateFiles) { diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/BaseInjection.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/BaseInjection.java index bba5f12ab8a7..76af46a71619 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/BaseInjection.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/BaseInjection.java @@ -66,9 +66,14 @@ public class BaseInjection implements Injection, PersistentStateComponent textEscaper = ((PsiLanguageInjectionHost)element).createLiteralTextEscaper(); + StringBuilder sb = new StringBuilder(); + textEscaper.decode(ElementManipulators.getValueTextRange(element), sb); + + return myCompiledIgnorePattern.matcher(StringPattern.newBombedCharSequence(sb)).find(); + } + @Override @NotNull public List getInjectedArea(final PsiElement element) { @@ -224,6 +242,7 @@ public class BaseInjection implements Injection, PersistentStateComponent placeElements = element.getChildren("place"); @@ -291,6 +312,9 @@ public class BaseInjection implements Injection, PersistentStateComponent 0) { + myIgnorePattern = pattern; + myCompiledIgnorePattern = Pattern.compile(pattern, Pattern.DOTALL); + } + else { + myIgnorePattern = ""; + myCompiledIgnorePattern = null; + } + } + catch (Exception ex) { + myCompiledIgnorePattern = null; + Logger.getInstance(getClass().getName()).info("Invalid ignore-pattern", ex); } } @@ -348,7 +394,6 @@ public class BaseInjection implements Injection, PersistentStateComponent getMatchingRanges(Matcher matcher, final int length) { final List list = new SmartList<>(); int start = 0; diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/Injection.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/Injection.java index 7faacd4cdcea..1a71113d0d6f 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/Injection.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/Injection.java @@ -46,6 +46,12 @@ public interface Injection { @NotNull List getInjectedArea(PsiElement element); + /** + * Determines whether injection to host or concatenation must be ignored. If at least one place in concatenation is ignored then + * the entire concatenation must be ignored and language must not be injected. + */ + boolean isIgnoredPlace(PsiElement element); + /** * Determines how the injection would like being displayed (e.g. attributes * return a qualified TAG-NAME/@ATT-NAME combination name instead of just diff --git a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjector.java b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjector.java index b9d42ac87e8d..97577d680a8a 100644 --- a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjector.java +++ b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjector.java @@ -115,14 +115,17 @@ public final class XmlLanguageInjector implements MultiHostInjector { xmlTag.acceptChildren(new PsiElementVisitor() { @Override - public void visitElement(@NotNull final PsiElement element) { + public void visitElement(@NotNull PsiElement element) { if (element instanceof XmlText) { if (!(element instanceof PsiLanguageInjectionHost) || element.getTextLength() == 0) return; - final List list = injection.getInjectedArea(element); - final InjectedLanguage l = - InjectedLanguage.create(injection.getInjectedLanguageId(), injection.getPrefix(), injection.getSuffix(), false); - for (TextRange textRange : list) { - result.add(Trinity.create((PsiLanguageInjectionHost)element, l, textRange)); + + if (!injection.isIgnoredPlace(element)) { + List list = injection.getInjectedArea(element); + InjectedLanguage l = + InjectedLanguage.create(injection.getInjectedLanguageId(), injection.getPrefix(), injection.getSuffix(), false); + for (TextRange textRange : list) { + result.add(Trinity.create((PsiLanguageInjectionHost)element, l, textRange)); + } } } else if (element instanceof XmlTag) {