/* * Copyright 2000-2015 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.openapi.editor.impl; import com.intellij.openapi.editor.event.DocumentEvent; import com.intellij.openapi.editor.impl.event.DocumentEventImpl; import com.intellij.openapi.editor.impl.event.RetargetRangeMarkers; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Segment; import com.intellij.openapi.util.TextRange; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** * A range marker that has to be manually updated with {@link #getUpdatedRange(DocumentEvent, FrozenDocument)}. * Can hold PSI-based range and be updated when the document is committed. */ public class ManualRangeMarker implements Segment { private final int myStart; private final int myEnd; private final boolean myGreedyLeft; private final boolean myGreedyRight; private final boolean mySurviveOnExternalChange; private final PersistentRangeMarker.LinesCols myLinesCols; public ManualRangeMarker(int start, int end, boolean greedyLeft, boolean greedyRight, boolean surviveOnExternalChange, @Nullable PersistentRangeMarker.LinesCols linesCols) { myStart = start; myEnd = end; myGreedyLeft = greedyLeft; myGreedyRight = greedyRight; mySurviveOnExternalChange = surviveOnExternalChange; myLinesCols = linesCols; } @Nullable public ManualRangeMarker getUpdatedRange(@NotNull DocumentEvent event, @NotNull FrozenDocument documentBefore) { if (event instanceof RetargetRangeMarkers) { int start = ((RetargetRangeMarkers)event).getStartOffset(); if (myStart >= start && myEnd <= ((RetargetRangeMarkers)event).getEndOffset()) { int delta = ((RetargetRangeMarkers)event).getMoveDestinationOffset() - start; return new ManualRangeMarker(myStart + delta, myEnd + delta, myGreedyLeft, myGreedyRight, mySurviveOnExternalChange, null); } } if (mySurviveOnExternalChange && PersistentRangeMarkerUtil.shouldTranslateViaDiff(event, myStart, myEnd)) { PersistentRangeMarker.LinesCols linesCols = myLinesCols != null ? myLinesCols : PersistentRangeMarker.storeLinesAndCols(documentBefore, myStart, myEnd); Pair<TextRange, PersistentRangeMarker.LinesCols> pair = linesCols == null ? null : PersistentRangeMarker.translateViaDiff((DocumentEventImpl)event, linesCols); if (pair != null) { return new ManualRangeMarker(pair.first.getStartOffset(), pair.first.getEndOffset(), myGreedyLeft, myGreedyRight, true, pair.second); } } TextRange range = RangeMarkerImpl.applyChange(event, myStart, myEnd, myGreedyLeft, myGreedyRight); return range == null ? null : new ManualRangeMarker(range.getStartOffset(), range.getEndOffset(), myGreedyLeft, myGreedyRight, mySurviveOnExternalChange, null); } @Override public int getStartOffset() { return myStart; } @Override public int getEndOffset() { return myEnd; } @Override public String toString() { return "ManualRangeMarker" + TextRange.create(this); } }