1 /*******************************************************************************
2 * Copyright (c) 2000, 2004 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.internal.corext.util;
13 //import java.util.Map;
15 import net.sourceforge.phpdt.core.ToolFactory;
16 import net.sourceforge.phpdt.core.formatter.DefaultCodeFormatterConstants;
18 //import net.sourceforge.phpdt.internal.corext.Assert;
19 import org.eclipse.core.runtime.Assert;
20 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
22 import org.eclipse.core.runtime.Preferences;
23 import org.eclipse.jface.text.BadLocationException;
24 import org.eclipse.jface.text.BadPositionCategoryException;
25 import org.eclipse.jface.text.DefaultPositionUpdater;
26 import org.eclipse.jface.text.Document;
27 import org.eclipse.jface.text.Position;
28 //import org.eclipse.text.edits.DeleteEdit;
29 //import org.eclipse.text.edits.InsertEdit;
30 //import org.eclipse.text.edits.MultiTextEdit;
31 //import org.eclipse.text.edits.ReplaceEdit;
32 import org.eclipse.text.edits.TextEdit;
34 public class CodeFormatterUtil {
37 * Creates a string that represents the given number of indents (can be
40 public static String createIndentString(int indent) {
41 // axelcl change start
42 // String str= format(CodeFormatter.K_EXPRESSION, "x", indent, null, "",
43 // (Map) null); //$NON-NLS-1$ //$NON-NLS-2$
44 String str = ToolFactory.createCodeFormatter().format("x", indent,
46 return str.substring(0, str.indexOf('x'));
50 public static int getTabWidth() {
51 Preferences preferences = PHPeclipsePlugin.getDefault()
52 .getPluginPreferences();
54 .getInt(DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE);
60 * Old API. Consider to use format2 (TextEdit)
62 // public static String format(int kind, String string, int
63 // indentationLevel, int[] positions, String lineSeparator, Map options) {
64 // return format(kind, string, 0, string.length(), indentationLevel,
65 // positions, lineSeparator, options);
68 // public static String format(int kind, String string, int
69 // indentationLevel, int[] positions, String lineSeparator, IJavaProject
71 // Map options= project != null ? project.getOptions(true) : null;
72 // return format(kind, string, 0, string.length(), indentationLevel,
73 // positions, lineSeparator, options);
77 * Old API. Consider to use format2 (TextEdit)
79 // public static String format(int kind, String string, int offset, int
80 // length, int indentationLevel, int[] positions, String lineSeparator, Map
82 // TextEdit edit= format2(kind, string, offset, length, indentationLevel,
83 // lineSeparator, options);
84 // if (edit == null) {
85 // //JavaPlugin.logErrorMessage("formatter failed to format (no edit
86 // returned). Will use unformatted text instead. kind: " + kind + ", string:
87 // " + string); //$NON-NLS-1$ //$NON-NLS-2$
88 // return string.substring(offset, offset + length);
90 // String formatted= getOldAPICompatibleResult(string, edit,
91 // indentationLevel, positions, lineSeparator, options);
92 // return formatted.substring(offset, formatted.length() - (string.length()
93 // - (offset + length)));
96 * Old API. Consider to use format2 (TextEdit)
98 // public static String format(ASTNode node, String string, int
99 // indentationLevel, int[] positions, String lineSeparator, Map options) {
101 // TextEdit edit= format2(node, string, indentationLevel, lineSeparator,
103 // if (edit == null) {
104 // //JavaPlugin.logErrorMessage("formatter failed to format (no edit
105 // returned). Will use unformatted text instead. node: " +
106 // node.getNodeType() + ", string: " + string); //$NON-NLS-1$ //$NON-NLS-2$
109 // return getOldAPICompatibleResult(string, edit, indentationLevel,
110 // positions, lineSeparator, options);
112 // private static String getOldAPICompatibleResult(String string,
113 // TextEdit edit, int indentationLevel, int[] positions,
114 // String lineSeparator, Map options) {
115 // Position[] p = null;
117 // if (positions != null) {
118 // p = new Position[positions.length];
119 // for (int i = 0; i < positions.length; i++) {
120 // p[i] = new Position(positions[i], 0);
123 // String res = evaluateFormatterEdit(string, edit, p);
125 // if (positions != null) {
126 // for (int i = 0; i < positions.length; i++) {
127 // Position curr = p[i];
128 // positions[i] = curr.getOffset();
135 * Evaluates the edit on the given string.
137 * @throws IllegalArgumentException
138 * If the positions are not inside the string, a
139 * IllegalArgumentException is thrown.
141 public static String evaluateFormatterEdit(String string, TextEdit edit,
142 Position[] positions) {
144 Document doc = createDocument(string, positions);
146 if (positions != null) {
147 for (int i = 0; i < positions.length; i++) {
148 Assert.isTrue(!positions[i].isDeleted,
149 "Position got deleted"); //$NON-NLS-1$
153 } catch (BadLocationException e) {
154 PHPeclipsePlugin.log(e); // bug in the formatter
158 "Fromatter created edits with wrong positions: " + e.getMessage()); //$NON-NLS-1$
164 * Creates edits that describe how to format the given string. Returns
165 * <code>null</code> if the code could not be formatted for the given
168 * @throws IllegalArgumentException
169 * If the offset and length are not inside the string, a
170 * IllegalArgumentException is thrown.
172 // public static TextEdit format2(int kind, String string, int offset, int
173 // length, int indentationLevel, String lineSeparator, Map options) {
174 // if (offset < 0 || length < 0 || offset + length > string.length()) {
175 // throw new IllegalArgumentException("offset or length outside of string.
176 // offset: " + offset + ", length: " + length + ", string size: " +
177 // string.length()); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
180 // return createCodeFormatter(options).format(kind, string, offset, length,
181 // indentationLevel, lineSeparator);
184 // public static TextEdit format2(int kind, String string, int
185 // indentationLevel, String lineSeparator, Map options) {
186 // return format2(kind, string, 0, string.length(), indentationLevel,
187 // lineSeparator, options);
190 * Creates edits that describe how to format the given string. Returns
191 * <code>null</code> if the code could not be formatted for the given
194 * @throws IllegalArgumentException
195 * If the offset and length are not inside the string, a
196 * IllegalArgumentException is thrown.
198 // public static TextEdit format2(ASTNode node, String str, int
199 // indentationLevel, String lineSeparator, Map options) {
201 // String prefix= ""; //$NON-NLS-1$
202 // String suffix= ""; //$NON-NLS-1$
203 // if (node instanceof Statement) {
204 // code= CodeFormatter.K_STATEMENTS;
205 // if (node.getNodeType() == ASTNode.SWITCH_CASE) {
206 // prefix= "switch(1) {"; //$NON-NLS-1$
207 // suffix= "}"; //$NON-NLS-1$
208 // code= CodeFormatter.K_STATEMENTS;
210 // } else if (node instanceof Expression && node.getNodeType() !=
211 // ASTNode.VARIABLE_DECLARATION_EXPRESSION) {
212 // code= CodeFormatter.K_EXPRESSION;
214 // switch (node.getNodeType()) {
215 // case ASTNode.METHOD_DECLARATION:
216 // case ASTNode.TYPE_DECLARATION:
217 // case ASTNode.FIELD_DECLARATION:
218 // case ASTNode.INITIALIZER:
219 // code= CodeFormatter.K_CLASS_BODY_DECLARATIONS;
221 // case ASTNode.ARRAY_TYPE:
222 // case ASTNode.PRIMITIVE_TYPE:
223 // case ASTNode.SIMPLE_TYPE:
224 // suffix= " x;"; //$NON-NLS-1$
225 // code= CodeFormatter.K_EXPRESSION;
227 // case ASTNode.COMPILATION_UNIT:
228 // code= CodeFormatter.K_COMPILATION_UNIT;
230 // case ASTNode.VARIABLE_DECLARATION_EXPRESSION:
231 // case ASTNode.SINGLE_VARIABLE_DECLARATION:
232 // suffix= ";"; //$NON-NLS-1$
233 // code= CodeFormatter.K_STATEMENTS;
235 // case ASTNode.VARIABLE_DECLARATION_FRAGMENT:
236 // prefix= "A "; //$NON-NLS-1$
237 // suffix= ";"; //$NON-NLS-1$
238 // code= CodeFormatter.K_STATEMENTS;
240 // case ASTNode.PACKAGE_DECLARATION:
241 // case ASTNode.IMPORT_DECLARATION:
242 // suffix= "\nclass A {}"; //$NON-NLS-1$
243 // code= CodeFormatter.K_COMPILATION_UNIT;
245 // case ASTNode.JAVADOC:
246 // suffix= "void foo();"; //$NON-NLS-1$
247 // code= CodeFormatter.K_CLASS_BODY_DECLARATIONS;
249 // case ASTNode.CATCH_CLAUSE:
250 // prefix= "try {}"; //$NON-NLS-1$
251 // code= CodeFormatter.K_STATEMENTS;
253 // case ASTNode.ANONYMOUS_CLASS_DECLARATION:
254 // prefix= "new A()"; //$NON-NLS-1$
255 // suffix= ";"; //$NON-NLS-1$
256 // code= CodeFormatter.K_STATEMENTS;
258 // case ASTNode.MEMBER_REF:
259 // case ASTNode.METHOD_REF:
260 // case ASTNode.METHOD_REF_PARAMETER:
261 // case ASTNode.TAG_ELEMENT:
262 // case ASTNode.TEXT_ELEMENT:
263 // // not yet supported
266 // Assert.isTrue(false, "Node type not covered: " +
267 // node.getClass().getName()); //$NON-NLS-1$
272 // String concatStr= prefix + str + suffix;
273 // TextEdit edit= format2(code, concatStr, prefix.length(), str.length(),
274 // indentationLevel, lineSeparator, options);
275 // if (prefix.length() > 0) {
276 // edit= shifEdit(edit, prefix.length());
280 // private static TextEdit shifEdit(TextEdit oldEdit, int diff) {
282 // if (oldEdit instanceof ReplaceEdit) {
283 // ReplaceEdit edit = (ReplaceEdit) oldEdit;
284 // newEdit = new ReplaceEdit(edit.getOffset() - diff,
285 // edit.getLength(), edit.getText());
286 // } else if (oldEdit instanceof InsertEdit) {
287 // InsertEdit edit = (InsertEdit) oldEdit;
288 // newEdit = new InsertEdit(edit.getOffset() - diff, edit.getText());
289 // } else if (oldEdit instanceof DeleteEdit) {
290 // DeleteEdit edit = (DeleteEdit) oldEdit;
291 // newEdit = new DeleteEdit(edit.getOffset() - diff, edit.getLength());
292 // } else if (oldEdit instanceof MultiTextEdit) {
293 // newEdit = new MultiTextEdit();
295 // return null; // not supported
297 // TextEdit[] children = oldEdit.getChildren();
298 // for (int i = 0; i < children.length; i++) {
299 // TextEdit shifted = shifEdit(children[i], diff);
300 // if (shifted != null) {
301 // newEdit.addChild(shifted);
307 private static Document createDocument(String string, Position[] positions)
308 throws IllegalArgumentException {
309 Document doc = new Document(string);
311 if (positions != null) {
312 final String POS_CATEGORY = "myCategory"; //$NON-NLS-1$
314 doc.addPositionCategory(POS_CATEGORY);
316 .addPositionUpdater(new DefaultPositionUpdater(
318 protected boolean notDeleted() {
319 if (fOffset < fPosition.offset
320 && (fPosition.offset + fPosition.length < fOffset
322 fPosition.offset = fOffset + fLength; // deleted
334 for (int i = 0; i < positions.length; i++) {
336 doc.addPosition(POS_CATEGORY, positions[i]);
337 } catch (BadLocationException e) {
338 throw new IllegalArgumentException(
339 "Position outside of string. offset: " + positions[i].offset + ", length: " + positions[i].length + ", string size: " + string.length()); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
343 } catch (BadPositionCategoryException cannotHappen) {
344 // can not happen: category is correctly set up