Added
Link Here
|
1 |
/* |
2 |
* Created on Feb 5, 2004 |
3 |
* |
4 |
* To change the template for this generated file go to |
5 |
* Window - Preferences - Java - Code Generation - Code and Comments |
6 |
*/ |
7 |
package org.eclipse.ant.internal.ui.editor.formatter; |
8 |
|
9 |
import java.util.Arrays; |
10 |
import java.util.LinkedList; |
11 |
|
12 |
import org.eclipse.jface.text.BadLocationException; |
13 |
import org.eclipse.jface.text.IDocument; |
14 |
import org.eclipse.jface.text.Position; |
15 |
import org.eclipse.jface.text.formatter.ContextBasedFormattingStrategy; |
16 |
import org.eclipse.jface.text.formatter.FormattingContext; |
17 |
import org.eclipse.jface.text.formatter.FormattingContextProperties; |
18 |
import org.eclipse.jface.text.formatter.IFormattingContext; |
19 |
import org.eclipse.jface.text.source.ISourceViewer; |
20 |
import org.eclipse.jface.util.Assert; |
21 |
|
22 |
/** |
23 |
* @author shacjo |
24 |
* |
25 |
* To change the template for this generated type comment go to Window - |
26 |
* Preferences - Java - Code Generation - Code and Comments |
27 |
*/ |
28 |
public class XmlCommentFormattingStrategy extends |
29 |
ContextBasedFormattingStrategy { |
30 |
|
31 |
/** |
32 |
*/ |
33 |
private static class CommentPartitionDecorator { |
34 |
|
35 |
public static CommentPartitionDecorator decorate(IDocument document, |
36 |
Position partition) { |
37 |
return new CommentPartitionDecorator(document, partition); |
38 |
} |
39 |
|
40 |
private IDocument document; |
41 |
|
42 |
private Position partition; |
43 |
|
44 |
/** |
45 |
* @param document |
46 |
* @param partition |
47 |
*/ |
48 |
public CommentPartitionDecorator(IDocument document, Position partition) { |
49 |
} |
50 |
|
51 |
/** |
52 |
* @param p1 |
53 |
* the partition with the low offset |
54 |
* @param p2 |
55 |
* the partition with the high offset |
56 |
* @return true of both partitions are to be formatted as a single unit |
57 |
*/ |
58 |
private boolean formatTogether(Position p1, Position p2) |
59 |
throws BadLocationException { |
60 |
|
61 |
Assert.isTrue(p1.offset < p2.offset); |
62 |
String interveningText = textBetween(p1, p2); |
63 |
|
64 |
if (interveningText.trim().length() == 0 |
65 |
&& interveningText.indexOf('\n') == -1 |
66 |
&& interveningText.indexOf('\r') == -1) { |
67 |
return true; |
68 |
} else { |
69 |
return false; |
70 |
} |
71 |
} |
72 |
|
73 |
public boolean formatWith(Position partition) |
74 |
throws BadLocationException { |
75 |
|
76 |
Assert.isNotNull(this.document); |
77 |
Assert.isNotNull(this.partition); |
78 |
|
79 |
if (this.partition.offset < partition.offset) { |
80 |
return formatTogether(this.partition, partition); |
81 |
} else if (this.partition.offset > partition.offset) { |
82 |
return formatTogether(partition, this.partition); |
83 |
} else { |
84 |
// I wouldn't expect both partitions to |
85 |
// start at the same spot. |
86 |
return false; |
87 |
} |
88 |
} |
89 |
|
90 |
/** |
91 |
* @return {@link Position#getLength()} |
92 |
*/ |
93 |
public int getLength() { |
94 |
return partition.getLength(); |
95 |
} |
96 |
|
97 |
/** |
98 |
* @return {@link Position#getOffset()} |
99 |
*/ |
100 |
public int getOffset() { |
101 |
return partition.getOffset(); |
102 |
} |
103 |
|
104 |
public String getText() throws BadLocationException { |
105 |
return textOf(this.partition); |
106 |
} |
107 |
|
108 |
/** |
109 |
* @param string |
110 |
*/ |
111 |
public void replaceWith(String text) throws BadLocationException { |
112 |
|
113 |
if (text != null && !text.equals(this.getText())) |
114 |
document.replace(this.getOffset(), this.getLength(), text); |
115 |
|
116 |
} |
117 |
|
118 |
/** |
119 |
* @param p1 |
120 |
* the partition with the low offset |
121 |
* @param p2 |
122 |
* the partition with the high offset |
123 |
* @return text between the end of the first positions and start of the |
124 |
* second |
125 |
*/ |
126 |
private String textBetween(Position p1, Position p2) |
127 |
throws BadLocationException { |
128 |
return document.get(p1.offset + p1.length, p2.offset |
129 |
- (p1.offset + p1.length)); |
130 |
} |
131 |
|
132 |
private String textOf(Position partition) throws BadLocationException { |
133 |
return this.document.get(partition.offset, partition.length); |
134 |
} |
135 |
} |
136 |
|
137 |
/** |
138 |
*/ |
139 |
private abstract static class Normalizer { |
140 |
|
141 |
abstract protected boolean isApplicableFor(String commentText); |
142 |
|
143 |
abstract protected String normalize(String commentText); |
144 |
|
145 |
public String safelyNormalize(String commentText) { |
146 |
if (isApplicableFor(commentText)) |
147 |
return normalize(commentText); |
148 |
else |
149 |
return commentText; |
150 |
} |
151 |
} |
152 |
|
153 |
private static class SeparartorCommentNormalizer extends Normalizer { |
154 |
|
155 |
/* |
156 |
* (non-Javadoc) |
157 |
* |
158 |
* @see org.eclipse.ant.internal.ui.editor.format.XmlCommentFormattingStrategy.Normalizer#isApplicableFor(java.lang.String) |
159 |
*/ |
160 |
protected boolean isApplicableFor(String commentText) { |
161 |
// TODO Auto-generated method stub |
162 |
return false; |
163 |
} |
164 |
|
165 |
/* |
166 |
* (non-Javadoc) |
167 |
* |
168 |
* @see org.eclipse.ant.internal.ui.editor.format.XmlCommentFormattingStrategy.Normalizer#normalize(java.lang.String) |
169 |
*/ |
170 |
protected String normalize(String commentText) { |
171 |
// TODO Auto-generated method stub |
172 |
return null; |
173 |
} |
174 |
} |
175 |
|
176 |
private class TextCommentNormalizer extends Normalizer { |
177 |
|
178 |
private String actualText(String comment) { |
179 |
return comment.substring(4, comment.length() - 3).trim(); |
180 |
} |
181 |
|
182 |
/* |
183 |
* (non-Javadoc) |
184 |
* |
185 |
* @see org.eclipse.ant.internal.ui.editor.format.XmlCommentFormattingStrategy.Normalizer#isApplicableFor(java.lang.String) |
186 |
*/ |
187 |
protected boolean isApplicableFor(String commentText) { |
188 |
|
189 |
return Character.isLetterOrDigit(actualText(commentText).charAt(0)) |
190 |
&& commentText.indexOf('\n') == -1 |
191 |
&& commentText.indexOf('\r') == -1; |
192 |
} |
193 |
|
194 |
/* |
195 |
* (non-Javadoc) |
196 |
* |
197 |
* @see org.eclipse.ant.internal.ui.editor.format.XmlCommentFormattingStrategy.Normalizer#normalize(java.lang.String) |
198 |
*/ |
199 |
protected String normalize(String comment) { |
200 |
|
201 |
String text = comment.substring(4, comment.length() - 3).trim(); |
202 |
|
203 |
// TODO assumes text length < fCommentWidth which isn't necessarily the case |
204 |
char[] whitespace = new char[fCommentWidth - (text.length() + 7)]; |
205 |
Arrays.fill(whitespace,' '); |
206 |
|
207 |
return "<!-- " + actualText(comment) + String.valueOf(whitespace) |
208 |
+ "-->"; |
209 |
} |
210 |
} |
211 |
|
212 |
private final int fCommentWidth = 40; |
213 |
|
214 |
/** Indentations to use by this strategy */ |
215 |
private final LinkedList fIndentations; |
216 |
|
217 |
/** Normalizers for handling partition formatting */ |
218 |
private final Normalizer[] fNormalizers; |
219 |
|
220 |
/** Partitions to be formatted by this strategy */ |
221 |
private final LinkedList fPartitions; |
222 |
|
223 |
/** |
224 |
* @param viewer |
225 |
*/ |
226 |
public XmlCommentFormattingStrategy(ISourceViewer viewer) { |
227 |
super(viewer); |
228 |
fIndentations = new LinkedList(); |
229 |
fPartitions = new LinkedList(); |
230 |
fNormalizers = new Normalizer[] {}; |
231 |
} |
232 |
|
233 |
/* |
234 |
* (non-Javadoc) |
235 |
* |
236 |
* @see org.eclipse.jface.text.formatter.IFormattingStrategyExtension#format() |
237 |
*/ |
238 |
public void format() { |
239 |
super.format(); |
240 |
Assert.isLegal(fPartitions.size() > 0); |
241 |
Assert.isLegal(fIndentations.size() > 0); |
242 |
|
243 |
final String indent = fIndentations.removeFirst().toString(); |
244 |
final CommentPartitionDecorator partition = (CommentPartitionDecorator) fPartitions |
245 |
.removeFirst(); |
246 |
|
247 |
// normalize length |
248 |
// normalize char pattern |
249 |
// format text |
250 |
// normalize |
251 |
|
252 |
try { |
253 |
|
254 |
for (int i = 0; i < fNormalizers.length; i++) { |
255 |
partition.replaceWith(fNormalizers[i].safelyNormalize(partition |
256 |
.getText())); |
257 |
} |
258 |
|
259 |
} catch (BadLocationException e) { |
260 |
// TODO Auto-generated catch block |
261 |
e.printStackTrace(); |
262 |
} |
263 |
|
264 |
} |
265 |
|
266 |
/* |
267 |
* @see org.eclipse.jface.text.formatter.ContextBasedFormattingStrategy#formatterStarts(org.eclipse.jface.text.formatter.IFormattingContext) |
268 |
*/ |
269 |
public void formatterStarts(IFormattingContext context) { |
270 |
super.formatterStarts(context); |
271 |
|
272 |
final FormattingContext current = (FormattingContext) context; |
273 |
fIndentations.addLast(current |
274 |
.getProperty(FormattingContextProperties.CONTEXT_INDENTATION)); |
275 |
|
276 |
fPartitions.addLast(CommentPartitionDecorator.decorate(this.getViewer() |
277 |
.getDocument(), (Position) current |
278 |
.getProperty(FormattingContextProperties.CONTEXT_PARTITION))); |
279 |
} |
280 |
|
281 |
/* |
282 |
* @see org.eclipse.jface.text.formatter.ContextBasedFormattingStrategy#formatterStops() |
283 |
*/ |
284 |
public void formatterStops() { |
285 |
super.formatterStops(); |
286 |
fIndentations.clear(); |
287 |
fPartitions.clear(); |
288 |
} |
289 |
} |