Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: f97184d5317db525cbb5238b33d2e042be5b65a5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*******************************************************************************
 * Copyright (c) 2000, 2006 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.cdt.internal.corext.util;

import java.util.Map;

import org.eclipse.text.edits.TextEdit;

import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.ToolFactory;
import org.eclipse.cdt.core.formatter.CodeFormatter;
import org.eclipse.cdt.core.formatter.DefaultCodeFormatterConstants;
import org.eclipse.cdt.core.model.ICProject;

public class CodeFormatterUtil {

	/**
	 * Creates a string that represents the given number of indentation units.
	 * The returned string can contain tabs and/or spaces depending on the core
	 * formatter preferences.
	 * 
	 * @param indentationUnits the number of indentation units to generate
	 * @param project the project from which to get the formatter settings,
	 *        <code>null</code> if the workspace default should be used
	 * @return the indent string
	 */
	public static String createIndentString(int indentationUnits, ICProject project) {
		Map<String, String> options= project != null ? project.getOptions(true) : CCorePlugin.getOptions();		
		return ToolFactory.createDefaultCodeFormatter(options).createIndentationString(indentationUnits);
	} 
		
	/**
	 * Gets the current tab width.
	 * 
	 * @param project The project where the source is used, used for project
	 *        specific options or <code>null</code> if the project is unknown
	 *        and the workspace default should be used
	 * @return The tab width
	 */
	public static int getTabWidth(ICProject project) {
		/*
		 * If the tab-char is SPACE, FORMATTER_INDENTATION_SIZE is not used
		 * by the core formatter.
		 * We piggy back the visual tab length setting in that preference in
		 * that case.
		 */
		String key;
		if (CCorePlugin.SPACE.equals(getCoreOption(project, DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR)))
			key= DefaultCodeFormatterConstants.FORMATTER_INDENTATION_SIZE;
		else
			key= DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE;
		
		return getCoreOption(project, key, 4);
	}

	/**
	 * Returns the current indent width.
	 * 
	 * @param project the project where the source is used or <code>null</code>
	 *        if the project is unknown and the workspace default should be used
	 * @return the indent width
	 */
	public static int getIndentWidth(ICProject project) {
		String key;
		if (DefaultCodeFormatterConstants.MIXED.equals(getCoreOption(project, DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR)))
			key= DefaultCodeFormatterConstants.FORMATTER_INDENTATION_SIZE;
		else
			key= DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE;
		
		return getCoreOption(project, key, 4);
	}

	/**
	 * Returns the possibly <code>project</code>-specific core preference
	 * defined under <code>key</code>.
	 * 
	 * @param project the project to get the preference from, or
	 *        <code>null</code> to get the global preference
	 * @param key the key of the preference
	 * @return the value of the preference
	 */
	private static String getCoreOption(ICProject project, String key) {
		if (project == null)
			return CCorePlugin.getOption(key);
		return project.getOption(key, true);
	}

	/**
	 * Returns the possibly <code>project</code>-specific core preference
	 * defined under <code>key</code>, or <code>def</code> if the value is
	 * not a integer.
	 * 
	 * @param project the project to get the preference from, or
	 *        <code>null</code> to get the global preference
	 * @param key the key of the preference
	 * @param def the default value
	 * @return the value of the preference
	 */
	private static int getCoreOption(ICProject project, String key, int def) {
		try {
			return Integer.parseInt(getCoreOption(project, key));
		} catch (NumberFormatException e) {
			return def;
		}
	}

	/**
	 * Creates edits that describe how to format the given string. Returns <code>null</code> if the code could not be formatted for the given kind.
	 * @throws IllegalArgumentException If the offset and length are not inside the string, a
	 *  IllegalArgumentException is thrown.
	 */
	public static TextEdit format(int kind, String source, int offset, int length, int indentationLevel, String lineSeparator, Map<String, String> options) {
		if (offset < 0 || length < 0 || offset + length > source.length()) {
			throw new IllegalArgumentException("offset or length outside of string. offset: " + offset + ", length: " + length + ", string size: " + source.length());   //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
		}
		CodeFormatter formatter = ToolFactory.createCodeFormatter(options);
		if (formatter != null) {
			return formatter.format(kind, source, offset, length, indentationLevel, lineSeparator);
		}
		return null;
	}
	
	public static TextEdit format(int kind, String source, int indentationLevel, String lineSeparator, Map<String, String> options) {
		String prefix= ""; //$NON-NLS-1$
		String suffix= ""; //$NON-NLS-1$
		switch (kind) {
		case CodeFormatter.K_EXPRESSION:
			prefix= "int __dummy__="; //$NON-NLS-1$
			suffix= ";"; //$NON-NLS-1$
			break;
		case CodeFormatter.K_STATEMENTS:
			prefix= "void __dummy__() {"; //$NON-NLS-1$
			suffix= "}"; //$NON-NLS-1$
			--indentationLevel;
			break;
		}
		String tuSource= prefix + source + suffix;
		TextEdit edit= format(CodeFormatter.K_TRANSLATION_UNIT, tuSource, prefix.length(), source.length(), indentationLevel, lineSeparator, options);
		if (edit != null && prefix.length() > 0) {
			edit.moveTree(-prefix.length());
		}
		return edit;
	}
	
	/**
	 * @return The formatter tab width on workspace level.
	 */
	public static int getTabWidth() {
		return getTabWidth(null);
	}
}

Back to the top