diff options
Diffstat (limited to 'platform/lang-impl/src/com/intellij/psi/impl')
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; } |