summaryrefslogtreecommitdiff
path: root/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java
diff options
context:
space:
mode:
Diffstat (limited to 'platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java')
-rw-r--r--platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java71
1 files changed, 56 insertions, 15 deletions
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java
index 27089fa70e91..fdc434d8d11a 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java
@@ -16,6 +16,7 @@
package com.intellij.psi.impl.source.tree.injected;
+import com.intellij.extapi.psi.PsiFileBase;
import com.intellij.injected.editor.*;
import com.intellij.lang.Language;
import com.intellij.lang.LanguageUtil;
@@ -48,8 +49,10 @@ import java.util.List;
* @author cdr
*/
public class InjectedLanguageUtil {
- static final Key<List<Trinity<IElementType, SmartPsiElementPointer<PsiLanguageInjectionHost>, TextRange>>> HIGHLIGHT_TOKENS = Key.create("HIGHLIGHT_TOKENS");
- public static Key<Boolean> FRANKENSTEIN_INJECTION = Key.create("FRANKENSTEIN_INJECTION"); // meaning: injected file text is probably incorrect
+ static final Key<List<Trinity<IElementType, SmartPsiElementPointer<PsiLanguageInjectionHost>, TextRange>>> HIGHLIGHT_TOKENS =
+ Key.create("HIGHLIGHT_TOKENS");
+ public static Key<Boolean> FRANKENSTEIN_INJECTION = Key.create("FRANKENSTEIN_INJECTION");
+ // meaning: injected file text is probably incorrect
public static void forceInjectionOnElement(@NotNull PsiElement host) {
enumerate(host, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
@@ -113,9 +116,9 @@ public class InjectedLanguageUtil {
* @return true if enumerated successfully
*/
public static boolean enumerate(@NotNull PsiElement host,
- @NotNull PsiFile containingFile,
- boolean probeUp,
- @NotNull PsiLanguageInjectionHost.InjectedPsiVisitor visitor) {
+ @NotNull PsiFile containingFile,
+ boolean probeUp,
+ @NotNull PsiLanguageInjectionHost.InjectedPsiVisitor visitor) {
//do not inject into nonphysical files except during completion
if (!containingFile.isPhysical() && containingFile.getOriginalFile() == containingFile) {
final PsiElement context = InjectedLanguageManager.getInstance(containingFile.getProject()).getInjectionHost(containingFile);
@@ -175,6 +178,32 @@ public class InjectedLanguageUtil {
return null;
}
+ /**
+ * Finds injected language in expression
+ *
+ * @param expression where to find
+ * @param classToFind class that represents language we look for
+ * @param <T> class that represents language we look for
+ * @return instance of class that represents language we look for or null of not found
+ */
+ @Nullable
+ @SuppressWarnings("unchecked") // We check types dynamically (using isAssignableFrom)
+ public static <T extends PsiFileBase> T findInjectedFile(@NotNull final PsiElement expression,
+ @NotNull final Class<T> classToFind) {
+ final List<Pair<PsiElement, TextRange>> files =
+ InjectedLanguageManager.getInstance(expression.getProject()).getInjectedPsiFiles(expression);
+ if (files == null) {
+ return null;
+ }
+ for (final Pair<PsiElement, TextRange> fileInfo : files) {
+ final PsiElement injectedFile = fileInfo.first;
+ if (classToFind.isAssignableFrom(injectedFile.getClass())) {
+ return (T)injectedFile;
+ }
+ }
+ return null;
+ }
+
public static Editor getEditorForInjectedLanguageNoCommit(@Nullable Editor editor, @Nullable PsiFile file, final int offset) {
if (editor == null || file == null || editor instanceof EditorWindow) return editor;
PsiFile injectedFile = findInjectedPsiNoCommit(file, offset);
@@ -200,7 +229,9 @@ public class InjectedLanguageUtil {
}
}
}
- if (!documentWindow.isValid()) return hostEditor; // since the moment we got hold of injectedFile and this moment call, document may have been dirtied
+ if (!documentWindow.isValid()) {
+ return hostEditor; // since the moment we got hold of injectedFile and this moment call, document may have been dirtied
+ }
return EditorWindowImpl.create(documentWindow, (EditorImpl)hostEditor, injectedFile);
}
@@ -284,7 +315,8 @@ public class InjectedLanguageUtil {
ParameterizedCachedValue<MultiHostRegistrarImpl, PsiElement> cachedValue =
CachedValuesManager.getManager(project).createParameterizedCachedValue(INJECTED_PSI_PROVIDER, false);
- CachedValueProvider.Result<MultiHostRegistrarImpl> result = CachedValueProvider.Result.create(registrar, PsiModificationTracker.MODIFICATION_COUNT, registrar);
+ CachedValueProvider.Result<MultiHostRegistrarImpl> result =
+ CachedValueProvider.Result.create(registrar, PsiModificationTracker.MODIFICATION_COUNT, registrar);
((PsiParameterizedCachedValue<MultiHostRegistrarImpl, PsiElement>)cachedValue).setValue(result);
e.putUserData(INJECTED_PSI, cachedValue);
@@ -307,7 +339,9 @@ public class InjectedLanguageUtil {
// returns (injected psi, leaf element at the offset, language of the leaf element)
// since findElementAt() is expensive, we trying to reuse its result
@NotNull
- private static Trinity<PsiElement,PsiElement,Language> tryOffset(@NotNull PsiFile hostFile, final int offset, @NotNull PsiDocumentManager documentManager) {
+ private static Trinity<PsiElement, PsiElement, Language> tryOffset(@NotNull PsiFile hostFile,
+ final int offset,
+ @NotNull PsiDocumentManager documentManager) {
FileViewProvider provider = hostFile.getViewProvider();
Language leafLanguage = null;
PsiElement leafElement = null;
@@ -319,11 +353,11 @@ public class InjectedLanguageUtil {
leafElement = element;
}
PsiElement injected = findInside(element, hostFile, offset, documentManager);
- if (injected != null) return Trinity.create(injected,element, language);
+ if (injected != null) return Trinity.create(injected, element, language);
}
// maybe we are at the border between two psi elements, then try to find injection at the end of the left element
if (offset != 0 && (element == null || element.getTextRange().getStartOffset() == offset)) {
- PsiElement leftElement = provider.findElementAt(offset-1, language);
+ PsiElement leftElement = provider.findElementAt(offset - 1, language);
if (leftElement != null && leftElement.getTextRange().getEndOffset() == offset) {
PsiElement injected = findInside(leftElement, hostFile, offset, documentManager);
if (injected != null) return Trinity.create(injected, element, language);
@@ -334,7 +368,10 @@ public class InjectedLanguageUtil {
return Trinity.create(null, leafElement, leafLanguage);
}
- private static PsiElement findInside(@NotNull PsiElement element, @NotNull PsiFile hostFile, final int hostOffset, @NotNull final PsiDocumentManager documentManager) {
+ private static PsiElement findInside(@NotNull PsiElement element,
+ @NotNull PsiFile hostFile,
+ final int hostOffset,
+ @NotNull final PsiDocumentManager documentManager) {
final Ref<PsiElement> out = new Ref<PsiElement>();
enumerate(element, hostFile, true, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
@Override
@@ -361,10 +398,12 @@ public class InjectedLanguageUtil {
// modification of cachedInjectedDocuments must be under PsiLock only
ConcurrentList<DocumentWindow> injected = hostPsiFile.getUserData(INJECTED_DOCS_KEY);
if (injected == null) {
- injected = ((UserDataHolderEx)hostPsiFile).putUserDataIfAbsent(INJECTED_DOCS_KEY, ContainerUtil.<DocumentWindow>createConcurrentList());
+ injected =
+ ((UserDataHolderEx)hostPsiFile).putUserDataIfAbsent(INJECTED_DOCS_KEY, ContainerUtil.<DocumentWindow>createConcurrentList());
}
return injected;
}
+
public static void clearCachedInjectedFragmentsForFile(@NotNull PsiFile file) {
file.putUserData(INJECTED_DOCS_KEY, null);
}
@@ -426,10 +465,12 @@ public class InjectedLanguageUtil {
}
return containingFile;
}
+
@NotNull
public static Editor getTopLevelEditor(@NotNull Editor editor) {
return editor instanceof EditorWindow ? ((EditorWindow)editor).getDelegate() : editor;
}
+
public static boolean isInInjectedLanguagePrefixSuffix(@NotNull final PsiElement element) {
PsiFile injectedFile = element.getContainingFile();
if (injectedFile == null) return false;
@@ -461,13 +502,13 @@ public class InjectedLanguageUtil {
public static String getUnescapedText(PsiFile file, @Nullable final PsiElement startElement, @Nullable final PsiElement endElement) {
final InjectedLanguageManager manager = InjectedLanguageManager.getInstance(file.getProject());
if (manager.getInjectionHost(file) == null) {
- return file.getText().substring(startElement == null? 0 : startElement.getTextRange().getStartOffset(),
- endElement == null? file.getTextLength() : endElement.getTextRange().getStartOffset());
+ return file.getText().substring(startElement == null ? 0 : startElement.getTextRange().getStartOffset(),
+ endElement == null ? file.getTextLength() : endElement.getTextRange().getStartOffset());
}
final StringBuilder sb = new StringBuilder();
file.accept(new PsiRecursiveElementWalkingVisitor() {
- Boolean myState = startElement == null? Boolean.TRUE : null;
+ Boolean myState = startElement == null ? Boolean.TRUE : null;
@Override
public void visitElement(PsiElement element) {