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