diagnostics
[fedora-idea.git] / platform / platform-impl / src / com / intellij / openapi / editor / impl / RangeMarkerImpl.java
blobfe0f72a9fb4a88adc4a021307839a63cd9e7f0d0
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.openapi.editor.impl;
18 import com.intellij.openapi.diagnostic.Logger;
19 import com.intellij.openapi.editor.event.DocumentEvent;
20 import com.intellij.openapi.editor.ex.DocumentEx;
21 import com.intellij.openapi.editor.ex.RangeMarkerEx;
22 import com.intellij.openapi.util.UserDataHolderBase;
23 import org.jetbrains.annotations.NonNls;
24 import org.jetbrains.annotations.NotNull;
26 import java.util.concurrent.atomic.AtomicLong;
28 public class RangeMarkerImpl extends UserDataHolderBase implements RangeMarkerEx {
29 private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.impl.RangeMarkerImpl");
31 protected final DocumentEx myDocument;
32 protected volatile int myStart;
33 protected volatile int myEnd;
34 private volatile boolean isValid = true;
35 private boolean isExpandToLeft = false;
36 private boolean isExpandToRight = false;
38 private static final AtomicLong counter = new AtomicLong();
39 private final long myId;
40 private volatile int modCount;
42 protected RangeMarkerImpl(@NotNull DocumentEx document, int start, int end) {
43 if (start < 0) {
44 throw new IllegalArgumentException("Wrong start: " + start+"; end="+end);
46 else if (end > document.getTextLength()) {
47 throw new IllegalArgumentException("Wrong end: " + end+ "; document length="+document.getTextLength()+"; start="+start);
49 else if (start > end){
50 throw new IllegalArgumentException("start > end: start=" + start+"; end="+end);
53 myDocument = document;
54 myStart = start;
55 myEnd = end;
56 myId = counter.getAndIncrement();
57 registerInDocument();
60 protected void registerInDocument() {
61 myDocument.addRangeMarker(this);
64 public long getId() {
65 return myId;
68 public int getStartOffset() {
69 return myStart;
72 public int getEndOffset() {
73 return myEnd;
76 public boolean isValid() {
77 return isValid;
80 public void invalidate() {
81 isValid = false;
84 @NotNull
85 public DocumentEx getDocument() {
86 return myDocument;
89 public void setGreedyToLeft(boolean greedy) {
90 isExpandToLeft = greedy;
93 public void setGreedyToRight(boolean greedy) {
94 isExpandToRight = greedy;
97 public boolean isGreedyToLeft() {
98 return isExpandToLeft;
101 public boolean isGreedyToRight() {
102 return isExpandToRight;
105 public final void documentChanged(DocumentEvent e) {
106 int modCount = this.modCount++;
107 int oldStart = myStart;
108 int oldEnd = myEnd;
109 int docLength = myDocument.getTextLength();
110 if (!isValid) {
111 LOG.error("Invalid range marker "+ (isExpandToLeft ? "[" : "(") + oldStart + ", " + oldEnd + (isExpandToRight ? "]" : ")") +
112 ". Event = " + e + ". Doc length=" + docLength + "; "+getClass());
113 return;
115 if (myStart > myEnd || myStart < 0 || myEnd > docLength - e.getNewLength() + e.getOldLength()) {
116 LOG.error("RangeMarker" + (isExpandToLeft ? "[" : "(") + oldStart + ", " + oldEnd + (isExpandToRight ? "]" : ")") +
117 " is invalid before update. Event = " + e + ". Doc length=" + docLength + "; "+getClass());
118 isValid = false;
119 return;
121 changedUpdateImpl(e);
122 if (isValid && (myStart > myEnd || myStart < 0 || myEnd > docLength)) {
123 LOG.error("RangeMarker" + (isExpandToLeft ? "[" : "(") + oldStart + ", " + oldEnd + (isExpandToRight ? "]" : ")") +
124 " update failed. Event = " + e + ". Result[" + myStart + ", " + myEnd + "], " +
125 "old doc length=" + docLength + "; real doc length = "+myDocument.getTextLength()+
126 "; old mod count="+modCount+"; mod count="+this.modCount+
127 "; "+getClass());
128 isValid = false;
132 protected void changedUpdateImpl(DocumentEvent e) {
133 if (!isValid) return;
135 // Process if one point.
136 if (myStart == myEnd) {
137 processIfOnePoint(e);
138 return;
141 final int offset = e.getOffset();
142 final int oldLength = e.getOldLength();
143 final int newLength = e.getNewLength();
145 // changes after the end.
146 if (myEnd < offset || !isExpandToRight && myEnd == offset) {
147 return;
150 // changes before start
151 if (myStart > offset + oldLength || !isExpandToLeft && myStart == offset + oldLength) {
152 myStart += newLength - oldLength;
153 myEnd += newLength - oldLength;
154 return;
157 // Changes inside marker's area. Expand/collapse.
158 if (myStart <= offset && myEnd >= offset + oldLength) {
159 myEnd += newLength - oldLength;
160 return;
163 // At this point we either have (myStart xor myEnd inside changed area) or whole area changed.
165 // Replacing prefix or suffix...
166 if (myStart >= offset && myStart <= offset + oldLength && myEnd > offset + oldLength) {
167 myEnd += newLength - oldLength;
168 myStart = offset + newLength;
169 return;
172 if (myEnd >= offset && myEnd <= offset + oldLength && myStart < offset) {
173 myEnd = offset;
174 return;
177 invalidate();
180 private void processIfOnePoint(DocumentEvent e) {
181 int offset = e.getOffset();
182 int oldLength = e.getOldLength();
183 int oldEnd = offset + oldLength;
184 if (offset < myStart && myStart < oldEnd) {
185 invalidate();
186 return;
189 if (offset == myStart && oldLength == 0 && isExpandToRight) {
190 myEnd += e.getNewLength();
191 return;
194 if (myStart > oldEnd || myStart == oldEnd && oldLength > 0) {
195 myStart += e.getNewLength() - oldLength;
196 myEnd += e.getNewLength() - oldLength;
200 @NonNls
201 public String toString() {
202 return "RangeMarker" + (isGreedyToLeft() ? "[" : "(") + (isValid ? "valid" : "invalid") + "," + getStartOffset() + "," + getEndOffset() + (
203 isGreedyToRight() ? "]" : ")");