mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IntelliLang: support ignore-pattern option for disabling injection for host or string concatenation
New <ignore-pattern> 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
This commit is contained in:
committed by
intellij-monorepo-bot
parent
198a91a353
commit
0409f037fd
+10
-4
@@ -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<Pair<PsiLanguageInjectionHost, Language>> 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<Boolean> unparsableRef = Ref.create(myUnparsable);
|
||||
List<Object> objects = ContextComputationProcessor.collectOperands(injection.getPrefix(), injection.getSuffix(), unparsableRef, myOperands);
|
||||
if (objects.isEmpty()) return Collections.emptyList();
|
||||
if (objects.isEmpty()) return emptyList();
|
||||
List<Trinity<PsiLanguageInjectionHost, InjectedLanguage, TextRange>> 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<TextRange> textBlockInjectedArea = getTextBlockInjectedArea(curHost);
|
||||
List<TextRange> 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<Pair<PsiLanguageInjectionHost, Language>> res = new ArrayList<>();
|
||||
if (separateFiles) {
|
||||
|
||||
+49
-4
@@ -66,9 +66,14 @@ public class BaseInjection implements Injection, PersistentStateComponent<Elemen
|
||||
@NonNls
|
||||
private String myValuePattern = "";
|
||||
private Pattern myCompiledValuePattern;
|
||||
|
||||
@NonNls
|
||||
private String myIgnorePattern = "";
|
||||
private Pattern myCompiledIgnorePattern;
|
||||
|
||||
private boolean mySingleFile;
|
||||
|
||||
public BaseInjection(@NotNull final String id) {
|
||||
public BaseInjection(@NotNull String id) {
|
||||
mySupportId = id;
|
||||
}
|
||||
|
||||
@@ -142,6 +147,19 @@ public class BaseInjection implements Injection, PersistentStateComponent<Elemen
|
||||
mySuffix = suffix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIgnoredPlace(PsiElement element) {
|
||||
if (myCompiledIgnorePattern == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LiteralTextEscaper<? extends PsiLanguageInjectionHost> 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<TextRange> getInjectedArea(final PsiElement element) {
|
||||
@@ -224,6 +242,7 @@ public class BaseInjection implements Injection, PersistentStateComponent<Elemen
|
||||
result = 31 * result + myPrefix.hashCode();
|
||||
result = 31 * result + mySuffix.hashCode();
|
||||
result = 31 * result + myValuePattern.hashCode();
|
||||
result = 31 * result + myIgnorePattern.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -237,6 +256,7 @@ public class BaseInjection implements Injection, PersistentStateComponent<Elemen
|
||||
myDisplayName = other.getDisplayName();
|
||||
|
||||
setValuePattern(other.getValuePattern());
|
||||
setIgnorePattern(other.getIgnorePattern());
|
||||
mySingleFile = other.mySingleFile;
|
||||
|
||||
myPlaces = other.getInjectionPlaces().clone();
|
||||
@@ -251,6 +271,7 @@ public class BaseInjection implements Injection, PersistentStateComponent<Elemen
|
||||
myPrefix = StringUtil.notNullize(element.getChildText("prefix"));
|
||||
mySuffix = StringUtil.notNullize(element.getChildText("suffix"));
|
||||
setValuePattern(element.getChildText("value-pattern"));
|
||||
setIgnorePattern(element.getChildText("ignore-pattern"));
|
||||
mySingleFile = element.getChild("single-file") != null;
|
||||
readExternalImpl(element);
|
||||
final List<Element> placeElements = element.getChildren("place");
|
||||
@@ -291,6 +312,9 @@ public class BaseInjection implements Injection, PersistentStateComponent<Elemen
|
||||
if (StringUtil.isNotEmpty(myValuePattern)) {
|
||||
e.addContent(new Element("value-pattern").setText(myValuePattern));
|
||||
}
|
||||
if (StringUtil.isNotEmpty(myIgnorePattern)) {
|
||||
e.addContent(new Element("ignore-pattern").setText(myIgnorePattern));
|
||||
}
|
||||
if (mySingleFile) {
|
||||
e.addContent(new Element("single-file"));
|
||||
}
|
||||
@@ -322,9 +346,31 @@ public class BaseInjection implements Injection, PersistentStateComponent<Elemen
|
||||
myCompiledValuePattern = null;
|
||||
}
|
||||
}
|
||||
catch (Exception e1) {
|
||||
catch (Exception ex) {
|
||||
myCompiledValuePattern = null;
|
||||
Logger.getInstance(getClass().getName()).info("Invalid pattern", e1);
|
||||
Logger.getInstance(getClass().getName()).info("Invalid value-pattern", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getIgnorePattern() {
|
||||
return myIgnorePattern;
|
||||
}
|
||||
|
||||
public void setIgnorePattern(@RegExp @Nullable String pattern) {
|
||||
try {
|
||||
if (pattern != null && pattern.length() > 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<Elemen
|
||||
return myCompiledValuePattern == null;
|
||||
}
|
||||
|
||||
|
||||
private static List<TextRange> getMatchingRanges(Matcher matcher, final int length) {
|
||||
final List<TextRange> list = new SmartList<>();
|
||||
int start = 0;
|
||||
|
||||
@@ -46,6 +46,12 @@ public interface Injection {
|
||||
@NotNull
|
||||
List<TextRange> 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
|
||||
|
||||
+9
-6
@@ -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<TextRange> 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<TextRange> 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) {
|
||||
|
||||
Reference in New Issue
Block a user