summaryrefslogtreecommitdiff
path: root/platform/lang-impl/src/com/intellij/psi/impl
diff options
context:
space:
mode:
Diffstat (limited to 'platform/lang-impl/src/com/intellij/psi/impl')
-rw-r--r--platform/lang-impl/src/com/intellij/psi/impl/DocumentCommitThread.java95
-rw-r--r--platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java18
-rw-r--r--platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeFormatterFacade.java5
-rw-r--r--platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java2
-rw-r--r--platform/lang-impl/src/com/intellij/psi/impl/source/tree/PsiCommentImpl.java45
-rw-r--r--platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/CommentLiteralEscaper.java59
-rw-r--r--platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedFileViewProvider.java2
-rw-r--r--platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java53
-rw-r--r--platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/MultiHostRegistrarImpl.java2
-rw-r--r--platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/Place.java6
-rw-r--r--platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/ShredImpl.java1
11 files changed, 135 insertions, 153 deletions
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/DocumentCommitThread.java b/platform/lang-impl/src/com/intellij/psi/impl/DocumentCommitThread.java
index c8793c085a58..32a2e38384d9 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/DocumentCommitThread.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/DocumentCommitThread.java
@@ -18,8 +18,8 @@ package com.intellij.psi.impl;
import com.intellij.codeInsight.daemon.impl.DaemonProgressIndicator;
import com.intellij.ide.startup.impl.StartupManagerImpl;
import com.intellij.openapi.Disposable;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.application.ex.ApplicationManagerEx;
+import com.intellij.openapi.application.ApplicationAdapter;
+import com.intellij.openapi.application.ex.ApplicationEx;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
@@ -54,17 +54,44 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run
private final Queue<CommitTask> documentsToCommit = new Queue<CommitTask>(10);
private final List<CommitTask> documentsToApplyInEDT = new ArrayList<CommitTask>(10); // guarded by documentsToCommit
+ private final ApplicationEx myApplication;
private volatile boolean isDisposed;
private CommitTask currentTask; // guarded by documentsToCommit
private volatile boolean threadFinished;
- private volatile boolean myEnabled = true; // true if we can do commits. set to false temporarily during the write action.
+ private volatile boolean myEnabled; // true if we can do commits. set to false temporarily during the write action.
public static DocumentCommitThread getInstance() {
return ServiceManager.getService(DocumentCommitThread.class);
}
- public DocumentCommitThread() {
- log("Starting thread",null, false);
+ public DocumentCommitThread(final ApplicationEx application) {
+ myApplication = application;
+ // install listener in EDT to avoid missing events in case we are inside write action right now
+ application.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ application.addApplicationListener(new ApplicationAdapter() {
+ private int runningWriteActions;
+
+ @Override
+ public void beforeWriteActionStart(Object action) {
+ if (runningWriteActions++ == 0) {
+ disable("Write action started: " + action);
+ }
+ }
+
+ @Override
+ public void writeActionFinished(Object action) {
+ if (--runningWriteActions == 0) {
+ enable("Write action finished: " + action);
+ }
+ }
+ }, DocumentCommitThread.this);
+
+ enable("Listener installed, started");
+ }
+ });
+ log("Starting thread", null, false);
new Thread(this, "Document commit thread").start();
}
@@ -88,14 +115,14 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run
}
}
- public void disable(@NonNls Object reason) {
+ private void disable(@NonNls Object reason) {
// write action has just started, all commits are useless
cancel(reason);
myEnabled = false;
log("Disabled", null, false, reason);
}
- public void enable(Object reason) {
+ private void enable(@NonNls Object reason) {
myEnabled = true;
wakeUpQueue();
log("Enabled", null, false, reason);
@@ -107,7 +134,7 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run
}
}
- private void cancel(@NonNls Object reason) {
+ private void cancel(@NonNls @NotNull Object reason) {
startNewTask(null, reason);
}
@@ -126,7 +153,7 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run
doQueue(project, document, reason);
}
- private void doQueue(Project project, Document document, Object reason) {
+ private void doQueue(@NotNull Project project, @NotNull Document document, @NotNull Object reason) {
synchronized (documentsToCommit) {
ProgressIndicator indicator = new DaemonProgressIndicator();
CommitTask newTask = new CommitTask(document, project, indicator, reason);
@@ -193,7 +220,6 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run
public void clearQueue() {
cancelAll();
log.setLength(0);
- disable("end of test");
wakeUpQueue();
}
@@ -303,9 +329,9 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run
}
if (success) {
- assert !ApplicationManager.getApplication().isDispatchThread();
+ assert !myApplication.isDispatchThread();
UIUtil.invokeLaterIfNeeded(finishRunnable);
- log("Invoked later finishRunnable", task, false, success, finishRunnable, indicator);
+ log("Invoked later finishRunnable", task, false, finishRunnable, indicator);
}
}
catch (ProcessCanceledException e) {
@@ -334,7 +360,7 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run
@Override
public void commitSynchronously(@NotNull Document document, @NotNull Project project) {
assert !isDisposed;
- ApplicationManager.getApplication().assertWriteAccessAllowed();
+ myApplication.assertWriteAccessAllowed();
if (!project.isInitialized() && !project.isDefault()) {
@NonNls String s = project + "; Disposed: "+project.isDisposed()+"; Open: "+project.isOpen();
@@ -380,7 +406,7 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run
return new ProgressIndicatorBase();
}
- private void startNewTask(CommitTask task, Object reason) {
+ private void startNewTask(@Nullable CommitTask task, @NotNull Object reason) {
synchronized (documentsToCommit) { // sync to prevent overwriting
CommitTask cur = currentTask;
if (cur != null) {
@@ -388,19 +414,19 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run
}
currentTask = task;
}
+ log("new task started", task, false, reason);
}
// returns finish commit Runnable (to be invoked later in EDT), or null on failure
@Nullable
- private Runnable commitUnderProgress(@NotNull final CommitTask task,
- final boolean synchronously) {
+ private Runnable commitUnderProgress(@NotNull final CommitTask task, final boolean synchronously) {
final Project project = task.project;
final Document document = task.document;
final List<Processor<Document>> finishProcessors = new SmartList<Processor<Document>>();
Runnable runnable = new Runnable() {
@Override
public void run() {
- ApplicationManager.getApplication().assertReadAccessAllowed();
+ myApplication.assertReadAccessAllowed();
if (project.isDisposed()) return;
final PsiDocumentManagerImpl documentManager = (PsiDocumentManagerImpl)PsiDocumentManager.getInstance(project);
@@ -424,14 +450,12 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run
}
};
if (synchronously) {
- ApplicationManager.getApplication().assertWriteAccessAllowed();
+ myApplication.assertWriteAccessAllowed();
runnable.run();
}
- else {
- if (!ApplicationManagerEx.getApplicationEx().tryRunReadAction(runnable)) {
- log("Could not start read action", task, synchronously, ApplicationManager.getApplication().isReadAccessAllowed(), Thread.currentThread());
- return null;
- }
+ else if (!myApplication.tryRunReadAction(runnable)) {
+ log("Could not start read action", task, synchronously, myApplication.isReadAccessAllowed(), Thread.currentThread());
+ return null;
}
boolean canceled = task.indicator.isCanceled();
@@ -443,7 +467,7 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run
Runnable finishRunnable = new Runnable() {
@Override
public void run() {
- ApplicationManager.getApplication().assertIsDispatchThread();
+ myApplication.assertIsDispatchThread();
Project project = task.project;
if (project.isDisposed()) return;
@@ -525,4 +549,27 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run
}
return result[0];
}
+
+ @TestOnly
+ boolean isEnabled() {
+ return myEnabled;
+ }
+
+ @TestOnly
+ public void waitUntilAllCommitted(long timeout) throws InterruptedException {
+ if (!myEnabled) {
+ throw new IllegalStateException("DocumentCommitThread is disabled");
+ }
+ int attempts = 0;
+ int delay = 100;
+ synchronized (documentsToCommit) {
+ while(!documentsToCommit.isEmpty() || currentTask != null) {
+ documentsToCommit.wait(delay);
+ if (delay * attempts > timeout) {
+ throw new RuntimeException("timeout");
+ }
+ attempts++;
+ }
+ }
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java
index 63b8a6af86e1..16926b18b834 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java
@@ -19,7 +19,6 @@ package com.intellij.psi.impl;
import com.intellij.AppTopics;
import com.intellij.injected.editor.DocumentWindow;
import com.intellij.injected.editor.EditorWindowImpl;
-import com.intellij.openapi.application.ApplicationAdapter;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.SettingsSavingComponent;
import com.intellij.openapi.editor.Document;
@@ -33,7 +32,10 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectLocator;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.*;
+import com.intellij.psi.FileViewProvider;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiManager;
+import com.intellij.psi.SmartPointerManager;
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
import com.intellij.util.FileContentUtil;
import com.intellij.util.Processor;
@@ -79,18 +81,6 @@ public class PsiDocumentManagerImpl extends PsiDocumentManagerBase implements Se
documentCommitThread.queueCommit(project, doc, "Bulk update finished");
}
});
- ApplicationManager.getApplication().addApplicationListener(new ApplicationAdapter() {
- @Override
- public void beforeWriteActionStart(Object action) {
- documentCommitThread.disable("Write action started: " + action);
- }
-
- @Override
- public void writeActionFinished(Object action) {
- documentCommitThread.enable("Write action finished: " + action);
- }
- }, project);
- documentCommitThread.enable("project open");
}
@Nullable
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeFormatterFacade.java b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeFormatterFacade.java
index fa1dd9e86b4a..c7b9bf3a3adf 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeFormatterFacade.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeFormatterFacade.java
@@ -391,14 +391,15 @@ public class CodeFormatterFacade {
/**
- * Inspects all lines of the given document and wraps all of them that exceed {@link CodeStyleSettings#RIGHT_MARGIN right margin}.
+ * Inspects all lines of the given document and wraps all of them that exceed {@link CodeStyleSettings#getRightMargin(com.intellij.lang.Language)}
+ * right margin}.
* <p/>
* I.e. the algorithm is to do the following for every line:
* <p/>
* <pre>
* <ol>
* <li>
- * Check if the line exceeds {@link CodeStyleSettings#RIGHT_MARGIN right margin}. Go to the next line in the case of
+ * Check if the line exceeds {@link CodeStyleSettings#getRightMargin(com.intellij.lang.Language)} right margin}. Go to the next line in the case of
* negative answer;
* </li>
* <li>Determine line wrap position; </li>
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java
index 767152fc1e2b..d51ef1216a59 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java
@@ -181,7 +181,7 @@ public class CodeStyleManagerImpl extends CodeStyleManager {
transformAllChildren(treeElement);
final CodeFormatterFacade codeFormatter = new CodeFormatterFacade(getSettings(), file.getLanguage());
- LOG.assertTrue(file.isValid());
+ LOG.assertTrue(file.isValid(), "File name: " + file.getName() + " , class: " + file.getClass().getSimpleName());
if (editor == null) {
editor = PsiUtilBase.findEditor(file);
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/PsiCommentImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/PsiCommentImpl.java
deleted file mode 100644
index d4e1b0d52f53..000000000000
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/PsiCommentImpl.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2000-2009 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.source.tree;
-
-import com.intellij.psi.LiteralTextEscaper;
-import com.intellij.psi.PsiLanguageInjectionHost;
-import com.intellij.psi.impl.source.tree.injected.CommentLiteralEscaper;
-import com.intellij.psi.tree.IElementType;
-import org.jetbrains.annotations.NotNull;
-
-public class PsiCommentImpl extends PsiCoreCommentImpl implements PsiLanguageInjectionHost {
- public PsiCommentImpl(IElementType type, CharSequence text) {
- super(type, text);
- }
-
- @Override
- public boolean isValidHost() {
- return true;
- }
-
- @Override
- public PsiLanguageInjectionHost updateText(@NotNull final String text) {
- return (PsiCommentImpl)replaceWithText(text);
- }
-
- @Override
- @NotNull
- public LiteralTextEscaper<PsiCommentImpl> createLiteralTextEscaper() {
- return new CommentLiteralEscaper(this);
- }
-}
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/CommentLiteralEscaper.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/CommentLiteralEscaper.java
deleted file mode 100644
index c6399e30b5f6..000000000000
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/CommentLiteralEscaper.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2000-2009 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.source.tree.injected;
-
-import com.intellij.openapi.util.ProperTextRange;
-import com.intellij.lang.CodeDocumentationAwareCommenter;
-import com.intellij.lang.Commenter;
-import com.intellij.lang.LanguageCommenters;
-import com.intellij.openapi.util.TextRange;
-import com.intellij.psi.LiteralTextEscaper;
-import com.intellij.psi.impl.source.tree.PsiCommentImpl;
-import org.jetbrains.annotations.NotNull;
-
-/**
- * @author cdr
-*/
-public class CommentLiteralEscaper extends LiteralTextEscaper<PsiCommentImpl> {
- public CommentLiteralEscaper(PsiCommentImpl host) {
- super(host);
- }
-
- @Override
- public boolean decode(@NotNull final TextRange rangeInsideHost, @NotNull StringBuilder outChars) {
- ProperTextRange.assertProperRange(rangeInsideHost);
- outChars.append(myHost.getText(), rangeInsideHost.getStartOffset(), rangeInsideHost.getEndOffset());
- return true;
- }
-
- @Override
- public int getOffsetInHost(int offsetInDecoded, @NotNull final TextRange rangeInsideHost) {
- int offset = offsetInDecoded + rangeInsideHost.getStartOffset();
- if (offset < rangeInsideHost.getStartOffset()) offset = rangeInsideHost.getStartOffset();
- if (offset > rangeInsideHost.getEndOffset()) offset = rangeInsideHost.getEndOffset();
- return offset;
- }
-
- @Override
- public boolean isOneLine() {
- final Commenter commenter = LanguageCommenters.INSTANCE.forLanguage(myHost.getLanguage());
- if (commenter instanceof CodeDocumentationAwareCommenter) {
- return myHost.getTokenType() == ((CodeDocumentationAwareCommenter) commenter).getLineCommentTokenType();
- }
- return false;
- }
-} \ No newline at end of file
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedFileViewProvider.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedFileViewProvider.java
index f4a6d576e6b8..58a9463b755d 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedFileViewProvider.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedFileViewProvider.java
@@ -61,7 +61,7 @@ public class InjectedFileViewProvider extends SingleRootFileViewProvider impleme
@NotNull Language language) {
super(psiManager, (VirtualFile)virtualFile, true, language);
myDocumentWindow = documentWindow;
- myProject = documentWindow.getShreds().get(0).getHost().getProject();
+ myProject = documentWindow.getShreds().getHostPointer().getProject();
}
@Override
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 fdc434d8d11a..647ace567d5d 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
@@ -24,7 +24,6 @@ import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.editor.impl.EditorImpl;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
@@ -38,6 +37,7 @@ import com.intellij.psi.impl.PsiParameterizedCachedValue;
import com.intellij.psi.impl.source.DummyHolder;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.*;
+import com.intellij.testFramework.LightVirtualFile;
import com.intellij.util.containers.ConcurrentList;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
@@ -93,7 +93,12 @@ public class InjectedLanguageUtil {
public static Place getShreds(@NotNull FileViewProvider viewProvider) {
if (!(viewProvider instanceof InjectedFileViewProvider)) return null;
InjectedFileViewProvider myFileViewProvider = (InjectedFileViewProvider)viewProvider;
- return ((DocumentWindowImpl)myFileViewProvider.getDocument()).getShreds();
+ return getShreds(myFileViewProvider.getDocument());
+ }
+
+ @NotNull
+ public static Place getShreds(@NotNull DocumentWindow document) {
+ return ((DocumentWindowImpl)document).getShreds();
}
public static void enumerate(@NotNull DocumentWindow documentWindow,
@@ -162,6 +167,13 @@ public class InjectedLanguageUtil {
return getEditorForInjectedLanguageNoCommit(editor, file, offset);
}
+ public static Editor getEditorForInjectedLanguageNoCommit(@Nullable Editor editor, @Nullable Caret caret, @Nullable PsiFile file) {
+ if (editor == null || file == null || editor instanceof EditorWindow || caret == null) return editor;
+
+ PsiFile injectedFile = findInjectedPsiNoCommit(file, caret.getOffset());
+ return getInjectedEditorForInjectedFile(editor, caret, injectedFile);
+ }
+
public static Caret getCaretForInjectedLanguageNoCommit(@Nullable Caret caret, @Nullable PsiFile file) {
if (caret == null || file == null || caret instanceof InjectedCaret) return caret;
@@ -212,17 +224,21 @@ public class InjectedLanguageUtil {
@NotNull
public static Editor getInjectedEditorForInjectedFile(@NotNull Editor hostEditor, @Nullable final PsiFile injectedFile) {
+ return getInjectedEditorForInjectedFile(hostEditor, hostEditor.getCaretModel().getCurrentCaret(), injectedFile);
+ }
+
+ @NotNull
+ public static Editor getInjectedEditorForInjectedFile(@NotNull Editor hostEditor, @NotNull Caret hostCaret, @Nullable final PsiFile injectedFile) {
if (injectedFile == null || hostEditor instanceof EditorWindow || hostEditor.isDisposed()) return hostEditor;
Project project = hostEditor.getProject();
if (project == null) project = injectedFile.getProject();
Document document = PsiDocumentManager.getInstance(project).getDocument(injectedFile);
if (!(document instanceof DocumentWindowImpl)) return hostEditor;
DocumentWindowImpl documentWindow = (DocumentWindowImpl)document;
- SelectionModel selectionModel = hostEditor.getSelectionModel();
- if (selectionModel.hasSelection()) {
- int selstart = selectionModel.getSelectionStart();
+ if (hostCaret.hasSelection()) {
+ int selstart = hostCaret.getSelectionStart();
if (selstart != -1) {
- int selend = Math.max(selstart, selectionModel.getSelectionEnd());
+ int selend = Math.max(selstart, hostCaret.getSelectionEnd());
if (!documentWindow.containsRange(selstart, selend)) {
// selection spreads out the injected editor range
return hostEditor;
@@ -573,4 +589,29 @@ public class InjectedLanguageUtil {
});
return ref.get();
}
+
+ @Nullable
+ public static PsiLanguageInjectionHost findInjectionHost(@Nullable PsiElement psi) {
+ if (psi == null) return null;
+ PsiFile containingFile = psi.getContainingFile().getOriginalFile(); // * formatting
+ PsiElement fileContext = containingFile.getContext(); // * quick-edit-handler
+ if (fileContext instanceof PsiLanguageInjectionHost) return (PsiLanguageInjectionHost)fileContext;
+ Place shreds = getShreds(containingFile.getViewProvider()); // * injection-registrar
+ if (shreds == null) {
+ VirtualFile virtualFile = PsiUtilCore.getVirtualFile(containingFile);
+ if (virtualFile instanceof LightVirtualFile) {
+ virtualFile = ((LightVirtualFile)virtualFile).getOriginalFile(); // * dynamic files-from-text
+ }
+ if (virtualFile instanceof VirtualFileWindow) {
+ shreds = getShreds(((VirtualFileWindow)virtualFile).getDocumentWindow());
+ }
+ }
+ return shreds != null ? shreds.getHostPointer().getElement() : null;
+ }
+
+ @Nullable
+ public static PsiLanguageInjectionHost findInjectionHost(@Nullable VirtualFile virtualFile) {
+ return virtualFile instanceof VirtualFileWindow ?
+ getShreds(((VirtualFileWindow)virtualFile).getDocumentWindow()).getHostPointer().getElement() : null;
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/MultiHostRegistrarImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/MultiHostRegistrarImpl.java
index 183af7374072..e520eea741be 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/MultiHostRegistrarImpl.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/MultiHostRegistrarImpl.java
@@ -389,7 +389,7 @@ public class MultiHostRegistrarImpl implements MultiHostRegistrar, ModificationT
"\nLeaf texts concatenated:'"+ patcher.catLeafs +"';" +
"\nFile root: "+parsedNode+
"\nLanguage: "+parsedNode.getPsi().getLanguage()+
- "\nHost file: "+ shreds.get(0).getHost().getContainingFile().getVirtualFile()
+ "\nHost file: "+ shreds.getHostPointer().getVirtualFile()
;
DebugUtil.startPsiModification("injection leaf patching");
try {
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/Place.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/Place.java
index afaf499b9bb9..f6be385077c2 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/Place.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/Place.java
@@ -17,6 +17,7 @@
package com.intellij.psi.impl.source.tree.injected;
import com.intellij.psi.PsiLanguageInjectionHost;
+import com.intellij.psi.SmartPsiElementPointer;
import com.intellij.util.SmartList;
import org.jetbrains.annotations.NotNull;
@@ -30,6 +31,11 @@ public class Place extends SmartList<PsiLanguageInjectionHost.Shred> {
super(shreds);
}
+ @NotNull
+ public SmartPsiElementPointer<PsiLanguageInjectionHost> getHostPointer() {
+ return ((ShredImpl)get(0)).getSmartPointer();
+ }
+
public boolean isValid() {
for (PsiLanguageInjectionHost.Shred shred : this) {
if (!shred.isValid()) {
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/ShredImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/ShredImpl.java
index aea41ab16f72..5c60a1c2254f 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/ShredImpl.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/ShredImpl.java
@@ -45,6 +45,7 @@ class ShredImpl implements PsiLanguageInjectionHost.Shred {
assert relevantRangeInHost.isValid();
}
+ @NotNull
public SmartPsiElementPointer<PsiLanguageInjectionHost> getSmartPointer() {
return hostElementPointer;
}