Mercurial > projects > dwt-addons
annotate dwtx/text/edits/CopySourceEdit.d @ 153:f70d9508c95c
Fix java Collection imports
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Mon, 25 Aug 2008 00:27:31 +0200 |
parents | 6dcb0baaa031 |
children | 7926b636c282 |
rev | line source |
---|---|
129 | 1 /******************************************************************************* |
2 * Copyright (c) 2000, 2006 IBM Corporation and others. | |
3 * All rights reserved. This program and the accompanying materials | |
4 * are made available under the terms of the Eclipse Public License v1.0 | |
5 * which accompanies this distribution, and is available at | |
6 * http://www.eclipse.org/legal/epl-v10.html | |
7 * | |
8 * Contributors: | |
9 * IBM Corporation - initial API and implementation | |
10 * Port to the D programming language: | |
11 * Frank Benoit <benoit@tionex.de> | |
12 *******************************************************************************/ | |
13 module dwtx.text.edits.CopySourceEdit; | |
14 | |
131 | 15 import dwtx.text.edits.MultiTextEdit; // packageimport |
16 import dwtx.text.edits.MoveSourceEdit; // packageimport | |
17 import dwtx.text.edits.CopyingRangeMarker; // packageimport | |
18 import dwtx.text.edits.ReplaceEdit; // packageimport | |
19 import dwtx.text.edits.EditDocument; // packageimport | |
20 import dwtx.text.edits.UndoCollector; // packageimport | |
21 import dwtx.text.edits.DeleteEdit; // packageimport | |
22 import dwtx.text.edits.MoveTargetEdit; // packageimport | |
23 import dwtx.text.edits.CopyTargetEdit; // packageimport | |
24 import dwtx.text.edits.TextEditCopier; // packageimport | |
25 import dwtx.text.edits.ISourceModifier; // packageimport | |
26 import dwtx.text.edits.TextEditMessages; // packageimport | |
27 import dwtx.text.edits.TextEditProcessor; // packageimport | |
28 import dwtx.text.edits.MalformedTreeException; // packageimport | |
29 import dwtx.text.edits.TreeIterationInfo; // packageimport | |
30 import dwtx.text.edits.TextEditVisitor; // packageimport | |
31 import dwtx.text.edits.TextEditGroup; // packageimport | |
32 import dwtx.text.edits.TextEdit; // packageimport | |
33 import dwtx.text.edits.RangeMarker; // packageimport | |
34 import dwtx.text.edits.UndoEdit; // packageimport | |
35 import dwtx.text.edits.InsertEdit; // packageimport | |
36 | |
37 | |
129 | 38 import dwt.dwthelper.utils; |
39 | |
153
f70d9508c95c
Fix java Collection imports
Frank Benoit <benoit@tionex.de>
parents:
136
diff
changeset
|
40 import dwtx.dwtxhelper.Collection; |
f70d9508c95c
Fix java Collection imports
Frank Benoit <benoit@tionex.de>
parents:
136
diff
changeset
|
41 |
129 | 42 |
43 import dwtx.core.runtime.Assert; | |
44 import dwtx.jface.text.BadLocationException; | |
45 import dwtx.jface.text.IDocument; | |
46 | |
47 /** | |
48 * A copy source edit denotes the source of a copy operation. Copy | |
49 * source edits are only valid inside an edit tree if they have a | |
50 * corresponding target edit. Furthermore the corresponding | |
51 * target edit can't be a direct or indirect child of the source | |
52 * edit. Violating one of two requirements will result in a <code> | |
53 * MalformedTreeException</code> when executing the edit tree. | |
54 * <p> | |
55 * A copy source edit can manage an optional source modifier. A | |
56 * source modifier can provide a set of replace edits which will | |
57 * to applied to the source before it gets inserted at the target | |
58 * position. | |
59 * | |
60 * @see dwtx.text.edits.CopyTargetEdit | |
61 * | |
62 * @since 3.0 | |
63 */ | |
64 public final class CopySourceEdit : TextEdit { | |
65 | |
66 private CopyTargetEdit fTarget; | |
67 private ISourceModifier fModifier; | |
68 | |
69 private String fSourceContent; | |
70 private TextEdit fSourceRoot; | |
71 | |
72 private static class PartialCopier : TextEditVisitor { | |
73 TextEdit fResult; | |
74 List fParents= new ArrayList(); | |
75 TextEdit fCurrentParent; | |
76 | |
77 public static TextEdit perform(TextEdit source) { | |
78 PartialCopier copier= new PartialCopier(); | |
79 source.accept(copier); | |
80 return copier.fResult; | |
81 } | |
82 private void manageCopy(TextEdit copy) { | |
83 if (fResult is null) | |
84 fResult= copy; | |
85 if (fCurrentParent !is null) { | |
86 fCurrentParent.addChild(copy); | |
87 } | |
88 fParents.add(fCurrentParent); | |
89 fCurrentParent= copy; | |
90 } | |
91 public void postVisit(TextEdit edit) { | |
134 | 92 fCurrentParent= cast(TextEdit)fParents.remove(fParents.size() - 1); |
129 | 93 } |
94 public bool visitNode(TextEdit edit) { | |
95 manageCopy(edit.doCopy()); | |
96 return true; | |
97 } | |
98 public bool visit(CopySourceEdit edit) { | |
99 manageCopy(new RangeMarker(edit.getOffset(), edit.getLength())); | |
100 return true; | |
101 } | |
102 public bool visit(CopyTargetEdit edit) { | |
103 manageCopy(new InsertEdit(edit.getOffset(), edit.getSourceEdit().getContent())); | |
104 return true; | |
105 } | |
106 public bool visit(MoveSourceEdit edit) { | |
107 manageCopy(new DeleteEdit(edit.getOffset(), edit.getLength())); | |
108 return true; | |
109 } | |
110 public bool visit(MoveTargetEdit edit) { | |
111 manageCopy(new InsertEdit(edit.getOffset(), edit.getSourceEdit().getContent())); | |
112 return true; | |
113 } | |
114 } | |
115 | |
116 /** | |
117 * Constructs a new copy source edit. | |
118 * | |
119 * @param offset the edit's offset | |
120 * @param length the edit's length | |
121 */ | |
130 | 122 public this(int offset, int length) { |
129 | 123 super(offset, length); |
124 } | |
125 | |
126 /** | |
127 * Constructs a new copy source edit. | |
128 * | |
129 * @param offset the edit's offset | |
130 * @param length the edit's length | |
131 * @param target the edit's target | |
132 */ | |
130 | 133 public this(int offset, int length, CopyTargetEdit target) { |
129 | 134 this(offset, length); |
135 setTargetEdit(target); | |
136 } | |
137 | |
138 /* | |
139 * Copy Constructor | |
140 */ | |
130 | 141 private this(CopySourceEdit other) { |
129 | 142 super(other); |
143 if (other.fModifier !is null) | |
144 fModifier= other.fModifier.copy(); | |
145 } | |
146 | |
147 /** | |
148 * Returns the associated target edit or <code>null</code> | |
149 * if no target edit is associated yet. | |
150 * | |
151 * @return the target edit or <code>null</code> | |
152 */ | |
153 public CopyTargetEdit getTargetEdit() { | |
154 return fTarget; | |
155 } | |
156 | |
157 /** | |
158 * Sets the target edit. | |
159 * | |
160 * @param edit the new target edit. | |
161 * | |
162 * @exception MalformedTreeException is thrown if the target edit | |
163 * is a direct or indirect child of the source edit | |
164 */ | |
136
6dcb0baaa031
Regex removal of throws decls, some instanceof
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
165 public void setTargetEdit(CopyTargetEdit edit) { |
129 | 166 Assert.isNotNull(edit); |
167 if (fTarget !is edit) { | |
168 fTarget= edit; | |
169 fTarget.setSourceEdit(this); | |
170 } | |
171 } | |
172 | |
173 /** | |
174 * Returns the current source modifier or <code>null</code> | |
175 * if no source modifier is set. | |
176 * | |
177 * @return the source modifier | |
178 */ | |
179 public ISourceModifier getSourceModifier() { | |
180 return fModifier; | |
181 } | |
182 | |
183 /** | |
184 * Sets the optional source modifier. | |
185 * | |
186 * @param modifier the source modifier or <code>null</code> | |
187 * if no source modification is need. | |
188 */ | |
189 public void setSourceModifier(ISourceModifier modifier) { | |
190 fModifier= modifier; | |
191 } | |
192 | |
193 /* | |
194 * @see TextEdit#doCopy | |
195 */ | |
196 protected TextEdit doCopy() { | |
197 return new CopySourceEdit(this); | |
198 } | |
199 | |
200 /* | |
201 * @see TextEdit#accept0 | |
202 */ | |
203 protected void accept0(TextEditVisitor visitor) { | |
204 bool visitChildren= visitor.visit(this); | |
205 if (visitChildren) { | |
206 acceptChildren(visitor); | |
207 } | |
208 } | |
209 | |
210 //---- API for CopyTargetEdit ------------------------------------------------ | |
211 | |
212 String getContent() { | |
213 // The source content can be null if the edit wasn't executed | |
214 // due to an exclusion list of the text edit processor. Return | |
215 // the empty string which can be moved without any harm. | |
216 if (fSourceContent is null) | |
217 return ""; //$NON-NLS-1$ | |
218 return fSourceContent; | |
219 } | |
220 | |
221 void clearContent() { | |
222 fSourceContent= null; | |
223 } | |
224 | |
225 /* | |
226 * @see TextEdit#postProcessCopy | |
227 */ | |
228 protected void postProcessCopy(TextEditCopier copier) { | |
229 if (fTarget !is null) { | |
134 | 230 CopySourceEdit source= cast(CopySourceEdit)copier.getCopy(this); |
231 CopyTargetEdit target= cast(CopyTargetEdit)copier.getCopy(fTarget); | |
129 | 232 if (source !is null && target !is null) |
233 source.setTargetEdit(target); | |
234 } | |
235 } | |
236 | |
237 //---- consistency check ---------------------------------------------------- | |
238 | |
239 int traverseConsistencyCheck(TextEditProcessor processor, IDocument document, List sourceEdits) { | |
240 int result= super.traverseConsistencyCheck(processor, document, sourceEdits); | |
241 // Since source computation takes place in a recursive fashion (see | |
242 // performSourceComputation) we only do something if we don't have a | |
243 // computed source already. | |
244 if (fSourceContent is null) { | |
245 if (sourceEdits.size() <= result) { | |
246 List list= new ArrayList(); | |
247 list.add(this); | |
248 for (int i= sourceEdits.size(); i < result; i++) | |
249 sourceEdits.add(null); | |
250 sourceEdits.add(list); | |
251 } else { | |
134 | 252 List list= cast(List)sourceEdits.get(result); |
129 | 253 if (list is null) { |
254 list= new ArrayList(); | |
255 sourceEdits.add(result, list); | |
256 } | |
257 list.add(this); | |
258 } | |
259 } | |
260 return result; | |
261 } | |
262 | |
136
6dcb0baaa031
Regex removal of throws decls, some instanceof
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
263 void performConsistencyCheck(TextEditProcessor processor, IDocument document) { |
129 | 264 if (fTarget is null) |
265 throw new MalformedTreeException(getParent(), this, TextEditMessages.getString("CopySourceEdit.no_target")); //$NON-NLS-1$ | |
266 if (fTarget.getSourceEdit() !is this) | |
267 throw new MalformedTreeException(getParent(), this, TextEditMessages.getString("CopySourceEdit.different_source")); //$NON-NLS-1$ | |
268 /* causes ASTRewrite to fail | |
269 if (getRoot() !is fTarget.getRoot()) | |
270 throw new MalformedTreeException(getParent(), this, TextEditMessages.getString("CopySourceEdit.different_tree")); //$NON-NLS-1$ | |
271 */ | |
272 } | |
273 | |
274 //---- source computation ------------------------------------------------------- | |
275 | |
276 void traverseSourceComputation(TextEditProcessor processor, IDocument document) { | |
277 // always perform source computation independent of processor.considerEdit | |
278 // The target might need the source and the source is computed in a | |
279 // temporary buffer. | |
280 performSourceComputation(processor, document); | |
281 } | |
282 | |
283 void performSourceComputation(TextEditProcessor processor, IDocument document) { | |
284 try { | |
285 MultiTextEdit root= new MultiTextEdit(getOffset(), getLength()); | |
286 root.internalSetChildren(internalGetChildren()); | |
287 fSourceContent= document.get(getOffset(), getLength()); | |
288 fSourceRoot= PartialCopier.perform(root); | |
289 fSourceRoot.internalMoveTree(-getOffset()); | |
290 if (fSourceRoot.hasChildren()) { | |
291 EditDocument subDocument= new EditDocument(fSourceContent); | |
292 TextEditProcessor subProcessor= TextEditProcessor.createSourceComputationProcessor(subDocument, fSourceRoot, TextEdit.NONE); | |
293 subProcessor.performEdits(); | |
294 if (needsTransformation()) | |
295 applyTransformation(subDocument); | |
296 fSourceContent= subDocument.get(); | |
297 fSourceRoot= null; | |
298 } else { | |
299 if (needsTransformation()) { | |
300 EditDocument subDocument= new EditDocument(fSourceContent); | |
301 applyTransformation(subDocument); | |
302 fSourceContent= subDocument.get(); | |
303 } | |
304 } | |
305 } catch (BadLocationException cannotHappen) { | |
306 Assert.isTrue(false); | |
307 } | |
308 } | |
309 | |
310 private bool needsTransformation() { | |
311 return fModifier !is null; | |
312 } | |
313 | |
136
6dcb0baaa031
Regex removal of throws decls, some instanceof
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
314 private void applyTransformation(IDocument document) { |
129 | 315 TextEdit newEdit= new MultiTextEdit(0, document.getLength()); |
316 ReplaceEdit[] replaces= fModifier.getModifications(document.get()); | |
317 for (int i= 0; i < replaces.length; i++) { | |
318 newEdit.addChild(replaces[i]); | |
319 } | |
320 try { | |
321 newEdit.apply(document, TextEdit.NONE); | |
322 } catch (BadLocationException cannotHappen) { | |
323 Assert.isTrue(false); | |
324 } | |
325 } | |
326 | |
327 //---- document updating ---------------------------------------------------------------- | |
328 | |
136
6dcb0baaa031
Regex removal of throws decls, some instanceof
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
329 int performDocumentUpdating(IDocument document) { |
129 | 330 fDelta= 0; |
331 return fDelta; | |
332 } | |
333 | |
334 //---- region updating ---------------------------------------------------------------- | |
335 | |
336 /* | |
337 * @see TextEdit#deleteChildren | |
338 */ | |
339 bool deleteChildren() { | |
340 return false; | |
341 } | |
342 } |