use of com.intellij.injected.editor.DocumentWindow in project intellij-community by JetBrains.
the class LookupImpl method insertLookupInDocumentWindowIfNeeded.
private int insertLookupInDocumentWindowIfNeeded(int caretOffset, int prefix, String lookupString) {
DocumentWindow document = getInjectedDocument(caretOffset);
if (document == null)
return insertLookupInDocument(caretOffset, myEditor.getDocument(), prefix, lookupString);
PsiFile file = PsiDocumentManager.getInstance(myProject).getPsiFile(document);
int offset = document.hostToInjected(caretOffset);
int lookupStart = Math.min(offset, Math.max(offset - prefix, 0));
int diff = -1;
if (file != null) {
List<TextRange> ranges = InjectedLanguageManager.getInstance(myProject).intersectWithAllEditableFragments(file, TextRange.create(lookupStart, offset));
if (!ranges.isEmpty()) {
diff = ranges.get(0).getStartOffset() - lookupStart;
if (ranges.size() == 1 && diff == 0)
diff = -1;
}
}
if (diff == -1)
return insertLookupInDocument(caretOffset, myEditor.getDocument(), prefix, lookupString);
return document.injectedToHost(insertLookupInDocument(offset, document, prefix - diff, diff == 0 ? lookupString : lookupString.substring(diff)));
}
use of com.intellij.injected.editor.DocumentWindow in project intellij-community by JetBrains.
the class TypedHandler method injectedEditorIfCharTypedIsSignificant.
@NotNull
public static Editor injectedEditorIfCharTypedIsSignificant(final int charTyped, @NotNull Editor editor, @NotNull PsiFile oldFile) {
int offset = editor.getCaretModel().getOffset();
// and thus we can use its lexer to insert closing braces etc
for (DocumentWindow documentWindow : InjectedLanguageUtil.getCachedInjectedDocuments(oldFile)) {
if (documentWindow.isValid() && documentWindow.containsRange(offset, offset)) {
PsiFile injectedFile = PsiDocumentManager.getInstance(oldFile.getProject()).getPsiFile(documentWindow);
if (injectedFile != null) {
Editor injectedEditor = InjectedLanguageUtil.getInjectedEditorForInjectedFile(editor, injectedFile);
// IDEA-52375/WEB-9105 fix: last quote in editable fragment should be handled by outer language quote handler
TextRange hostRange = documentWindow.getHostRange(offset);
CharSequence sequence = editor.getDocument().getCharsSequence();
if (sequence.length() > offset && charTyped != Character.codePointAt(sequence, offset) || hostRange != null && hostRange.contains(offset)) {
return injectedEditor;
}
}
}
}
return editor;
}
use of com.intellij.injected.editor.DocumentWindow in project intellij-community by JetBrains.
the class InjectedFileViewProvider method clone.
@Override
public FileViewProvider clone() {
final DocumentWindow oldDocumentWindow = ((VirtualFileWindow) getVirtualFile()).getDocumentWindow();
Document hostDocument = oldDocumentWindow.getDelegate();
final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(getManager().getProject());
PsiFile hostFile = documentManager.getPsiFile(hostDocument);
Language language = getBaseLanguage();
PsiFile file = getPsi(language);
final Language hostFileLanguage = InjectedLanguageManager.getInstance(file.getProject()).getTopLevelFile(file).getLanguage();
PsiFile hostPsiFileCopy = (PsiFile) hostFile.copy();
Segment firstTextRange = oldDocumentWindow.getHostRanges()[0];
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());
}
}
};
for (PsiElement current = hostElementCopy; current != null && current != hostPsiFileCopy; current = current.getParent()) {
current.putUserData(LANGUAGE_FOR_INJECTED_COPY_KEY, language);
try {
InjectedLanguageUtil.enumerate(current, hostPsiFileCopy, false, visitor);
} finally {
current.putUserData(LANGUAGE_FOR_INJECTED_COPY_KEY, null);
}
if (provider.get() != null)
break;
}
return provider.get();
}
use of com.intellij.injected.editor.DocumentWindow in project intellij-community by JetBrains.
the class InjectedLanguageManagerImpl method startRunInjectors.
@Override
public void startRunInjectors(@NotNull final Document hostDocument, final boolean synchronously) {
if (myProject.isDisposed())
return;
if (!synchronously && ApplicationManager.getApplication().isWriteAccessAllowed())
return;
// use cached to avoid recreate PSI in alien project
final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myProject);
final PsiFile hostPsiFile = documentManager.getCachedPsiFile(hostDocument);
if (hostPsiFile == null)
return;
final ConcurrentList<DocumentWindow> injected = InjectedLanguageUtil.getCachedInjectedDocuments(hostPsiFile);
if (injected.isEmpty())
return;
if (myProgress.isCanceled()) {
myProgress = new DaemonProgressIndicator();
}
final Set<DocumentWindow> newDocuments = Collections.synchronizedSet(new THashSet<>());
final Processor<DocumentWindow> commitProcessor = documentWindow -> {
if (myProject.isDisposed())
return false;
ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
if (indicator != null && indicator.isCanceled())
return false;
if (documentManager.isUncommited(hostDocument) || !hostPsiFile.isValid())
return false;
InjectedLanguageUtil.enumerate(documentWindow, hostPsiFile, (injectedPsi, places) -> {
DocumentWindow newDocument = (DocumentWindow) injectedPsi.getViewProvider().getDocument();
if (newDocument != null) {
PsiDocumentManagerBase.checkConsistency(injectedPsi, newDocument);
newDocuments.add(newDocument);
}
});
return true;
};
final Runnable commitInjectionsRunnable = () -> {
if (myProgress.isCanceled())
return;
JobLauncher.getInstance().invokeConcurrentlyUnderProgress(new ArrayList<>(injected), myProgress, true, commitProcessor);
synchronized (ourInjectionPsiLock) {
injected.clear();
injected.addAll(newDocuments);
}
};
if (synchronously) {
if (Thread.holdsLock(PsiLock.LOCK)) {
// hack for the case when docCommit was called from within PSI modification, e.g. in formatter.
// we can't spawn threads to do injections there, otherwise a deadlock is imminent
ContainerUtil.process(new ArrayList<>(injected), commitProcessor);
} else {
commitInjectionsRunnable.run();
}
} else {
JobLauncher.getInstance().submitToJobThread(() -> ApplicationManagerEx.getApplicationEx().tryRunReadAction(commitInjectionsRunnable), null);
}
}
use of com.intellij.injected.editor.DocumentWindow in project intellij-community by JetBrains.
the class CodeFormatterFacade method doProcessRange.
private ASTNode doProcessRange(final ASTNode element, final int startOffset, final int endOffset, @Nullable RangeMarker rangeMarker) {
final PsiElement psiElement = SourceTreeToPsiMap.treeElementToPsi(element);
assert psiElement != null;
final PsiFile file = psiElement.getContainingFile();
final Document document = file.getViewProvider().getDocument();
PsiElement elementToFormat = document instanceof DocumentWindow ? InjectedLanguageManager.getInstance(file.getProject()).getTopLevelFile(file) : psiElement;
final PsiFile fileToFormat = elementToFormat.getContainingFile();
final FormattingModelBuilder builder = LanguageFormatting.INSTANCE.forContext(fileToFormat);
if (builder != null) {
if (rangeMarker == null && document != null && endOffset < document.getTextLength()) {
rangeMarker = document.createRangeMarker(startOffset, endOffset);
}
TextRange range = preprocess(element, TextRange.create(startOffset, endOffset));
if (document instanceof DocumentWindow) {
DocumentWindow documentWindow = (DocumentWindow) document;
range = documentWindow.injectedToHost(range);
}
//final SmartPsiElementPointer pointer = SmartPointerManager.getInstance(psiElement.getProject()).createSmartPsiElementPointer(psiElement);
final FormattingModel model = CoreFormatterUtil.buildModel(builder, elementToFormat, mySettings, FormattingMode.REFORMAT);
if (file.getTextLength() > 0) {
try {
FormatterEx.getInstanceEx().format(model, mySettings, mySettings.getIndentOptionsByFile(fileToFormat, range), new FormatTextRanges(range, true));
wrapLongLinesIfNecessary(file, document, startOffset, endOffset);
} catch (IncorrectOperationException e) {
LOG.error(e);
}
}
if (!psiElement.isValid()) {
if (rangeMarker != null) {
final PsiElement at = file.findElementAt(rangeMarker.getStartOffset());
final PsiElement result = PsiTreeUtil.getParentOfType(at, psiElement.getClass(), false);
assert result != null;
rangeMarker.dispose();
return result.getNode();
} else {
assert false;
}
}
// return SourceTreeToPsiMap.psiElementToTree(pointer.getElement());
}
if (rangeMarker != null) {
rangeMarker.dispose();
}
return element;
}
Aggregations