summaryrefslogtreecommitdiff
path: root/platform/lang-impl/src/com/intellij/psi
diff options
context:
space:
mode:
Diffstat (limited to 'platform/lang-impl/src/com/intellij/psi')
-rw-r--r--platform/lang-impl/src/com/intellij/psi/impl/search/LexerEditorHighlighterLexer.java133
-rw-r--r--platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerRunnable.java4
-rw-r--r--platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java71
3 files changed, 58 insertions, 150 deletions
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/search/LexerEditorHighlighterLexer.java b/platform/lang-impl/src/com/intellij/psi/impl/search/LexerEditorHighlighterLexer.java
deleted file mode 100644
index 2add3ed1b3c5..000000000000
--- a/platform/lang-impl/src/com/intellij/psi/impl/search/LexerEditorHighlighterLexer.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright 2000-2013 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.psi.impl.search;
-
-import com.intellij.lexer.Lexer;
-import com.intellij.lexer.LexerBase;
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.editor.highlighter.EditorHighlighter;
-import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory;
-import com.intellij.openapi.editor.highlighter.HighlighterIterator;
-import com.intellij.openapi.editor.impl.EditorHighlighterCache;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.PsiDocumentManager;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.PsiManager;
-import com.intellij.psi.impl.cache.impl.id.PlatformIdTableBuilding;
-import com.intellij.psi.tree.IElementType;
-import com.intellij.util.text.CharSequenceSubSequence;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-/**
-* @author Sergey Evdokimov
-*/
-public class LexerEditorHighlighterLexer extends LexerBase {
- private HighlighterIterator iterator;
- private CharSequence buffer;
- private int start;
- private int end;
- private final EditorHighlighter myHighlighter;
- private final boolean myAlreadyInitializedHighlighter;
-
- public LexerEditorHighlighterLexer(final EditorHighlighter highlighter, boolean alreadyInitializedHighlighter) {
- myHighlighter = highlighter;
- myAlreadyInitializedHighlighter = alreadyInitializedHighlighter;
- }
-
- @Nullable
- public static Lexer getLexerBasedOnLexerHighlighter(CharSequence text, VirtualFile virtualFile, Project project) {
- EditorHighlighter highlighter = null;
-
- PsiFile psiFile = virtualFile != null ? PsiManager.getInstance(project).findFile(virtualFile) : null;
- final Document document = psiFile != null ? PsiDocumentManager.getInstance(project).getDocument(psiFile) : null;
- final EditorHighlighter cachedEditorHighlighter;
- boolean alreadyInitializedHighlighter = false;
-
- if (document != null &&
- (cachedEditorHighlighter = EditorHighlighterCache.getEditorHighlighterForCachesBuilding(document)) != null &&
- PlatformIdTableBuilding.checkCanUseCachedEditorHighlighter(text, cachedEditorHighlighter)) {
- highlighter = cachedEditorHighlighter;
- alreadyInitializedHighlighter = true;
- }
- else if (virtualFile != null) {
- highlighter = EditorHighlighterFactory.getInstance().createEditorHighlighter(project, virtualFile);
- }
-
- if (highlighter != null) {
- return new LexerEditorHighlighterLexer(highlighter, alreadyInitializedHighlighter);
- }
- return null;
- }
-
- @Override
- public void start(@NotNull CharSequence buffer, int startOffset, int endOffset, int state) {
- if (myAlreadyInitializedHighlighter) {
- this.buffer = buffer;
- start = startOffset;
- end = endOffset;
- } else {
- myHighlighter.setText(new CharSequenceSubSequence(this.buffer = buffer, start = startOffset, end = endOffset));
- }
- iterator = myHighlighter.createIterator(0);
- }
-
- public void resetPosition(int offset) {
- iterator = myHighlighter.createIterator(offset);
- }
-
- @Override
- public int getState() {
- return 0;
- }
-
- @Override
- public IElementType getTokenType() {
- if (iterator.atEnd()) return null;
- return iterator.getTokenType();
- }
-
- @Override
- public int getTokenStart() {
- return iterator.getStart();
- }
-
- @Override
- public int getTokenEnd() {
- return iterator.getEnd();
- }
-
- @Override
- public void advance() {
- iterator.advance();
- }
-
- @NotNull
- @Override
- public CharSequence getBufferSequence() {
- return buffer;
- }
-
- @Override
- public int getBufferEnd() {
- return end;
- }
-
- public HighlighterIterator getHighlighterIterator() {
- return iterator;
- }
-}
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerRunnable.java b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerRunnable.java
index 1b17faf21905..42dcb46c7ac0 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerRunnable.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerRunnable.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * Copyright 2000-2014 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.
@@ -149,7 +149,7 @@ abstract class CodeStyleManagerRunnable<T> {
SourceTreeToPsiMap.psiElementToTree(CodeStyleManagerImpl.findElementInTreeWithFormatterEnabled(file, offset));
if (elementAtOffset == null) {
int significantRangeStart = CharArrayUtil.shiftBackward(file.getText(), offset - 1, "\r\t ");
- return new TextRange(significantRangeStart, offset);
+ return new TextRange(Math.max(significantRangeStart, 0), offset);
}
final FormattingModelBuilder builder = LanguageFormatting.INSTANCE.forContext(file);
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) {