1
/*******************************************************************************
2
* Copyright (c) 2000, 2011 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
9
* IBM Corporation - initial API and implementation
10
* Markus Schorn (Wind River Systems)
11
* Andrew Ferguson (Symbian)
12
* Anton Leherbauer (Wind River Systems)
13
* oyvind.harboe@zylin.com - http://bugs.eclipse.org/250638
14
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
15
*******************************************************************************/
16
package org.eclipse.cdt.core;
18
import java.io.IOException;
20
import java.util.ArrayList;
21
import java.util.HashMap;
22
import java.util.HashSet;
23
import java.util.MissingResourceException;
24
import java.util.ResourceBundle;
26
import org.eclipse.cdt.core.cdtvariables.ICdtVariableManager;
27
import org.eclipse.cdt.core.cdtvariables.IUserVarSupplier;
28
import org.eclipse.cdt.core.dom.IPDOMManager;
29
import org.eclipse.cdt.core.envvar.IEnvironmentVariableManager;
30
import org.eclipse.cdt.core.index.IIndexManager;
31
import org.eclipse.cdt.core.model.CModelException;
32
import org.eclipse.cdt.core.model.CoreModel;
33
import org.eclipse.cdt.core.model.ILanguage;
34
import org.eclipse.cdt.core.model.ITranslationUnit;
35
import org.eclipse.cdt.core.model.IWorkingCopy;
36
import org.eclipse.cdt.core.parser.IScannerInfoProvider;
37
import org.eclipse.cdt.core.resources.IConsole;
38
import org.eclipse.cdt.core.resources.IPathEntryVariableManager;
39
import org.eclipse.cdt.core.settings.model.ICConfigExtensionReference;
40
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
41
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
42
import org.eclipse.cdt.core.settings.model.ICProjectDescriptionManager;
43
import org.eclipse.cdt.core.settings.model.WriteAccessException;
44
import org.eclipse.cdt.core.settings.model.util.CDataUtil;
45
import org.eclipse.cdt.internal.core.CContentTypes;
46
import org.eclipse.cdt.internal.core.CDTLogWriter;
47
import org.eclipse.cdt.internal.core.CdtVarPathEntryVariableManager;
48
import org.eclipse.cdt.internal.core.ICConsole;
49
import org.eclipse.cdt.internal.core.PositionTrackerManager;
50
import org.eclipse.cdt.internal.core.cdtvariables.CdtVariableManager;
51
import org.eclipse.cdt.internal.core.cdtvariables.UserVarSupplier;
52
import org.eclipse.cdt.internal.core.envvar.EnvironmentVariableManager;
53
import org.eclipse.cdt.internal.core.model.CModelManager;
54
import org.eclipse.cdt.internal.core.model.Util;
55
import org.eclipse.cdt.internal.core.pdom.PDOMManager;
56
import org.eclipse.cdt.internal.core.resources.ResourceLookup;
57
import org.eclipse.cdt.internal.core.settings.model.CProjectDescriptionManager;
58
import org.eclipse.cdt.internal.core.settings.model.ExceptionFactory;
59
import org.eclipse.cdt.internal.errorparsers.ErrorParserExtensionManager;
60
import org.eclipse.core.resources.ICommand;
61
import org.eclipse.core.resources.IProject;
62
import org.eclipse.core.resources.IProjectDescription;
63
import org.eclipse.core.resources.IResource;
64
import org.eclipse.core.resources.IWorkspace;
65
import org.eclipse.core.resources.IWorkspaceRunnable;
66
import org.eclipse.core.resources.ResourcesPlugin;
67
import org.eclipse.core.runtime.CoreException;
68
import org.eclipse.core.runtime.IConfigurationElement;
69
import org.eclipse.core.runtime.IExtension;
70
import org.eclipse.core.runtime.IExtensionPoint;
71
import org.eclipse.core.runtime.IExtensionRegistry;
72
import org.eclipse.core.runtime.IProgressMonitor;
73
import org.eclipse.core.runtime.IStatus;
74
import org.eclipse.core.runtime.NullProgressMonitor;
75
import org.eclipse.core.runtime.OperationCanceledException;
76
import org.eclipse.core.runtime.Platform;
77
import org.eclipse.core.runtime.Plugin;
78
import org.eclipse.core.runtime.Preferences;
79
import org.eclipse.core.runtime.QualifiedName;
80
import org.eclipse.core.runtime.Status;
81
import org.eclipse.core.runtime.SubProgressMonitor;
82
import org.eclipse.core.runtime.content.IContentType;
83
import org.eclipse.core.runtime.jobs.Job;
84
import org.eclipse.core.runtime.preferences.InstanceScope;
85
import org.osgi.framework.BundleContext;
87
import com.ibm.icu.text.MessageFormat;
90
* CCorePlugin is the life-cycle owner of the core plug-in, and starting point for access to many core APIs.
92
* @noextend This class is not intended to be subclassed by clients.
93
* @noinstantiate This class is not intended to be instantiated by clients.
95
public class CCorePlugin extends Plugin {
97
public static final int STATUS_CDTPROJECT_EXISTS = 1;
98
public static final int STATUS_CDTPROJECT_MISMATCH = 2;
99
public static final int CDT_PROJECT_NATURE_ID_MISMATCH = 3;
101
* Status code for core exception that is thrown if a pdom grew larger than the supported limit.
104
public static final int STATUS_PDOM_TOO_LARGE = 4;
106
public static final String PLUGIN_ID = "org.eclipse.cdt.core"; //$NON-NLS-1$
108
public static final String BUILDER_MODEL_ID = PLUGIN_ID + ".CBuildModel"; //$NON-NLS-1$
109
public static final String BINARY_PARSER_SIMPLE_ID = "BinaryParser"; //$NON-NLS-1$
110
public final static String BINARY_PARSER_UNIQ_ID = PLUGIN_ID + "." + BINARY_PARSER_SIMPLE_ID; //$NON-NLS-1$
111
public final static String PREF_BINARY_PARSER = "binaryparser"; //$NON-NLS-1$
112
public final static String DEFAULT_BINARY_PARSER_SIMPLE_ID = "ELF"; //$NON-NLS-1$
113
public final static String DEFAULT_BINARY_PARSER_UNIQ_ID = PLUGIN_ID + "." + DEFAULT_BINARY_PARSER_SIMPLE_ID; //$NON-NLS-1$
114
public final static String PREF_USE_STRUCTURAL_PARSE_MODE = "useStructualParseMode"; //$NON-NLS-1$
116
public static final String INDEX_SIMPLE_ID = "CIndex"; //$NON-NLS-1$
117
public static final String INDEX_UNIQ_ID = PLUGIN_ID + "." + INDEX_SIMPLE_ID; //$NON-NLS-1$
119
public static final String INDEXER_SIMPLE_ID = "CIndexer"; //$NON-NLS-1$
120
public static final String INDEXER_UNIQ_ID = PLUGIN_ID + "." + INDEXER_SIMPLE_ID; //$NON-NLS-1$
121
public static final String PREF_INDEXER = "indexer"; //$NON-NLS-1$
122
public static final String DEFAULT_INDEXER = IPDOMManager.ID_FAST_INDEXER;
125
* Name of the extension point for contributing an error parser
127
public final static String ERROR_PARSER_SIMPLE_ID = "ErrorParser"; //$NON-NLS-1$
129
* Full unique name of the extension point for contributing an error parser
131
public final static String ERROR_PARSER_UNIQ_ID = PLUGIN_ID + "." + ERROR_PARSER_SIMPLE_ID; //$NON-NLS-1$
133
// default store for pathentry
134
public final static String DEFAULT_PATHENTRY_STORE_ID = PLUGIN_ID + ".cdtPathEntryStore"; //$NON-NLS-1$
136
// Build Model Interface Discovery
137
public final static String BUILD_SCANNER_INFO_SIMPLE_ID = "ScannerInfoProvider"; //$NON-NLS-1$
138
public final static String BUILD_SCANNER_INFO_UNIQ_ID = PLUGIN_ID + "." + BUILD_SCANNER_INFO_SIMPLE_ID; //$NON-NLS-1$
140
public static final String DEFAULT_PROVIDER_ID = CCorePlugin.PLUGIN_ID + ".defaultConfigDataProvider"; //$NON-NLS-1$
142
private final static String SCANNER_INFO_PROVIDER2_NAME = "ScannerInfoProvider2"; //$NON-NLS-1$
143
private final static String SCANNER_INFO_PROVIDER2 = PLUGIN_ID + "." + SCANNER_INFO_PROVIDER2_NAME; //$NON-NLS-1$
146
* Name of the extension point for contributing a source code formatter
148
public static final String FORMATTER_EXTPOINT_ID = "CodeFormatter" ; //$NON-NLS-1$
151
* Possible configurable option ID.
152
* @see #getDefaultOptions
154
public static final String CORE_ENCODING = PLUGIN_ID + ".encoding"; //$NON-NLS-1$
157
* IContentType id for C Source Unit
159
public final static String CONTENT_TYPE_CSOURCE = "org.eclipse.cdt.core.cSource"; //$NON-NLS-1$
161
* IContentType id for C Header Unit
163
public final static String CONTENT_TYPE_CHEADER = "org.eclipse.cdt.core.cHeader"; //$NON-NLS-1$
165
* IContentType id for C++ Source Unit
167
public final static String CONTENT_TYPE_CXXSOURCE = "org.eclipse.cdt.core.cxxSource"; //$NON-NLS-1$
169
* IContentType id for C++ Header Unit
171
public final static String CONTENT_TYPE_CXXHEADER = "org.eclipse.cdt.core.cxxHeader"; //$NON-NLS-1$
173
* IContentType id for ASM Unit
175
public final static String CONTENT_TYPE_ASMSOURCE = "org.eclipse.cdt.core.asmSource"; //$NON-NLS-1$
177
* IContentType id for Binary Files
179
public final static String CONTENT_TYPE_BINARYFILE = "org.eclipse.cdt.core.binaryFile"; //$NON-NLS-1$
182
* Possible configurable option value.
183
* @see #getDefaultOptions()
185
public static final String INSERT = "insert"; //$NON-NLS-1$
187
* Possible configurable option value.
188
* @see #getDefaultOptions()
190
public static final String DO_NOT_INSERT = "do not insert"; //$NON-NLS-1$
192
* Possible configurable option value.
193
* @see #getDefaultOptions()
195
public static final String TAB = "tab"; //$NON-NLS-1$
197
* Possible configurable option value.
198
* @see #getDefaultOptions()
200
public static final String SPACE = "space"; //$NON-NLS-1$
202
private static CCorePlugin fgCPlugin;
203
private static ResourceBundle fgResourceBundle;
206
* @noreference This field is not intended to be referenced by clients.
208
public CDTLogWriter cdtLog = null;
210
private volatile CProjectDescriptionManager fNewCProjectDescriptionManager;
212
private CoreModel fCoreModel;
214
private PDOMManager pdomManager;
216
private CdtVarPathEntryVariableManager fPathEntryVariableManager;
218
private final class NullConsole implements IConsole {
219
private ConsoleOutputStream nullStream = new ConsoleOutputStream() {
221
public void write(byte[] b) throws IOException {
224
public void write(byte[] b, int off, int len) throws IOException {
227
public void write(int c) throws IOException {
230
public void start(IProject project) {
232
public ConsoleOutputStream getOutputStream() {
235
public ConsoleOutputStream getInfoStream() {
238
public ConsoleOutputStream getErrorStream() {
243
// -------- static methods --------
247
fgResourceBundle = ResourceBundle.getBundle("org.eclipse.cdt.internal.core.CCorePluginResources"); //$NON-NLS-1$
248
} catch (MissingResourceException x) {
249
fgResourceBundle = null;
254
* Returns the shared working copies currently registered for the default buffer factory.
257
public static IWorkingCopy[] getSharedWorkingCopies() {
258
return CModelManager.getDefault().getSharedWorkingCopies(null);
261
public static String getResourceString(String key) {
263
return fgResourceBundle.getString(key);
264
} catch (MissingResourceException e) {
265
return "!" + key + "!"; //$NON-NLS-1$ //$NON-NLS-2$
266
} catch (NullPointerException e) {
267
return "#" + key + "#"; //$NON-NLS-1$ //$NON-NLS-2$
271
public static IWorkspace getWorkspace() {
272
return ResourcesPlugin.getWorkspace();
275
public static String getFormattedString(String key, String arg) {
276
return MessageFormat.format(getResourceString(key), new Object[] { arg });
279
@SuppressWarnings("cast") // java.text.MessageFormat would require the cast
280
public static String getFormattedString(String key, String[] args) {
281
return MessageFormat.format(getResourceString(key), (Object[])args);
284
public static ResourceBundle getResourceBundle() {
285
return fgResourceBundle;
288
public static IPositionTrackerManager getPositionTrackerManager() {
289
return PositionTrackerManager.getInstance();
292
public static CCorePlugin getDefault() {
298
* @see Plugin#shutdown
301
public void stop(BundleContext context) throws Exception {
303
pdomManager.shutdown();
305
PositionTrackerManager.getInstance().uninstall();
307
// if (fDescriptorManager != null) {
308
// fDescriptorManager.shutdown();
311
if (fCoreModel != null) {
312
fCoreModel.shutdown();
315
if (cdtLog != null) {
319
if (fPathEntryVariableManager != null) {
320
fPathEntryVariableManager.shutdown();
323
fNewCProjectDescriptionManager.shutdown();
324
ResourceLookup.shutdown();
326
savePluginPreferences();
333
* @see Plugin#startup
336
public void start(BundleContext context) throws Exception {
337
super.start(context);
339
// do harmless stuff first.
340
cdtLog = new CDTLogWriter(CCorePlugin.getDefault().getStateLocation().append(".log").toFile()); //$NON-NLS-1$
341
configurePluginDebugOptions();
342
PositionTrackerManager.getInstance().install();
343
ResourceLookup.startup();
345
// new project model needs to register the resource listener first.
346
CProjectDescriptionManager descManager = CProjectDescriptionManager.getInstance();
347
final Job post1 = descManager.startup();
348
fNewCProjectDescriptionManager = descManager;
350
fPathEntryVariableManager = new CdtVarPathEntryVariableManager();
351
fPathEntryVariableManager.startup();
353
fCoreModel = CoreModel.getDefault();
354
fCoreModel.startup();
356
pdomManager = new PDOMManager();
357
final Job post2= pdomManager.startup();
359
// bug 186755, when started after the platform has been started the job manager
360
// is no longer suspended. So we have to start a job at the very end to make
361
// sure we don't trigger a concurrent plug-in activation from within the job.
367
* TODO: Add all options here
368
* Returns a table of all known configurable options with their default values.
369
* These options allow to configure the behavior of the underlying components.
370
* The client may safely use the result as a template that they can modify and
371
* then pass to <code>setOptions</code>.
373
* Helper constants have been defined on CCorePlugin for each of the option ID and
374
* their possible constant values.
376
* Note: more options might be added in further releases.
378
* RECOGNIZED OPTIONS:
380
* CORE / Specify Default Source Encoding Format
381
* Get the encoding format for translated sources. This setting is read-only, it is equivalent
382
* to 'ResourcesPlugin.getEncoding()'.
383
* - option id: "org.eclipse.cdt.core.encoding"
384
* - possible values: { any of the supported encoding names}.
385
* - default: <platform default>
388
* @return a mutable map containing the default settings of all known options
389
* (key type: <code>String</code>; value type: <code>String</code>)
392
public static HashMap<String, String> getDefaultOptions() {
393
HashMap<String, String> defaultOptions = new HashMap<String, String>(10);
395
// see #initializeDefaultPluginPreferences() for changing default settings
396
Preferences preferences = getDefault().getPluginPreferences();
397
HashSet<String> optionNames = CModelManager.OptionNames;
399
// get preferences set to their default
400
for (String propertyName : preferences.defaultPropertyNames()){
401
if (optionNames.contains(propertyName))
402
defaultOptions.put(propertyName, preferences.getDefaultString(propertyName));
404
// get preferences not set to their default
405
for (String propertyName : preferences.propertyNames()) {
406
if (optionNames.contains(propertyName))
407
defaultOptions.put(propertyName, preferences.getDefaultString(propertyName));
409
// get encoding through resource plugin
410
defaultOptions.put(CORE_ENCODING, ResourcesPlugin.getEncoding());
412
return defaultOptions;
416
* Helper method for returning one option value only. Equivalent to <code>(String)CCorePlugin.getOptions().get(optionName)</code>
417
* Note that it may answer <code>null</code> if this option does not exist.
419
* For a complete description of the configurable options, see <code>getDefaultOptions</code>.
422
* @param optionName the name of an option
423
* @return the String value of a given option
424
* @see CCorePlugin#getDefaultOptions
426
public static String getOption(String optionName) {
428
if (CORE_ENCODING.equals(optionName)){
429
return ResourcesPlugin.getEncoding();
431
if (CModelManager.OptionNames.contains(optionName)){
432
Preferences preferences = getDefault().getPluginPreferences();
433
return preferences.getString(optionName).trim();
439
* Returns the table of the current options. Initially, all options have their default values,
440
* and this method returns a table that includes all known options.
442
* For a complete description of the configurable options, see <code>getDefaultOptions</code>.
445
* @return table of current settings of all options
446
* (key type: <code>String</code>; value type: <code>String</code>)
447
* @see CCorePlugin#getDefaultOptions
449
public static HashMap<String, String> getOptions() {
450
HashMap<String, String> options = new HashMap<String, String>(10);
452
// see #initializeDefaultPluginPreferences() for changing default settings
453
Plugin plugin = getDefault();
454
if (plugin != null) {
455
Preferences preferences = plugin.getPluginPreferences();
456
HashSet<String> optionNames = CModelManager.OptionNames;
458
// get preferences set to their default
459
for (String propertyName : preferences.defaultPropertyNames()){
460
if (optionNames.contains(propertyName)){
461
options.put(propertyName, preferences.getDefaultString(propertyName));
464
// get preferences not set to their default
465
for (String propertyName : preferences.propertyNames()){
466
if (optionNames.contains(propertyName)){
467
options.put(propertyName, preferences.getString(propertyName).trim());
470
// get encoding through resource plugin
471
options.put(CORE_ENCODING, ResourcesPlugin.getEncoding());
477
* Sets the current table of options. All and only the options explicitly included in the given table
478
* are remembered; all previous option settings are forgotten, including ones not explicitly
481
* For a complete description of the configurable options, see <code>getDefaultOptions</code>.
484
* @param newOptions the new options (key type: <code>String</code>; value type: <code>String</code>),
485
* or <code>null</code> to reset all options to their default values
486
* @see CCorePlugin#getDefaultOptions
488
public static void setOptions(HashMap<String, String> newOptions) {
490
// see #initializeDefaultPluginPreferences() for changing default settings
491
Preferences preferences = getDefault().getPluginPreferences();
493
if (newOptions == null){
494
newOptions = getDefaultOptions();
496
for (String key : newOptions.keySet()){
497
if (!CModelManager.OptionNames.contains(key)) continue; // unrecognized option
498
if (key.equals(CORE_ENCODING)) continue; // skipped, contributed by resource prefs
499
String value = newOptions.get(key);
500
preferences.setValue(key, value);
504
getDefault().savePluginPreferences();
509
* Create CDT console adapter for build console defined as an extension.
510
* See {@code org.eclipse.cdt.core.CBuildConsole} extension point.
511
* If the console class is instance of {@link ICConsole} it is initialized
512
* with context id, name and icon to be shown in the list of consoles in the
515
* @param extConsoleId - console id defined in the extension point.
516
* @param contextId - context menu id in the Console view. A caller needs to define
517
* a distinct one for own use.
518
* @param name - name of console to appear in the list of consoles in context menu
519
* in the Console view.
520
* @param iconUrl - a {@link URL} of the icon for the context menu of the Console
521
* view. The url is expected to point to an image in eclipse OSGi bundle.
522
* Here is an example how to retrieve URL:<br/>
524
* URL iconUrl = CUIPlugin.getDefault().getBundle().getEntry("icons/obj16/flask.png");
527
* @return CDT console adapter.
529
private IConsole getConsole(String extConsoleId, String contextId, String name, URL iconUrl) {
531
IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(CCorePlugin.PLUGIN_ID, "CBuildConsole"); //$NON-NLS-1$
532
if (extensionPoint != null) {
533
IExtension[] extensions = extensionPoint.getExtensions();
534
for (IExtension extension : extensions) {
535
IConfigurationElement[] configElements = extension.getConfigurationElements();
536
for (IConfigurationElement configElement : configElements) {
537
String consoleID = configElement.getAttribute("id"); //$NON-NLS-1$
538
if ((extConsoleId == null && consoleID == null) || (extConsoleId != null && extConsoleId.equals(consoleID))) {
539
IConsole console = (IConsole) configElement.createExecutableExtension("class"); //$NON-NLS-1$
540
if (console instanceof ICConsole) {
541
((ICConsole) console).init(contextId, name, iconUrl);
548
} catch (CoreException e) {
551
return new NullConsole();
555
* Create CDT console adapter.
556
* The adapter serves as a bridge between core plugin and UI console API in a way that
557
* a user can create a UI console from plugins having no dependencies to UI.
559
* @param id - id of the console specified in extension point to instantiate
561
* @return CDT console adapter.
563
public IConsole getConsole(String id) {
564
return getConsole(id, null, null, null);
568
* Create CDT console adapter for build console. A new instance of class
569
* {@code org.eclipse.cdt.internal.ui.buildconsole.CBuildConsole} is created
570
* and initialized with the parameters.
572
* @param contextId - context menu id in the Console view. A caller needs to define
573
* a distinct one for own use.
574
* @param name - name of console to appear in the list of consoles in context menu
575
* in the Console view.
576
* @param iconUrl - a {@link URL} of the icon for the context menu of the Console
577
* view. The url is expected to point to an image in eclipse OSGi bundle.
578
* Here is an example how to retrieve URL:<br/>
580
* URL iconUrl = CUIPlugin.getDefault().getBundle().getResource("icons/obj16/flask.png");
583
* {@code iconUrl} can be <b>null</b>, in that case the default image is used.
584
* See {@code org.eclipse.cdt.internal.ui.buildconsole.BuildConsole(IBuildConsoleManager, String, String, URL)}
586
* @return CDT console adapter.
590
public IConsole getBuildConsole(String contextId, String name, URL iconUrl) {
591
return getConsole(null, contextId, name, iconUrl);
595
* Create CDT console adapter connected to the default build console.
597
public IConsole getConsole() {
598
String consoleID = System.getProperty("org.eclipse.cdt.core.console"); //$NON-NLS-1$
599
return getConsole(consoleID);
603
* @deprecated Use {@link #getDefaultBinaryParserExtensions(IProject)} instead.
606
public ICExtensionReference[] getBinaryParserExtensions(IProject project) throws CoreException {
607
ICExtensionReference ext[] = new ICExtensionReference[0];
608
if (project != null) {
610
ICDescriptor cdesc = getCProjectDescription(project, false);
613
ICExtensionReference[] cextensions = cdesc.get(BINARY_PARSER_UNIQ_ID, true);
614
if (cextensions != null && cextensions.length > 0)
616
} catch (CoreException e) {
624
* Returns the binary parser extensions for the default settings configuration.
627
public ICConfigExtensionReference[] getDefaultBinaryParserExtensions(IProject project) throws CoreException {
628
ICConfigExtensionReference ext[] = new ICConfigExtensionReference[0];
629
if (project != null) {
630
ICProjectDescription desc = CCorePlugin.getDefault().getProjectDescription(project, false);
632
ICConfigurationDescription cfgDesc = desc.getDefaultSettingConfiguration();
633
if (cfgDesc != null) {
634
ext = cfgDesc.get(CCorePlugin.BINARY_PARSER_UNIQ_ID);
642
* @deprecated - use getBinaryParserExtensions(IProject project)
645
public IBinaryParser[] getBinaryParser(IProject project) throws CoreException {
646
IBinaryParser parsers[] = null;
647
if (project != null) {
649
ICDescriptor cdesc = getCProjectDescription(project, false);
650
ICExtensionReference[] cextensions = cdesc.get(BINARY_PARSER_UNIQ_ID, true);
651
if (cextensions.length > 0) {
652
ArrayList<IBinaryParser> list = new ArrayList<IBinaryParser>(cextensions.length);
653
for (ICExtensionReference ref : cextensions) {
654
IBinaryParser parser = null;
656
parser = (IBinaryParser)ref.createExtension();
657
} catch (ClassCastException e) {
658
log(e); // wrong binary parser definition ?
660
if (parser != null) {
664
parsers = new IBinaryParser[list.size()];
665
list.toArray(parsers);
667
} catch (CoreException e) {
668
// ignore since we fall back to a default....
671
if (parsers == null) {
672
IBinaryParser parser = getDefaultBinaryParser();
673
if (parser != null) {
674
parsers = new IBinaryParser[] {parser};
680
public IBinaryParser getDefaultBinaryParser() throws CoreException {
681
IBinaryParser parser = null;
682
String id = getPluginPreferences().getDefaultString(PREF_BINARY_PARSER);
683
if (id == null || id.length() == 0) {
684
id = DEFAULT_BINARY_PARSER_UNIQ_ID;
686
IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(CCorePlugin.PLUGIN_ID, BINARY_PARSER_SIMPLE_ID);
687
IExtension extension = extensionPoint.getExtension(id);
688
if (extension != null) {
689
IConfigurationElement element[] = extension.getConfigurationElements();
690
for (IConfigurationElement element2 : element) {
691
if (element2.getName().equalsIgnoreCase("cextension")) { //$NON-NLS-1$
692
parser = (IBinaryParser) element2.createExecutableExtension("run"); //$NON-NLS-1$
697
IStatus s = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, -1, CCorePlugin.getResourceString("CCorePlugin.exception.noBinaryFormat"), null); //$NON-NLS-1$
698
throw new CoreException(s);
703
public CoreModel getCoreModel() {
707
public static IIndexManager getIndexManager() {
708
return getDefault().pdomManager;
711
public IPathEntryVariableManager getPathEntryVariableManager() {
712
return fPathEntryVariableManager;
716
* @deprecated use {@link #getProjectDescription(IProject, boolean)} instead
719
public ICDescriptor getCProjectDescription(IProject project) throws CoreException {
720
return fNewCProjectDescriptionManager.getDescriptorManager().getDescriptor(project);
724
* Please use {@link #getProjectDescription(IProject, boolean)} to fetch the
725
* ICProjectDescription for the project. And use {@link ICProjectDescription#getConfigurations()}
726
* to get an array of ICConfigurationDescriptions, which have similar API to ICDescriptor,
727
* allowing you to store settings and configure extensions at the Configuration level
728
* rather than at the project level.
732
* @return ICDescriptor or <b>null</b> if <b>create</b> is <b>false</b> and no .cdtproject file exists on disk.
733
* @throws CoreException
737
public ICDescriptor getCProjectDescription(IProject project, boolean create) throws CoreException {
738
return fNewCProjectDescriptionManager.getDescriptorManager().getDescriptor(project, create);
741
public void mapCProjectOwner(IProject project, String id, boolean override) throws CoreException {
744
fNewCProjectDescriptionManager.getDescriptorManager().configure(project, id);
746
fNewCProjectDescriptionManager.getDescriptorManager().convert(project, id);
748
} catch (Exception e) {
749
throw ExceptionFactory.createCoreException(e);
754
* @deprecated Settings should be set per ICConfigurationDescription rather than
755
* global to the project. Please use {@link #getProjectDescription(IProject, boolean)}
756
* to fetch the ICProjectDescription for the project. And use
757
* {@link ICProjectDescription#getConfigurations()} to get an array of
758
* ICConfigurationDescriptions, which have similar API to ICDescriptor,
759
* allowing you to store settings and configure extensions at the Configuration level
760
* rather than at the project level.
763
public ICDescriptorManager getCDescriptorManager() {
764
return fNewCProjectDescriptionManager.getDescriptorManager();
768
* Creates a C project resource given the project handle and description.
770
* @param description the project description to create a project resource for
771
* @param projectHandle the project handle to create a project resource for
772
* @param monitor the progress monitor to show visual progress with
773
* @param projectID required for mapping the project to an owner
775
* @exception CoreException if the operation fails
776
* @exception OperationCanceledException if the operation is canceled
778
public IProject createCProject(
779
final IProjectDescription description,
780
final IProject projectHandle,
781
IProgressMonitor monitor,
782
final String projectID)
783
throws CoreException, OperationCanceledException {
785
getWorkspace().run(new IWorkspaceRunnable() {
786
public void run(IProgressMonitor monitor) throws CoreException {
788
if (monitor == null) {
789
monitor = new NullProgressMonitor();
791
monitor.beginTask("Creating C Project...", 3); //$NON-NLS-1$
792
if (!projectHandle.exists()) {
793
projectHandle.create(description, new SubProgressMonitor(monitor, 1));
796
if (monitor.isCanceled()) {
797
throw new OperationCanceledException();
801
projectHandle.open(IResource.BACKGROUND_REFRESH, new SubProgressMonitor(monitor, 1));
803
mapCProjectOwner(projectHandle, projectID, false);
805
// Add C Nature ... does not add duplicates
806
CProjectNature.addCNature(projectHandle, new SubProgressMonitor(monitor, 1));
811
}, getWorkspace().getRoot(), 0, monitor);
812
return projectHandle;
815
public IProject createCDTProject(
816
final IProjectDescription description,
817
final IProject projectHandle,
818
IProgressMonitor monitor) throws CoreException, OperationCanceledException{
819
return createCDTProject(description, projectHandle, null, monitor);
822
public IProject createCDTProject(
823
final IProjectDescription description,
824
final IProject projectHandle,
826
IProgressMonitor monitor)
827
throws CoreException, OperationCanceledException {
829
getWorkspace().run(new IWorkspaceRunnable() {
830
public void run(IProgressMonitor monitor) throws CoreException {
832
if (monitor == null) {
833
monitor = new NullProgressMonitor();
835
monitor.beginTask("Creating C Project...", 3); //$NON-NLS-1$
836
if (!projectHandle.exists()) {
837
projectHandle.create(description, new SubProgressMonitor(monitor, 1));
840
if (monitor.isCanceled()) {
841
throw new OperationCanceledException();
845
projectHandle.open(IResource.BACKGROUND_REFRESH, new SubProgressMonitor(monitor, 1));
847
// mapCProjectOwner(projectHandle, projectID, false);
849
// Add C Nature ... does not add duplicates
850
CProjectNature.addCNature(projectHandle, new SubProgressMonitor(monitor, 1));
853
ICProjectDescription projDes = createProjectDescription(projectHandle, true);
854
ICConfigurationDescription cfgs[] = projDes.getConfigurations();
855
ICConfigurationDescription cfg = null;
856
for (ICConfigurationDescription cfg2 : cfgs) {
857
if(bsId.equals(cfg2.getBuildSystemId())){
864
ICConfigurationDescription prefCfg = getPreferenceConfiguration(bsId);
866
cfg = projDes.createConfiguration(CDataUtil.genId(prefCfg.getId()), prefCfg.getName(), prefCfg);
871
setProjectDescription(projectHandle, projDes);
878
}, getWorkspace().getRoot(), 0, monitor);
879
return projectHandle;
883
* Method convertProjectFromCtoCC converts
884
* a C Project to a C++ Project
885
* The newProject MUST, not be null, already have a C Nature
886
* && must NOT already have a C++ Nature
888
* @param projectHandle
890
* @throws CoreException
893
public void convertProjectFromCtoCC(IProject projectHandle, IProgressMonitor monitor) throws CoreException {
894
if ((projectHandle != null)
895
&& projectHandle.hasNature(CProjectNature.C_NATURE_ID)
896
&& !projectHandle.hasNature(CCProjectNature.CC_NATURE_ID)) {
897
// Add C++ Nature ... does not add duplicates
898
CCProjectNature.addCCNature(projectHandle, monitor);
903
* Method to convert a project to a C nature
904
* All checks should have been done externally
905
* (as in the Conversion Wizards).
906
* This method blindly does the conversion.
908
public void convertProjectToC(IProject projectHandle, IProgressMonitor monitor, String projectID)
909
throws CoreException {
910
if ((projectHandle == null) || (monitor == null) || (projectID == null)) {
913
IWorkspace workspace = ResourcesPlugin.getWorkspace();
914
IProjectDescription description = workspace.newProjectDescription(projectHandle.getName());
915
description.setLocation(projectHandle.getFullPath());
916
createCProject(description, projectHandle, monitor, projectID);
919
public void convertProjectToNewC(IProject projectHandle, String bsId, IProgressMonitor monitor)
920
throws CoreException {
921
if ((projectHandle == null) || (monitor == null) || (bsId == null)) {
922
throw new NullPointerException();
924
IWorkspace workspace = ResourcesPlugin.getWorkspace();
925
IProjectDescription description = workspace.newProjectDescription(projectHandle.getName());
926
description.setLocation(projectHandle.getFullPath());
927
createCDTProject(description, projectHandle, bsId, monitor);
931
* Method to convert a project to a C++ nature
933
public void convertProjectToCC(IProject projectHandle, IProgressMonitor monitor, String projectID)
934
throws CoreException {
935
if ((projectHandle == null) || (monitor == null) || (projectID == null)) {
938
createCProject(projectHandle.getDescription(), projectHandle, monitor, projectID);
939
// now add C++ nature
940
convertProjectFromCtoCC(projectHandle, monitor);
943
public void convertProjectToNewCC(IProject projectHandle, String bsId, IProgressMonitor monitor)
944
throws CoreException {
945
if ((projectHandle == null) || (monitor == null) || (bsId == null)) {
946
throw new NullPointerException();
948
createCDTProject(projectHandle.getDescription(), projectHandle, bsId, monitor);
949
// now add C++ nature
950
convertProjectFromCtoCC(projectHandle, monitor);
954
* Get the IProcessList contributed interface for the platform.
955
* @return IProcessList
957
public IProcessList getProcessList() throws CoreException {
958
IExtensionPoint extension = Platform.getExtensionRegistry().getExtensionPoint(CCorePlugin.PLUGIN_ID, "ProcessList"); //$NON-NLS-1$
959
if (extension != null) {
960
IExtension[] extensions = extension.getExtensions();
961
IConfigurationElement defaultContributor = null;
962
for (IExtension extension2 : extensions) {
963
IConfigurationElement[] configElements = extension2.getConfigurationElements();
964
for (IConfigurationElement configElement : configElements) {
965
if (configElement.getName().equals("processList")) { //$NON-NLS-1$
966
String platform = configElement.getAttribute("platform"); //$NON-NLS-1$
967
if (platform == null ) { // first contributor found with not platform will be default.
968
if (defaultContributor == null) {
969
defaultContributor = configElement;
971
} else if (platform.equals(Platform.getOS())) {
972
// found explicit contributor for this platform.
973
return (IProcessList) configElement.createExecutableExtension("class"); //$NON-NLS-1$
978
if ( defaultContributor != null) {
979
return (IProcessList) defaultContributor.createExecutableExtension("class"); //$NON-NLS-1$
987
* @deprecated since CDT 6.1. Use {@link ErrorParserManager#getErrorParserAvailableIds()} instead
988
* @return array of error parsers ids
991
public String[] getAllErrorParsersIDs() {
992
ErrorParserExtensionManager.loadErrorParserExtensions();
993
return ErrorParserExtensionManager.getErrorParserAvailableIds();
997
* @deprecated since CDT 6.1. Use {@link ErrorParserManager#getErrorParserCopy(String)} instead
998
* @param id - id of error parser
999
* @return array of error parsers
1002
public IErrorParser[] getErrorParser(String id) {
1003
ErrorParserExtensionManager.loadErrorParserExtensions();
1004
IErrorParser errorParser = ErrorParserExtensionManager.getErrorParserInternal(id);
1005
if (errorParser == null) {
1006
return new IErrorParser[] {};
1008
return new IErrorParser[] { errorParser };
1012
public IScannerInfoProvider getScannerInfoProvider(IProject project) {
1013
IScannerInfoProvider provider = null;
1015
// Look up in session property for previously created provider
1016
QualifiedName scannerInfoProviderName = new QualifiedName(PLUGIN_ID, SCANNER_INFO_PROVIDER2_NAME);
1017
provider = (IScannerInfoProvider)project.getSessionProperty(scannerInfoProviderName);
1018
if (provider != null)
1021
// Next search the extension registry to see if a provider is registered with a build command
1022
IExtensionRegistry registry = Platform.getExtensionRegistry();
1023
IExtensionPoint point = registry.getExtensionPoint(SCANNER_INFO_PROVIDER2);
1024
if (point != null) {
1025
IExtension[] exts = point.getExtensions();
1026
for (IExtension ext : exts) {
1027
IConfigurationElement[] elems = ext.getConfigurationElements();
1028
for (IConfigurationElement elem : elems) {
1029
String builder = elem.getAttribute("builder"); //$NON-NLS-1$
1030
if (builder != null) {
1031
IProjectDescription desc = project.getDescription();
1032
ICommand[] commands = desc.getBuildSpec();
1033
for (ICommand command : commands)
1034
if (builder.equals(command.getBuilderName()))
1035
provider = (IScannerInfoProvider)elem.createExecutableExtension("class"); //$NON-NLS-1$
1041
// Default to the proxy
1042
if (provider == null)
1043
provider = fNewCProjectDescriptionManager.getScannerInfoProviderProxy(project);
1044
project.setSessionProperty(scannerInfoProviderName, provider);
1045
} catch (CoreException e) {
1046
// Bug 313725: When project is being closed, don't report an error.
1047
if (!project.isOpen())
1057
* Helper function, returning the content type for a filename
1059
* getContentType(null, filename)
1062
* @return the content type found, or <code>null</code>
1064
public static IContentType getContentType(String filename) {
1065
return CContentTypes.getContentType(null, filename);
1069
* Returns the content type for a filename. The method respects
1070
* project specific content type definitions. The lookup prefers case-
1071
* sensitive matches over the others.
1072
* @param project a project with possible project specific settings. Can be <code>null</code>
1073
* @param filename a filename to compute the content type for
1074
* @return the content type found or <code>null</code>
1076
public static IContentType getContentType(IProject project, String filename) {
1077
return CContentTypes.getContentType(project, filename);
1081
* Tests whether the given project uses its project specific content types.
1083
public static boolean usesProjectSpecificContentTypes(IProject project) {
1084
return CContentTypes.usesProjectSpecificContentTypes(project);
1088
* Enables or disables the project specific content types.
1090
public static void setUseProjectSpecificContentTypes(IProject project, boolean val) {
1091
CContentTypes.setUseProjectSpecificContentTypes(project, val);
1096
private static final String MODEL = CCorePlugin.PLUGIN_ID + "/debug/model" ; //$NON-NLS-1$
1097
private static final String PARSER = CCorePlugin.PLUGIN_ID + "/debug/parser" ; //$NON-NLS-1$
1098
private static final String PARSER_EXCEPTIONS = CCorePlugin.PLUGIN_ID + "/debug/parser/exceptions" ; //$NON-NLS-1$
1099
private static final String SCANNER = CCorePlugin.PLUGIN_ID + "/debug/scanner"; //$NON-NLS-1$
1100
private static final String DELTA = CCorePlugin.PLUGIN_ID + "/debug/deltaprocessor" ; //$NON-NLS-1$
1101
//private static final String CONTENTASSIST = CCorePlugin.PLUGIN_ID + "/debug/contentassist" ; //$NON-NLS-1$
1104
* Configure the plug-in with respect to option settings defined in ".options" file
1106
public void configurePluginDebugOptions() {
1108
if(CCorePlugin.getDefault().isDebugging()) {
1109
String option = Platform.getDebugOption(PARSER);
1110
if(option != null) Util.VERBOSE_PARSER = option.equalsIgnoreCase("true") ; //$NON-NLS-1$
1112
option = Platform.getDebugOption(PARSER_EXCEPTIONS);
1113
if( option != null ) Util.PARSER_EXCEPTIONS = option.equalsIgnoreCase("true"); //$NON-NLS-1$
1115
option = Platform.getDebugOption(SCANNER);
1116
if( option != null ) Util.VERBOSE_SCANNER = option.equalsIgnoreCase("true"); //$NON-NLS-1$
1118
option = Platform.getDebugOption(MODEL);
1119
if(option != null) Util.VERBOSE_MODEL = option.equalsIgnoreCase("true") ; //$NON-NLS-1$
1121
option = Platform.getDebugOption(DELTA);
1122
if(option != null) Util.VERBOSE_DELTA= option.equalsIgnoreCase("true") ; //$NON-NLS-1$
1127
// Preference to turn on/off the use of structural parse mode to build the CModel
1128
public void setStructuralParseMode(boolean useNewParser) {
1129
getPluginPreferences().setValue(PREF_USE_STRUCTURAL_PARSE_MODE, useNewParser);
1130
savePluginPreferences();
1133
public boolean useStructuralParseMode() {
1134
return getPluginPreferences().getBoolean(PREF_USE_STRUCTURAL_PARSE_MODE);
1138
* @deprecated use {@link ITranslationUnit} or {@link ILanguage} to construct ASTs, instead.
1141
public org.eclipse.cdt.core.dom.CDOM getDOM() {
1142
return org.eclipse.cdt.core.dom.CDOM.getInstance();
1145
public ICdtVariableManager getCdtVariableManager(){
1146
return CdtVariableManager.getDefault();
1149
public IEnvironmentVariableManager getBuildEnvironmentManager(){
1150
return EnvironmentVariableManager.getDefault();
1153
public ICConfigurationDescription getPreferenceConfiguration(String buildSystemId) throws CoreException{
1154
return fNewCProjectDescriptionManager.getPreferenceConfiguration(buildSystemId);
1157
public ICConfigurationDescription getPreferenceConfiguration(String buildSystemId, boolean write) throws CoreException{
1158
return fNewCProjectDescriptionManager.getPreferenceConfiguration(buildSystemId, write);
1161
public void setPreferenceConfiguration(String buildSystemId, ICConfigurationDescription des) throws CoreException {
1162
fNewCProjectDescriptionManager.setPreferenceConfiguration(buildSystemId, des);
1166
* this method is a full equivalent to <code>createProjectDescription(IProject, boolean, false)</code>.
1168
* @see #createProjectDescription(IProject, boolean, boolean)
1170
public ICProjectDescription createProjectDescription(IProject project, boolean loadIfExists) throws CoreException{
1171
return fNewCProjectDescriptionManager.createProjectDescription(project, loadIfExists);
1175
* the method creates and returns a writable project description
1177
* @param project project for which the project description is requested
1178
* @param loadIfExists if true the method first tries to load and return the project description
1179
* from the settings file (.cproject)
1180
* if false, the stored settings are ignored and the new (empty) project description is created
1181
* @param creating if true the created project description will be contain the true "isCdtProjectCreating" state.
1182
* NOTE: in case the project already contains the project description AND its "isCdtProjectCreating" is false
1183
* the resulting description will be created with the false "isCdtProjectCreating" state
1185
* NOTE: changes made to the returned project description will not be applied until the {@link #setProjectDescription(IProject, ICProjectDescription)} is called
1186
* @return {@link ICProjectDescription}
1187
* @throws CoreException
1189
public ICProjectDescription createProjectDescription(IProject project, boolean loadIfExists, boolean creating) throws CoreException{
1190
return fNewCProjectDescriptionManager.createProjectDescription(project, loadIfExists, creating);
1194
* returns the project description associated with this project or null if the project does not contain the
1195
* CDT data associated with it.
1197
* this is a convenience method fully equivalent to getProjectDescription(project, true)
1198
* see {@link #getProjectDescription(IProject, boolean)} for more detail
1200
* @return a writable copy of the ICProjectDescription or null if the project does not contain the
1201
* CDT data associated with it.
1202
* Note: changes to the project description will not be reflected/used by the core
1203
* until the {@link #setProjectDescription(IProject, ICProjectDescription)} is called
1205
* @see #getProjectDescription(IProject, boolean)
1207
public ICProjectDescription getProjectDescription(IProject project){
1208
return fNewCProjectDescriptionManager.getProjectDescription(project);
1212
* this method is called to save/apply the project description
1213
* the method should be called to apply changes made to the project description
1214
* returned by the {@link #getProjectDescription(IProject, boolean)} or {@link #createProjectDescription(IProject, boolean)}
1218
* @throws CoreException
1220
* @see #getProjectDescription(IProject, boolean)
1221
* @see #createProjectDescription(IProject, boolean)
1223
public void setProjectDescription(IProject project, ICProjectDescription des) throws CoreException {
1224
fNewCProjectDescriptionManager.setProjectDescription(project, des);
1227
public void setProjectDescription(IProject project, ICProjectDescription des, boolean force, IProgressMonitor monitor) throws CoreException {
1228
fNewCProjectDescriptionManager.setProjectDescription(project, des, force, monitor);
1232
* returns the project description associated with this project or null if the project does not contain the
1233
* CDT data associated with it.
1235
* @param project project for which the description is requested
1236
* @param write if true, the writable description copy is returned.
1237
* If false the cached read-only description is returned.
1239
* CDT core maintains the cached project description settings. If only read access is needed to description,
1240
* then the read-only project description should be obtained.
1241
* This description always operates with cached data and thus it is better to use it for performance reasons
1242
* All set* calls to the read-only description result in the {@link WriteAccessException}
1244
* When the writable description is requested, the description copy is created.
1245
* Changes to this description will not be reflected/used by the core and Build System untill the
1246
* {@link #setProjectDescription(IProject, ICProjectDescription)} is called
1248
* Each getProjectDescription(project, true) returns a new copy of the project description
1250
* The writable description uses the cached data untill the first set call
1251
* after that the description communicates directly to the Build System
1252
* i.e. the implementer of the org.eclipse.cdt.core.CConfigurationDataProvider extension
1253
* This ensures the Core<->Build System settings integrity
1255
* @return {@link ICProjectDescription} or null if the project does not contain the
1256
* CDT data associated with it.
1258
public ICProjectDescription getProjectDescription(IProject project, boolean write){
1259
return fNewCProjectDescriptionManager.getProjectDescription(project, write);
1263
* forces the cached data of the specified projects to be re-calculated.
1264
* if the <code>projects</code> argument is <code>null</code> al projects
1265
* within the workspace are updated
1269
* @throws CoreException
1271
public void updateProjectDescriptions(IProject projects[], IProgressMonitor monitor) throws CoreException{
1272
fNewCProjectDescriptionManager.updateProjectDescriptions(projects, monitor);
1276
* Answers whether the given project is a new-style project, i.e. CConfigurationDataProvider-driven
1278
public boolean isNewStyleProject(IProject project){
1279
return fNewCProjectDescriptionManager.isNewStyleProject(project);
1283
* Answers whether the given project is a new-style project, i.e. CConfigurationDataProvider-driven
1285
public boolean isNewStyleProject(ICProjectDescription des){
1286
return fNewCProjectDescriptionManager.isNewStyleProject(des);
1289
public ICProjectDescriptionManager getProjectDescriptionManager(){
1290
return fNewCProjectDescriptionManager;
1294
* @return editable User-variable's supplier
1296
public static IUserVarSupplier getUserVarSupplier() {
1297
return UserVarSupplier.getInstance();
1303
* @noreference This constructor is not intended to be referenced by clients.
1305
public CCorePlugin() {
1311
* @noreference This method is not intended to be referenced by clients.
1313
public static void log(String e) {
1314
log(createStatus(e));
1318
* @noreference This method is not intended to be referenced by clients.
1320
public static void log(Throwable e) {
1321
String msg= e.getMessage();
1323
log("Error", e); //$NON-NLS-1$
1325
log("Error: " + msg, e); //$NON-NLS-1$
1330
* @noreference This method is not intended to be referenced by clients.
1332
public static void log(String message, Throwable e) {
1333
Throwable nestedException;
1334
if (e instanceof CModelException
1335
&& (nestedException = ((CModelException)e).getException()) != null) {
1336
e = nestedException;
1338
log(createStatus(message, e));
1342
* @noreference This method is not intended to be referenced by clients.
1344
public static IStatus createStatus(String msg) {
1345
return createStatus(msg, null);
1349
* @noreference This method is not intended to be referenced by clients.
1351
public static IStatus createStatus(String msg, Throwable e) {
1352
return new Status(IStatus.ERROR, PLUGIN_ID, msg, e);
1356
* @noreference This method is not intended to be referenced by clients.
1358
public static void log(IStatus status) {
1359
getDefault().getLog().log(status);
1363
* @deprecated use getIndexManager().
1364
* @noreference This method is not intended to be referenced by clients.
1367
public static IPDOMManager getPDOMManager() {
1368
return getDefault().pdomManager;
1372
* Returns preference controlling whether source roots are shown at the top of projects
1373
* or embedded within the resource tree of projects when they are not top level folders.
1375
* @return boolean preference value
1378
public static boolean showSourceRootsAtTopOfProject() {
1379
return InstanceScope.INSTANCE.getNode(PLUGIN_ID)
1380
.getBoolean(CCorePreferenceConstants.SHOW_SOURCE_ROOTS_AT_TOP_LEVEL_OF_PROJECT, true);
b'\\ No newline at end of file'