This commit is contained in:
Alexey Kudravtsev
2017-04-10 16:21:18 +03:00
parent 79398f482c
commit 34351a335f
8 changed files with 40 additions and 64 deletions
@@ -45,7 +45,7 @@ public interface PsiLanguageInjectionHost extends PsiElement {
/**
* Update the host element using the provided text of the injected file. It may be required to escape characters from {@code text}
* in accordance with the host language syntax. The implementation may delegate to {@link com.intellij.psi.ElementManipulators#handleContentChange(PsiElement, String)}
* in accordance with the host language syntax. The implementation may delegate to {@link ElementManipulators#handleContentChange(PsiElement, String)}
* if {@link com.intellij.psi.ElementManipulator} implementation is registered for this element class
* @param text text of the injected file
* @return the updated instance
@@ -59,6 +59,7 @@ public interface PsiLanguageInjectionHost extends PsiElement {
LiteralTextEscaper<? extends PsiLanguageInjectionHost> createLiteralTextEscaper();
@FunctionalInterface
interface InjectedPsiVisitor {
void visit(@NotNull PsiFile injectedPsi, @NotNull List<Shred> places);
}
@@ -122,16 +122,13 @@ class InjectedSelfElementInfo extends SmartPointerElementInfo {
@NotNull final TextRange rangeInHostFile) {
final PsiDocumentManagerBase docManager = (PsiDocumentManagerBase)PsiDocumentManager.getInstance(getProject());
final PsiFile[] result = {null};
final PsiLanguageInjectionHost.InjectedPsiVisitor visitor = new PsiLanguageInjectionHost.InjectedPsiVisitor() {
@Override
public void visit(@NotNull PsiFile injectedPsi, @NotNull List<PsiLanguageInjectionHost.Shred> places) {
Document document = docManager.getDocument(injectedPsi);
if (document instanceof DocumentWindow) {
DocumentWindow window = (DocumentWindow)docManager.getLastCommittedDocument(document);
TextRange hostRange = window.injectedToHost(new TextRange(0, injectedPsi.getTextLength()));
if (hostRange.contains(rangeInHostFile)) {
result[0] = injectedPsi;
}
final PsiLanguageInjectionHost.InjectedPsiVisitor visitor = (injectedPsi, places) -> {
Document document = docManager.getDocument(injectedPsi);
if (document instanceof DocumentWindow) {
DocumentWindow window = (DocumentWindow)docManager.getLastCommittedDocument(document);
TextRange hostRange = window.injectedToHost(new TextRange(0, injectedPsi.getTextLength()));
if (hostRange.contains(rangeInHostFile)) {
result[0] = injectedPsi;
}
}
};
@@ -142,7 +139,7 @@ class InjectedSelfElementInfo extends SmartPointerElementInfo {
for (DocumentWindow documentWindow : InjectedLanguageManager.getInstance(getProject()).getCachedInjectedDocuments(hostFile)) {
PsiFile injected = documentManager.getPsiFile(documentWindow);
if (injected != null) {
visitor.visit(injected, Collections.<PsiLanguageInjectionHost.Shred>emptyList());
visitor.visit(injected, Collections.emptyList());
}
}
}
@@ -151,7 +148,7 @@ class InjectedSelfElementInfo extends SmartPointerElementInfo {
if (injected != null) {
for (Pair<PsiElement, TextRange> pair : injected) {
PsiFile injectedFile = pair.first.getContainingFile();
visitor.visit(injectedFile, ContainerUtil.<PsiLanguageInjectionHost.Shred>emptyList());
visitor.visit(injectedFile, ContainerUtil.emptyList());
}
}
}
@@ -162,7 +159,7 @@ class InjectedSelfElementInfo extends SmartPointerElementInfo {
@Override
public boolean pointsToTheSameElementAs(@NotNull SmartPointerElementInfo other) {
if (getClass() != other.getClass()) return false;
if (!(((InjectedSelfElementInfo)other).myHostContext).equals(myHostContext)) return false;
if (!((InjectedSelfElementInfo)other).myHostContext.equals(myHostContext)) return false;
SmartPointerElementInfo myElementInfo = ((SmartPsiElementPointerImpl)myInjectedFileRangeInHostFile).getElementInfo();
SmartPointerElementInfo oElementInfo = ((SmartPsiElementPointerImpl)((InjectedSelfElementInfo)other).myInjectedFileRangeInHostFile).getElementInfo();
return myElementInfo.pointsToTheSameElementAs(oElementInfo);
@@ -27,13 +27,13 @@ import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
public class ClassMapCachingNulls<T> {
class ClassMapCachingNulls<T> {
private final Map<Class, T[]> myBackingMap;
private final T[] myEmptyArray;
private final List<T> myOrderingArray;
private final Map<Class, T[]> myMap = ContainerUtil.newConcurrentMap();
public ClassMapCachingNulls(@NotNull Map<Class, T[]> backingMap, T[] emptyArray, @NotNull List<T> orderingArray) {
ClassMapCachingNulls(@NotNull Map<Class, T[]> backingMap, T[] emptyArray, @NotNull List<T> orderingArray) {
myBackingMap = backingMap;
myEmptyArray = emptyArray;
myOrderingArray = orderingArray;
@@ -103,7 +103,7 @@ public class ClassMapCachingNulls<T> {
return value;
}
public Map<Class, T[]> getBackingMap() {
Map<Class, T[]> getBackingMap() {
return myBackingMap;
}
@@ -43,12 +43,7 @@ public class InjectedFileViewProvider extends SingleRootFileViewProvider impleme
private Project myProject;
private final Object myLock = new Object();
private final DocumentWindowImpl myDocumentWindow;
private static final ThreadLocal<Boolean> disabledTemporarily = new ThreadLocal<Boolean>(){
@Override
protected Boolean initialValue() {
return false;
}
};
private static final ThreadLocal<Boolean> disabledTemporarily = ThreadLocal.withInitial(() -> false);
private boolean myPatchingLeaves;
InjectedFileViewProvider(@NotNull PsiManager psiManager,
@@ -98,13 +93,10 @@ public class InjectedFileViewProvider extends SingleRootFileViewProvider impleme
PsiElement hostElementCopy = hostPsiFileCopy.getViewProvider().findElementAt(firstTextRange.getStartOffset(), hostFileLanguage);
assert hostElementCopy != null;
final Ref<FileViewProvider> provider = new Ref<>();
PsiLanguageInjectionHost.InjectedPsiVisitor visitor = new PsiLanguageInjectionHost.InjectedPsiVisitor() {
@Override
public void visit(@NotNull PsiFile injectedPsi, @NotNull List<PsiLanguageInjectionHost.Shred> places) {
Document document = documentManager.getCachedDocument(injectedPsi);
if (document instanceof DocumentWindowImpl && oldDocumentWindow.areRangesEqual((DocumentWindowImpl)document)) {
provider.set(injectedPsi.getViewProvider());
}
PsiLanguageInjectionHost.InjectedPsiVisitor visitor = (injectedPsi, places) -> {
Document document = documentManager.getCachedDocument(injectedPsi);
if (document instanceof DocumentWindowImpl && oldDocumentWindow.areRangesEqual((DocumentWindowImpl)document)) {
provider.set(injectedPsi.getViewProvider());
}
};
for (PsiElement current = hostElementCopy; current != null && current != hostPsiFileCopy; current = current.getParent()) {
@@ -179,7 +171,7 @@ public class InjectedFileViewProvider extends SingleRootFileViewProvider impleme
return isEventSystemEnabled();
}
public void performNonPhysically(Runnable runnable) {
void performNonPhysically(Runnable runnable) {
synchronized (myLock) {
disabledTemporarily.set(true);
try {
@@ -64,6 +64,7 @@ import java.util.*;
*/
public class InjectedLanguageManagerImpl extends InjectedLanguageManager implements Disposable {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.injected.InjectedLanguageManagerImpl");
@SuppressWarnings("RedundantStringConstructorCall")
static final Object ourInjectionPsiLock = new String("injectionPsiLock");
private final Project myProject;
private final DumbService myDumbService;
@@ -56,10 +56,7 @@ public class InjectedLanguageUtil {
// meaning: injected file text is probably incorrect
public static void forceInjectionOnElement(@NotNull PsiElement host) {
enumerate(host, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
@Override
public void visit(@NotNull PsiFile injectedPsi, @NotNull List<PsiLanguageInjectionHost.Shred> places) {
}
enumerate(host, (injectedPsi, places) -> {
});
}
@@ -408,18 +405,15 @@ public class InjectedLanguageUtil {
final int hostOffset,
@NotNull final PsiDocumentManager documentManager) {
final Ref<PsiElement> out = new Ref<>();
enumerate(element, hostFile, true, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
@Override
public void visit(@NotNull PsiFile injectedPsi, @NotNull List<PsiLanguageInjectionHost.Shred> places) {
for (PsiLanguageInjectionHost.Shred place : places) {
TextRange hostRange = place.getHost().getTextRange();
if (hostRange.cutOut(place.getRangeInsideHost()).grown(1).contains(hostOffset)) {
DocumentWindowImpl document = (DocumentWindowImpl)documentManager.getCachedDocument(injectedPsi);
if (document == null) return;
int injectedOffset = document.hostToInjected(hostOffset);
PsiElement injElement = injectedPsi.findElementAt(injectedOffset);
out.set(injElement == null ? injectedPsi : injElement);
}
enumerate(element, hostFile, true, (injectedPsi, places) -> {
for (PsiLanguageInjectionHost.Shred place : places) {
TextRange hostRange = place.getHost().getTextRange();
if (hostRange.cutOut(place.getRangeInsideHost()).grown(1).contains(hostOffset)) {
DocumentWindowImpl document = (DocumentWindowImpl)documentManager.getCachedDocument(injectedPsi);
if (document == null) return;
int injectedOffset = document.hostToInjected(hostOffset);
PsiElement injElement = injectedPsi.findElementAt(injectedOffset);
out.set(injElement == null ? injectedPsi : injElement);
}
}
});
@@ -439,7 +433,7 @@ public class InjectedLanguageUtil {
return injected;
}
public static void clearCachedInjectedFragmentsForFile(@NotNull PsiFile file) {
static void clearCachedInjectedFragmentsForFile(@NotNull PsiFile file) {
file.putUserData(INJECTED_DOCS_KEY, null);
}
@@ -527,12 +521,7 @@ public class InjectedLanguageUtil {
public static boolean hasInjections(@NotNull PsiLanguageInjectionHost host) {
if (!host.isPhysical()) return false;
final Ref<Boolean> result = Ref.create(false);
enumerate(host, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
@Override
public void visit(@NotNull final PsiFile injectedPsi, @NotNull final List<PsiLanguageInjectionHost.Shred> places) {
result.set(true);
}
});
enumerate(host, (injectedPsi, places) -> result.set(true));
return result.get().booleanValue();
}
@@ -602,12 +591,7 @@ public class InjectedLanguageUtil {
@Nullable
public static PsiElement findElementInInjected(@NotNull PsiLanguageInjectionHost injectionHost, final int offset) {
final Ref<PsiElement> ref = Ref.create();
enumerate(injectionHost, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
@Override
public void visit(@NotNull final PsiFile injectedPsi, @NotNull final List<PsiLanguageInjectionHost.Shred> places) {
ref.set(injectedPsi.findElementAt(offset - getInjectedStart(places)));
}
});
enumerate(injectionHost, (injectedPsi, places) -> ref.set(injectedPsi.findElementAt(offset - getInjectedStart(places))));
return ref.get();
}
@@ -496,7 +496,6 @@ public class MultiHostRegistrarImpl implements MultiHostRegistrar, ModificationT
Place shreds,
VirtualFileWindow virtualFile,
Project project) {
List<Trinity<IElementType, SmartPsiElementPointer<PsiLanguageInjectionHost>, TextRange>> tokens = new ArrayList<>(10);
SyntaxHighlighter syntaxHighlighter = SyntaxHighlighterFactory.getSyntaxHighlighter(language, project, (VirtualFile)virtualFile);
Lexer lexer = syntaxHighlighter.getHighlightingLexer();
lexer.start(outChars);
@@ -508,6 +507,7 @@ public class MultiHostRegistrarImpl implements MultiHostRegistrar, ModificationT
int suffixLength = 0;
TextRange rangeInsideHost = null;
int shredEndOffset = -1;
List<Trinity<IElementType, SmartPsiElementPointer<PsiLanguageInjectionHost>, TextRange>> tokens = new ArrayList<>(10);
for (IElementType tokenType = lexer.getTokenType(); tokenType != null; lexer.advance(), tokenType = lexer.getTokenType()) {
TextRange range = new ProperTextRange(lexer.getTokenStart(), lexer.getTokenEnd());
while (range != null && !range.isEmpty()) {
@@ -59,7 +59,7 @@ class ShredImpl implements PsiLanguageInjectionHost.Shred {
}
@NotNull
public SmartPsiElementPointer<PsiLanguageInjectionHost> getSmartPointer() {
SmartPsiElementPointer<PsiLanguageInjectionHost> getSmartPointer() {
return hostElementPointer;
}
@@ -88,13 +88,14 @@ class ShredImpl implements PsiLanguageInjectionHost.Shred {
}
@Override
@SuppressWarnings({"HardCodedStringLiteral"})
@SuppressWarnings("HardCodedStringLiteral")
public String toString() {
PsiLanguageInjectionHost host = getHost();
Segment hostRange = getHostRangeMarker();
return "Shred " + (host == null ? null : host.getTextRange()) + ": " + host +
" In host range: " + (hostRange != null ? "(" + hostRange.getStartOffset() + "," + hostRange.getEndOffset() + ");" : "invalid;") +
" PSI range: " + this.range;
" PSI range: " +
range;
}
@Override