@Override @NotNull public RangeMarker createRangeMarker(final int startOffset, final int endOffset) { ProperTextRange hostRange = injectedToHost(new ProperTextRange(startOffset, endOffset)); RangeMarker hostMarker = myDelegate.createRangeMarker(hostRange); int startShift = Math.max(0, hostToInjected(hostRange.getStartOffset()) - startOffset); int endShift = Math.max(0, endOffset - hostToInjected(hostRange.getEndOffset()) - startShift); return new RangeMarkerWindow(this, (RangeMarkerEx) hostMarker, startShift, endShift); }
void repaint(int startOffset, int endOffset) { markDirtied(); ProperTextRange range = offsetToYPosition(startOffset, endOffset); myEditor .getVerticalScrollBar() .repaint(0, range.getStartOffset(), PREFERRED_WIDTH, range.getLength() + getMinHeight()); }
private void commitToOriginalInner() { final String text = myNewDocument.getText(); final Map< PsiLanguageInjectionHost, Set<Trinity<RangeMarker, RangeMarker, SmartPsiElementPointer>>> map = ContainerUtil.classify( myMarkers.iterator(), new Convertor< Trinity<RangeMarker, RangeMarker, SmartPsiElementPointer>, PsiLanguageInjectionHost>() { @Override public PsiLanguageInjectionHost convert( final Trinity<RangeMarker, RangeMarker, SmartPsiElementPointer> o) { final PsiElement element = o.third.getElement(); return (PsiLanguageInjectionHost) element; } }); PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myProject); documentManager.commitDocument(myOrigDocument); // commit here and after each manipulator update int localInsideFileCursor = 0; for (PsiLanguageInjectionHost host : map.keySet()) { if (host == null) continue; String hostText = host.getText(); ProperTextRange insideHost = null; StringBuilder sb = new StringBuilder(); for (Trinity<RangeMarker, RangeMarker, SmartPsiElementPointer> entry : map.get(host)) { RangeMarker origMarker = entry.first; // check for validity? int hostOffset = host.getTextRange().getStartOffset(); ProperTextRange localInsideHost = new ProperTextRange( origMarker.getStartOffset() - hostOffset, origMarker.getEndOffset() - hostOffset); RangeMarker rangeMarker = entry.second; ProperTextRange localInsideFile = new ProperTextRange( Math.max(localInsideFileCursor, rangeMarker.getStartOffset()), rangeMarker.getEndOffset()); if (insideHost != null) { // append unchanged inter-markers fragment sb.append( hostText.substring(insideHost.getEndOffset(), localInsideHost.getStartOffset())); } sb.append( localInsideFile.getEndOffset() <= text.length() && !localInsideFile.isEmpty() ? localInsideFile.substring(text) : ""); localInsideFileCursor = localInsideFile.getEndOffset(); insideHost = insideHost == null ? localInsideHost : insideHost.union(localInsideHost); } assert insideHost != null; ElementManipulators.getManipulator(host).handleContentChange(host, insideHost, sb.toString()); documentManager.commitDocument(myOrigDocument); } }
protected void changedUpdateImpl(@NotNull DocumentEvent e) { if (!isValid()) return; ProperTextRange newRange = applyChange(e, intervalStart(), intervalEnd(), isGreedyToLeft(), isGreedyToRight()); if (newRange == null) { invalidate(e); return; } setIntervalStart(newRange.getStartOffset()); setIntervalEnd(newRange.getEndOffset()); }
private boolean showToolTipByMouseMove(final MouseEvent e, final double width) { MouseEvent me = e; Set<RangeHighlighter> highlighters = new THashSet<RangeHighlighter>(); getNearestHighlighters(this, me, width, highlighters); getNearestHighlighters( (MarkupModelEx) myEditor.getDocument().getMarkupModel(getEditor().getProject()), me, width, highlighters); if (highlighters.isEmpty()) return false; int minDelta = Integer.MAX_VALUE; int y = e.getY(); for (RangeHighlighter each : highlighters) { ProperTextRange range = offsetToYPosition(each.getStartOffset(), each.getEndOffset()); int eachStartY = range.getStartOffset(); int eachEndY = range.getEndOffset(); int eachY = eachStartY + (eachEndY - eachStartY) / 2; if (Math.abs(e.getY() - eachY) < minDelta) { y = eachY; } } me = new MouseEvent( (Component) e.getSource(), e.getID(), e.getWhen(), e.getModifiers(), e.getX(), y + 1, e.getClickCount(), e.isPopupTrigger()); TooltipRenderer bigRenderer = myTooltipRendererProvider.calcTooltipRenderer(highlighters); if (bigRenderer != null) { showTooltip( me, bigRenderer, new HintHint(me).setAwtTooltip(true).setPreferredPosition(Balloon.Position.atLeft)); return true; } return false; }
@Override @NotNull public RangeMarker createRangeMarker( final int startOffset, final int endOffset, final boolean surviveOnExternalChange) { if (!surviveOnExternalChange) { return createRangeMarker(startOffset, endOffset); } ProperTextRange hostRange = injectedToHost(new ProperTextRange(startOffset, endOffset)); // todo persistent? RangeMarker hostMarker = myDelegate.createRangeMarker( hostRange.getStartOffset(), hostRange.getEndOffset(), surviveOnExternalChange); int startShift = Math.max(0, hostToInjected(hostRange.getStartOffset()) - startOffset); int endShift = Math.max(0, endOffset - hostToInjected(hostRange.getEndOffset()) - startShift); return new RangeMarkerWindow(this, (RangeMarkerEx) hostMarker, startShift, endShift); }
private static void highlightTodos( @NotNull PsiFile file, @NotNull CharSequence text, int startOffset, int endOffset, @NotNull ProgressIndicator progress, @NotNull ProperTextRange priorityRange, @NotNull Collection<HighlightInfo> result, @NotNull Collection<HighlightInfo> outsideResult) { PsiSearchHelper helper = PsiSearchHelper.SERVICE.getInstance(file.getProject()); TodoItem[] todoItems = helper.findTodoItems(file, startOffset, endOffset); if (todoItems.length == 0) return; for (TodoItem todoItem : todoItems) { progress.checkCanceled(); TextRange range = todoItem.getTextRange(); String description = text.subSequence(range.getStartOffset(), range.getEndOffset()).toString(); TextAttributes attributes = todoItem.getPattern().getAttributes().getTextAttributes(); HighlightInfo info = HighlightInfo.createHighlightInfo( HighlightInfoType.TODO, range, description, description, attributes); assert info != null; if (priorityRange.containsRange(info.getStartOffset(), info.getEndOffset())) { result.add(info); } else { outsideResult.add(info); } } }
public static void renameNonCodeUsages( @NotNull Project project, @NotNull NonCodeUsageInfo[] usages) { PsiDocumentManager.getInstance(project).commitAllDocuments(); Map<Document, List<UsageOffset>> docsToOffsetsMap = new HashMap<Document, List<UsageOffset>>(); final PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(project); for (NonCodeUsageInfo usage : usages) { PsiElement element = usage.getElement(); if (element == null) continue; element = CodeInsightUtilBase.forcePsiPostprocessAndRestoreElement(element, true); if (element == null) continue; final ProperTextRange rangeInElement = usage.getRangeInElement(); if (rangeInElement == null) continue; final PsiFile containingFile = element.getContainingFile(); final Document document = psiDocumentManager.getDocument(containingFile); final Segment segment = usage.getSegment(); LOG.assertTrue(segment != null); int fileOffset = segment.getStartOffset(); List<UsageOffset> list = docsToOffsetsMap.get(document); if (list == null) { list = new ArrayList<UsageOffset>(); docsToOffsetsMap.put(document, list); } list.add(new UsageOffset(fileOffset, fileOffset + rangeInElement.getLength(), usage.newText)); } for (Document document : docsToOffsetsMap.keySet()) { List<UsageOffset> list = docsToOffsetsMap.get(document); LOG.assertTrue(list != null, document); UsageOffset[] offsets = list.toArray(new UsageOffset[list.size()]); Arrays.sort(offsets); for (int i = offsets.length - 1; i >= 0; i--) { UsageOffset usageOffset = offsets[i]; document.replaceString(usageOffset.startOffset, usageOffset.endOffset, usageOffset.newText); } PsiDocumentManager.getInstance(project).commitDocument(document); } PsiDocumentManager.getInstance(project).commitAllDocuments(); }
AnchorElementInfo(@NotNull PsiElement anchor, @NotNull PsiFile containingFile) { super( containingFile.getProject(), ProperTextRange.create(anchor.getTextRange()), anchor.getClass(), containingFile, LanguageUtil.getRootLanguage(anchor)); assert !(anchor instanceof PsiFile) : "FileElementInfo must be used for file: " + anchor; myStubElementTypeAndId = pack(-1, null); }
// finds the first nearest text range @Nullable("null means invalid") private static TextRange findNearestTextRange( final DocumentWindow documentWindow, final int startOffset) { TextRange textRange = null; for (Segment marker : documentWindow.getHostRanges()) { TextRange curRange = ProperTextRange.create(marker); if (curRange.getStartOffset() > startOffset && textRange != null) break; textRange = curRange; } return textRange; }
// finds the first nearest text range private static TextRange findNearestTextRange( final DocumentWindow documentWindow, final int startOffset) { TextRange textRange = null; for (RangeMarker marker : documentWindow.getHostRanges()) { TextRange curRange = ProperTextRange.create(marker); if (curRange.getStartOffset() > startOffset && textRange != null) break; textRange = curRange; } assert textRange != null; return textRange; }
@Override @NotNull public TextRange injectedToHost( @NotNull PsiElement injectedContext, @NotNull TextRange injectedTextRange) { ProperTextRange.assertProperRange(injectedTextRange); PsiFile file = injectedContext.getContainingFile(); if (file == null) return injectedTextRange; Document document = PsiDocumentManager.getInstance(file.getProject()).getCachedDocument(file); if (!(document instanceof DocumentWindowImpl)) return injectedTextRange; DocumentWindowImpl documentWindow = (DocumentWindowImpl) document; return documentWindow.injectedToHost(injectedTextRange); }
@Override public TextRange getHostRange(int hostOffset) { synchronized (myLock) { for (PsiLanguageInjectionHost.Shred shred : myShreds) { Segment currentRange = shred.getHostRangeMarker(); if (currentRange == null) continue; TextRange textRange = ProperTextRange.create(currentRange); if (textRange.grown(1).contains(hostOffset)) return textRange; } } return null; }
@Override public boolean containsRange(int start, int end) { synchronized (myLock) { ProperTextRange query = new ProperTextRange(start, end); for (PsiLanguageInjectionHost.Shred shred : myShreds) { Segment hostRange = shred.getHostRangeMarker(); if (hostRange == null) continue; TextRange textRange = ProperTextRange.create(hostRange); if (textRange.contains(query)) return true; } return false; } }
@Override public boolean decode(@NotNull final TextRange rangeInsideHost, @NotNull StringBuilder outChars) { ProperTextRange.assertProperRange(rangeInsideHost); TextRange valueTextRange = myXmlAttribute.getValueTextRange(); int startInDecoded = myXmlAttribute.physicalToDisplay( rangeInsideHost.getStartOffset() - valueTextRange.getStartOffset()); int endInDecoded = myXmlAttribute.physicalToDisplay( rangeInsideHost.getEndOffset() - valueTextRange.getStartOffset()); String displayValue = myXmlAttribute.getDisplayValue(); // todo investigate IIOB http://www.jetbrains.net/jira/browse/IDEADEV-16796 startInDecoded = startInDecoded < 0 ? 0 : startInDecoded > displayValue.length() ? displayValue.length() : startInDecoded; endInDecoded = endInDecoded < 0 ? 0 : endInDecoded > displayValue.length() ? displayValue.length() : endInDecoded; if (startInDecoded > endInDecoded) endInDecoded = startInDecoded; outChars.append(displayValue, startInDecoded, endInDecoded); return true; }
@Override @NotNull public RangeMarker createRangeMarker(@NotNull final TextRange textRange) { final ProperTextRange properTextRange = new ProperTextRange(textRange); return createRangeMarker(properTextRange.getStartOffset(), properTextRange.getEndOffset()); }
@Override public RangeMarker getRangeGuard(final int startOffset, final int endOffset) { ProperTextRange hostRange = injectedToHost(new ProperTextRange(startOffset, endOffset)); return myDelegate.getRangeGuard(hostRange.getStartOffset(), hostRange.getEndOffset()); }
@Override @NotNull public RangeMarker createGuardedBlock(final int startOffset, final int endOffset) { ProperTextRange hostRange = injectedToHost(new ProperTextRange(startOffset, endOffset)); return myDelegate.createGuardedBlock(hostRange.getStartOffset(), hostRange.getEndOffset()); }