use of com.intellij.injected.editor.DocumentWindow in project intellij-community by JetBrains.
the class CodeFormatterFacade method processText.
public void processText(PsiFile file, final FormatTextRanges ranges, boolean doPostponedFormatting) {
final Project project = file.getProject();
Document document = PsiDocumentManager.getInstance(project).getDocument(file);
final List<FormatTextRange> textRanges = ranges.getRanges();
if (document instanceof DocumentWindow) {
file = InjectedLanguageManager.getInstance(file.getProject()).getTopLevelFile(file);
final DocumentWindow documentWindow = (DocumentWindow) document;
for (FormatTextRange range : textRanges) {
range.setTextRange(documentWindow.injectedToHost(range.getTextRange()));
}
document = documentWindow.getDelegate();
}
final FormattingModelBuilder builder = LanguageFormatting.INSTANCE.forContext(file);
final Language contextLanguage = file.getLanguage();
if (builder != null) {
if (file.getTextLength() > 0) {
LOG.assertTrue(document != null);
try {
final FileViewProvider viewProvider = file.getViewProvider();
final PsiElement startElement = viewProvider.findElementAt(textRanges.get(0).getTextRange().getStartOffset(), contextLanguage);
final PsiElement endElement = viewProvider.findElementAt(textRanges.get(textRanges.size() - 1).getTextRange().getEndOffset() - 1, contextLanguage);
final PsiElement commonParent = startElement != null && endElement != null ? PsiTreeUtil.findCommonParent(startElement, endElement) : null;
ASTNode node = null;
if (commonParent != null) {
node = commonParent.getNode();
}
if (node == null) {
node = file.getNode();
}
for (FormatTextRange range : ranges.getRanges()) {
TextRange rangeToUse = preprocess(node, range.getTextRange());
range.setTextRange(rangeToUse);
}
if (doPostponedFormatting) {
RangeMarker[] markers = new RangeMarker[textRanges.size()];
int i = 0;
for (FormatTextRange range : textRanges) {
TextRange textRange = range.getTextRange();
int start = textRange.getStartOffset();
int end = textRange.getEndOffset();
if (start >= 0 && end > start && end <= document.getTextLength()) {
markers[i] = document.createRangeMarker(textRange);
markers[i].setGreedyToLeft(true);
markers[i].setGreedyToRight(true);
i++;
}
}
final PostprocessReformattingAspect component = file.getProject().getComponent(PostprocessReformattingAspect.class);
FormattingProgressTask.FORMATTING_CANCELLED_FLAG.set(false);
component.doPostponedFormatting(file.getViewProvider());
i = 0;
for (FormatTextRange range : textRanges) {
RangeMarker marker = markers[i];
if (marker != null) {
range.setTextRange(TextRange.create(marker));
marker.dispose();
}
i++;
}
}
if (FormattingProgressTask.FORMATTING_CANCELLED_FLAG.get()) {
return;
}
final FormattingModel originalModel = CoreFormatterUtil.buildModel(builder, file, mySettings, FormattingMode.REFORMAT);
final FormattingModel model = new DocumentBasedFormattingModel(originalModel, document, project, mySettings, file.getFileType(), file);
FormatterEx formatter = FormatterEx.getInstanceEx();
if (CodeStyleManager.getInstance(project).isSequentialProcessingAllowed()) {
formatter.setProgressTask(new FormattingProgressTask(project, file, document));
}
CommonCodeStyleSettings.IndentOptions indentOptions = mySettings.getIndentOptionsByFile(file, textRanges.size() == 1 ? textRanges.get(0).getTextRange() : null);
formatter.format(model, mySettings, indentOptions, ranges, myReformatContext);
for (FormatTextRange range : textRanges) {
TextRange textRange = range.getTextRange();
wrapLongLinesIfNecessary(file, document, textRange.getStartOffset(), textRange.getEndOffset());
}
} catch (IncorrectOperationException e) {
LOG.error(e);
}
}
}
}
use of com.intellij.injected.editor.DocumentWindow in project intellij-community by JetBrains.
the class CodeFormatterFacade method preprocess.
private TextRange preprocess(@NotNull final ASTNode node, @NotNull TextRange range) {
TextRange result = range;
PsiElement psi = node.getPsi();
if (!psi.isValid()) {
return result;
}
PsiFile file = psi.getContainingFile();
// We use a set here because we encountered a situation when more than one PSI leaf points to the same injected fragment
// (at least for sql injected into sql).
final LinkedHashSet<TextRange> injectedFileRangesSet = ContainerUtilRt.newLinkedHashSet();
if (!psi.getProject().isDefault()) {
List<DocumentWindow> injectedDocuments = InjectedLanguageUtil.getCachedInjectedDocuments(file);
if (!injectedDocuments.isEmpty()) {
for (DocumentWindow injectedDocument : injectedDocuments) {
injectedFileRangesSet.add(TextRange.from(injectedDocument.injectedToHost(0), injectedDocument.getTextLength()));
}
} else {
Collection<PsiLanguageInjectionHost> injectionHosts = collectInjectionHosts(file, range);
PsiLanguageInjectionHost.InjectedPsiVisitor visitor = new PsiLanguageInjectionHost.InjectedPsiVisitor() {
@Override
public void visit(@NotNull PsiFile injectedPsi, @NotNull List<PsiLanguageInjectionHost.Shred> places) {
for (PsiLanguageInjectionHost.Shred place : places) {
Segment rangeMarker = place.getHostRangeMarker();
injectedFileRangesSet.add(TextRange.create(rangeMarker.getStartOffset(), rangeMarker.getEndOffset()));
}
}
};
for (PsiLanguageInjectionHost host : injectionHosts) {
InjectedLanguageUtil.enumerate(host, visitor);
}
}
}
if (!injectedFileRangesSet.isEmpty()) {
List<TextRange> ranges = ContainerUtilRt.newArrayList(injectedFileRangesSet);
Collections.reverse(ranges);
for (TextRange injectedFileRange : ranges) {
int startHostOffset = injectedFileRange.getStartOffset();
int endHostOffset = injectedFileRange.getEndOffset();
if (startHostOffset >= range.getStartOffset() && endHostOffset <= range.getEndOffset()) {
PsiFile injected = InjectedLanguageUtil.findInjectedPsiNoCommit(file, startHostOffset);
if (injected != null) {
int startInjectedOffset = range.getStartOffset() > startHostOffset ? startHostOffset - range.getStartOffset() : 0;
int endInjectedOffset = injected.getTextLength();
if (range.getEndOffset() < endHostOffset) {
endInjectedOffset -= endHostOffset - range.getEndOffset();
}
final TextRange initialInjectedRange = TextRange.create(startInjectedOffset, endInjectedOffset);
TextRange injectedRange = initialInjectedRange;
for (PreFormatProcessor processor : Extensions.getExtensions(PreFormatProcessor.EP_NAME)) {
injectedRange = processor.process(injected.getNode(), injectedRange);
}
// Allow only range expansion (not reduction) for injected context.
if ((initialInjectedRange.getStartOffset() > injectedRange.getStartOffset() && initialInjectedRange.getStartOffset() > 0) || (initialInjectedRange.getEndOffset() < injectedRange.getEndOffset() && initialInjectedRange.getEndOffset() < injected.getTextLength())) {
range = TextRange.create(range.getStartOffset() + injectedRange.getStartOffset() - initialInjectedRange.getStartOffset(), range.getEndOffset() + initialInjectedRange.getEndOffset() - injectedRange.getEndOffset());
}
}
}
}
}
if (!mySettings.FORMATTER_TAGS_ENABLED) {
for (PreFormatProcessor processor : Extensions.getExtensions(PreFormatProcessor.EP_NAME)) {
result = processor.process(node, result);
}
} else {
result = preprocessEnabledRanges(node, result);
}
return result;
}
use of com.intellij.injected.editor.DocumentWindow in project intellij-community by JetBrains.
the class MultiHostRegistrarImpl method freezeWindow.
@NotNull
public static DocumentWindow freezeWindow(@NotNull DocumentWindowImpl window) {
Place shreds = window.getShreds();
Project project = shreds.getHostPointer().getProject();
DocumentEx delegate = ((PsiDocumentManagerBase) PsiDocumentManager.getInstance(project)).getLastCommittedDocument(window.getDelegate());
Place place = new Place(ContainerUtil.map(shreds, shred -> ((ShredImpl) shred).withPsiRange()));
return new DocumentWindowImpl(delegate, window.isOneLine(), place);
}
use of com.intellij.injected.editor.DocumentWindow in project intellij-community by JetBrains.
the class MultiHostRegistrarImpl method registerDocument.
// under com.intellij.psi.PsiLock.LOCK
private static PsiFile registerDocument(final DocumentWindowImpl documentWindow, final PsiFile injectedPsi, final Place shreds, final PsiFile hostPsiFile, final PsiDocumentManager documentManager) {
List<DocumentWindow> injected = InjectedLanguageUtil.getCachedInjectedDocuments(hostPsiFile);
for (int i = injected.size() - 1; i >= 0; i--) {
DocumentWindowImpl oldDocument = (DocumentWindowImpl) injected.get(i);
final PsiFileImpl oldFile = (PsiFileImpl) documentManager.getCachedPsiFile(oldDocument);
FileViewProvider viewProvider;
if (oldFile == null || !oldFile.isValid() || !((viewProvider = oldFile.getViewProvider()) instanceof InjectedFileViewProvider) || ((InjectedFileViewProvider) viewProvider).isDisposed()) {
injected.remove(i);
Disposer.dispose(oldDocument);
continue;
}
InjectedFileViewProvider oldViewProvider = (InjectedFileViewProvider) viewProvider;
final ASTNode injectedNode = injectedPsi.getNode();
final ASTNode oldFileNode = oldFile.getNode();
assert injectedNode != null : "New node is null";
if (oldDocument.areRangesEqual(documentWindow)) {
if (oldFile.getFileType() != injectedPsi.getFileType() || oldFile.getLanguage() != injectedPsi.getLanguage()) {
injected.remove(i);
Disposer.dispose(oldDocument);
continue;
}
oldFile.putUserData(FileContextUtil.INJECTED_IN_ELEMENT, injectedPsi.getUserData(FileContextUtil.INJECTED_IN_ELEMENT));
assert shreds.isValid();
if (!oldFile.textMatches(injectedPsi)) {
oldViewProvider.performNonPhysically(() -> {
DebugUtil.startPsiModification("injected tree diff");
try {
final DiffLog diffLog = BlockSupportImpl.mergeTrees(oldFile, oldFileNode, injectedNode, new DaemonProgressIndicator(), oldFileNode.getText());
DocumentCommitThread.doActualPsiChange(oldFile, diffLog);
} finally {
DebugUtil.finishPsiModification();
}
});
}
assert shreds.isValid();
return oldFile;
}
}
injected.add(documentWindow);
return injectedPsi;
}
use of com.intellij.injected.editor.DocumentWindow in project intellij-community by JetBrains.
the class CodeStyleManagerImpl method reformatNewlyAddedElement.
@Override
public void reformatNewlyAddedElement(@NotNull final ASTNode parent, @NotNull final ASTNode addedElement) throws IncorrectOperationException {
LOG.assertTrue(addedElement.getTreeParent() == parent, "addedElement must be added to parent");
final PsiElement psiElement = parent.getPsi();
PsiFile containingFile = psiElement.getContainingFile();
final FileViewProvider fileViewProvider = containingFile.getViewProvider();
if (fileViewProvider instanceof MultiplePsiFilesPerDocumentFileViewProvider) {
containingFile = fileViewProvider.getPsi(fileViewProvider.getBaseLanguage());
}
TextRange textRange = addedElement.getTextRange();
final Document document = fileViewProvider.getDocument();
if (document instanceof DocumentWindow) {
containingFile = InjectedLanguageManager.getInstance(containingFile.getProject()).getTopLevelFile(containingFile);
textRange = ((DocumentWindow) document).injectedToHost(textRange);
}
final FormattingModelBuilder builder = LanguageFormatting.INSTANCE.forContext(containingFile);
if (builder != null) {
final FormattingModel model = CoreFormatterUtil.buildModel(builder, containingFile, getSettings(), FormattingMode.REFORMAT);
FormatterEx.getInstanceEx().formatAroundRange(model, getSettings(), containingFile, textRange);
}
adjustLineIndent(containingFile, textRange);
}
Aggregations