From 64c57825896980a473ebc362f5a32d806c2c85e4 Mon Sep 17 00:00:00 2001 From: Doug Schaefer Date: Mon, 31 Aug 2015 11:26:50 -0400 Subject: [PATCH] Bug 321443 - First implementation of new build model. Includes adaptation of the Arduino build model where many of these ideas started to the new model. And start of the Qt build system which uses it. Change-Id: Icb212185773ebc4d415e8a9862101744703ff80b --- .../org.eclipse.cdt.core/META-INF/MANIFEST.MF | 12 +- core/org.eclipse.cdt.core/plugin.xml | 18 + core/org.eclipse.cdt.core/pom.xml | 2 +- .../schema/ToolChain.exsd | 60 +- .../src/org/eclipse/cdt/core/CCorePlugin.java | 867 ++++++++++-------- .../cdt/core/build/CBuildConfiguration.java | 139 +++ .../cdt/core/build/CConsoleParser.java | 121 +++ .../eclipse/cdt/core/build/CToolChain.java | 119 +++ .../eclipse/cdt/core/build/GCCToolChain.java | 224 +++++ .../cdt/core/build/IConsoleService.java | 45 + .../internal/core/build/ScannerInfoData.java | 166 ++++ .../build/ScannerInfoSaveParticipant.java | 50 + .../core/build/ToolChainScannerInfo.java | 56 ++ core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF | 3 +- .../OSGI-INF/consoleservice.xml | 6 + core/org.eclipse.cdt.ui/pom.xml | 2 +- .../internal/ui/build/CConsoleService.java | 56 +- .../cdt/internal/ui/build/CHyperlink.java | 11 +- .../ui/build/CPatternMatchListener.java | 63 ++ .../qt/core/build/IConsoleService.java | 14 - .../cdt/internal/qt/core/build/QtBuilder.java | 5 +- qt/org.eclipse.cdt.qt.ui/META-INF/MANIFEST.MF | 1 - .../OSGI-INF/consoleservice.xml | 6 - .../cdt/internal/qt/ui/QtUIPlugin.java | 3 - .../META-INF/MANIFEST.MF | 1 - .../build.properties | 1 - .../org.eclipse.cdt.arduino.core/plugin.xml | 1 - .../cdt/arduino/core/internal/Activator.java | 10 - .../core/internal/board/ArduinoManager.java | 2 +- .../build/ArduinoBuildConfiguration.java | 201 +--- .../core/internal/build/ArduinoBuilder.java | 22 +- .../console/ArduinoConsoleParser.java | 53 -- .../console/ArduinoConsoleService.java | 25 - .../internal/console/ArduinoErrorParser.java | 67 -- .../ArduinoLaunchConfigurationDelegate.java | 4 +- .../org.eclipse.cdt.arduino.ui/plugin.xml | 6 - .../ui/internal/launch/ArduinoConsole.java | 162 ---- .../launch/ArduinoErrorMatchListener.java | 30 - .../launch/ArduinoPatternMatchListener.java | 43 - 39 files changed, 1664 insertions(+), 1013 deletions(-) rename toolchains/arduino/org.eclipse.cdt.arduino.core/schema/consoleService.exsd => core/org.eclipse.cdt.core/schema/ToolChain.exsd (60%) create mode 100644 core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/CBuildConfiguration.java create mode 100644 core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/CConsoleParser.java create mode 100644 core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/CToolChain.java create mode 100644 core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/GCCToolChain.java create mode 100644 core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/IConsoleService.java create mode 100644 core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/build/ScannerInfoData.java create mode 100644 core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/build/ScannerInfoSaveParticipant.java create mode 100644 core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/build/ToolChainScannerInfo.java create mode 100644 core/org.eclipse.cdt.ui/OSGI-INF/consoleservice.xml rename qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/QtConsoleService.java => core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/build/CConsoleService.java (64%) rename toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/launch/ArduinoHyperlink.java => core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/build/CHyperlink.java (72%) create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/build/CPatternMatchListener.java delete mode 100644 qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/IConsoleService.java delete mode 100644 qt/org.eclipse.cdt.qt.ui/OSGI-INF/consoleservice.xml delete mode 100644 toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/console/ArduinoConsoleParser.java delete mode 100644 toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/console/ArduinoConsoleService.java delete mode 100644 toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/console/ArduinoErrorParser.java delete mode 100644 toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/launch/ArduinoConsole.java delete mode 100644 toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/launch/ArduinoErrorMatchListener.java delete mode 100644 toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/launch/ArduinoPatternMatchListener.java diff --git a/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF b/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF index 11216c0d519..bd44f8fcfd0 100644 --- a/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF +++ b/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF @@ -2,12 +2,13 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.cdt.core; singleton:=true -Bundle-Version: 5.11.0.qualifier +Bundle-Version: 5.12.0.qualifier Bundle-Activator: org.eclipse.cdt.core.CCorePlugin Bundle-Vendor: %providerName Bundle-Localization: plugin Export-Package: org.eclipse.cdt.core, org.eclipse.cdt.core.browser, + org.eclipse.cdt.core.build, org.eclipse.cdt.core.cdtvariables, org.eclipse.cdt.core.dom, org.eclipse.cdt.core.dom.ast, @@ -73,7 +74,11 @@ Export-Package: org.eclipse.cdt.core, org.eclipse.cdt.internal.core.indexer;x-internal:=true, org.eclipse.cdt.internal.core.language;x-friends:="org.eclipse.cdt.ui", org.eclipse.cdt.internal.core.language.settings.providers;x-internal:=true, - org.eclipse.cdt.internal.core.model;x-friends:="org.eclipse.cdt.ui,org.eclipse.cdt.debug.core,org.eclipse.cdt.debug.ui,org.eclipse.cdt.codan.ui", + org.eclipse.cdt.internal.core.model; + x-friends:="org.eclipse.cdt.ui, + org.eclipse.cdt.debug.core, + org.eclipse.cdt.debug.ui, + org.eclipse.cdt.codan.ui", org.eclipse.cdt.internal.core.model.ext;x-friends:="org.eclipse.cdt.ui", org.eclipse.cdt.internal.core.parser;x-internal:=true, org.eclipse.cdt.internal.core.parser.problem;x-internal:=true, @@ -122,6 +127,7 @@ Require-Bundle: org.eclipse.cdt.core.native;bundle-version="[5.7.0,6.0.0)";visib org.eclipse.core.variables;bundle-version="[3.1.100,4.0.0)", org.eclipse.ltk.core.refactoring;bundle-version="3.4.0", org.eclipse.text;bundle-version="[3.2.0,4.0.0)", - com.ibm.icu;bundle-version="4.4.2" + com.ibm.icu;bundle-version="4.4.2", + com.google.gson;bundle-version="2.2.4" Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: JavaSE-1.7 diff --git a/core/org.eclipse.cdt.core/plugin.xml b/core/org.eclipse.cdt.core/plugin.xml index d5e0020806e..f258d41eec2 100644 --- a/core/org.eclipse.cdt.core/plugin.xml +++ b/core/org.eclipse.cdt.core/plugin.xml @@ -683,6 +683,7 @@ + @@ -856,5 +857,22 @@ ordering="first"> + + + + + + + + + + diff --git a/core/org.eclipse.cdt.core/pom.xml b/core/org.eclipse.cdt.core/pom.xml index 61c12cda467..051df4d494a 100644 --- a/core/org.eclipse.cdt.core/pom.xml +++ b/core/org.eclipse.cdt.core/pom.xml @@ -11,7 +11,7 @@ ../../pom.xml - 5.11.0-SNAPSHOT + 5.12.0-SNAPSHOT org.eclipse.cdt.core eclipse-plugin diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/schema/consoleService.exsd b/core/org.eclipse.cdt.core/schema/ToolChain.exsd similarity index 60% rename from toolchains/arduino/org.eclipse.cdt.arduino.core/schema/consoleService.exsd rename to core/org.eclipse.cdt.core/schema/ToolChain.exsd index e56c770ca91..c421b87247b 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/schema/consoleService.exsd +++ b/core/org.eclipse.cdt.core/schema/ToolChain.exsd @@ -1,10 +1,10 @@ - + - - - + + + [Enter description of this extension point.] @@ -12,13 +12,13 @@ - + - + - - + + @@ -39,60 +39,72 @@ - + - + - + + + + A toolchain that implements the CToolChain interface and identified with the id attribute. + + - + - + id for the toolchain. + + + + + + + The adaptor class for the toolchain. This is passed to getAdaptor on the CBuildConfiguration object. - - - + + + - + - + [Enter the first release in which this extension point appears.] - + - + [Enter extension point usage example here.] - + - + [Enter API information here.] - + - + [Enter information about supplied implementation of this extension point.] diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java index a46940444f9..0d832f38595 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java @@ -50,6 +50,7 @@ import org.eclipse.cdt.internal.core.CdtVarPathEntryVariableManager; import org.eclipse.cdt.internal.core.ICConsole; import org.eclipse.cdt.internal.core.PositionTrackerManager; +import org.eclipse.cdt.internal.core.build.ScannerInfoSaveParticipant; import org.eclipse.cdt.internal.core.cdtvariables.CdtVariableManager; import org.eclipse.cdt.internal.core.cdtvariables.UserVarSupplier; import org.eclipse.cdt.internal.core.dom.ast.tag.TagService; @@ -92,8 +93,8 @@ import com.ibm.icu.text.MessageFormat; /** - * CCorePlugin is the life-cycle owner of the core plug-in, and starting point for access to many - * core APIs. + * CCorePlugin is the life-cycle owner of the core plug-in, and starting point + * for access to many core APIs. * * @noextend This class is not intended to be subclassed by clients. * @noinstantiate This class is not intended to be instantiated by clients. @@ -103,7 +104,9 @@ public class CCorePlugin extends Plugin { public static final int STATUS_CDTPROJECT_MISMATCH = 2; public static final int CDT_PROJECT_NATURE_ID_MISMATCH = 3; /** - * Status code for core exception that is thrown if a pdom grew larger than the supported limit. + * Status code for core exception that is thrown if a pdom grew larger than + * the supported limit. + * * @since 5.2 */ public static final int STATUS_PDOM_TOO_LARGE = 4; @@ -115,7 +118,8 @@ public class CCorePlugin extends Plugin { public static final String BINARY_PARSER_UNIQ_ID = PLUGIN_ID + "." + BINARY_PARSER_SIMPLE_ID; //$NON-NLS-1$ public static final String PREF_BINARY_PARSER = "binaryparser"; //$NON-NLS-1$ public static final String DEFAULT_BINARY_PARSER_SIMPLE_ID = "ELF"; //$NON-NLS-1$ - public static final String DEFAULT_BINARY_PARSER_UNIQ_ID = PLUGIN_ID + "." + DEFAULT_BINARY_PARSER_SIMPLE_ID; //$NON-NLS-1$ + public static final String DEFAULT_BINARY_PARSER_UNIQ_ID = PLUGIN_ID + "." //$NON-NLS-1$ + + DEFAULT_BINARY_PARSER_SIMPLE_ID; public static final String PREF_USE_STRUCTURAL_PARSE_MODE = "useStructualParseMode"; //$NON-NLS-1$ public static final String INDEX_SIMPLE_ID = "CIndex"; //$NON-NLS-1$ @@ -150,22 +154,23 @@ public class CCorePlugin extends Plugin { /** * Name of the extension point for contributing a source code formatter */ - public static final String FORMATTER_EXTPOINT_ID = "CodeFormatter" ; //$NON-NLS-1$ + public static final String FORMATTER_EXTPOINT_ID = "CodeFormatter"; //$NON-NLS-1$ - /** - * Possible configurable option ID. - * @see #getDefaultOptions - */ - public static final String CORE_ENCODING = PLUGIN_ID + ".encoding"; //$NON-NLS-1$ + /** + * Possible configurable option ID. + * + * @see #getDefaultOptions + */ + public static final String CORE_ENCODING = PLUGIN_ID + ".encoding"; //$NON-NLS-1$ /** * IContentType id for C Source Unit */ - public static final String CONTENT_TYPE_CSOURCE = "org.eclipse.cdt.core.cSource"; //$NON-NLS-1$ + public static final String CONTENT_TYPE_CSOURCE = "org.eclipse.cdt.core.cSource"; //$NON-NLS-1$ /** * IContentType id for C Header Unit */ - public static final String CONTENT_TYPE_CHEADER = "org.eclipse.cdt.core.cHeader"; //$NON-NLS-1$ + public static final String CONTENT_TYPE_CHEADER = "org.eclipse.cdt.core.cHeader"; //$NON-NLS-1$ /** * IContentType id for C++ Source Unit */ @@ -184,22 +189,26 @@ public class CCorePlugin extends Plugin { public static final String CONTENT_TYPE_BINARYFILE = "org.eclipse.cdt.core.binaryFile"; //$NON-NLS-1$ /** - * Possible configurable option value. + * Possible configurable option value. + * * @see #getDefaultOptions() */ public static final String INSERT = "insert"; //$NON-NLS-1$ /** - * Possible configurable option value. + * Possible configurable option value. + * * @see #getDefaultOptions() */ public static final String DO_NOT_INSERT = "do not insert"; //$NON-NLS-1$ /** - * Possible configurable option value. + * Possible configurable option value. + * * @see #getDefaultOptions() */ public static final String TAB = "tab"; //$NON-NLS-1$ /** - * Possible configurable option value. + * Possible configurable option value. + * * @see #getDefaultOptions() */ public static final String SPACE = "space"; //$NON-NLS-1$ @@ -227,24 +236,30 @@ private final class NullConsole implements IConsole { @Override public void write(byte[] b) throws IOException { } + @Override public void write(byte[] b, int off, int len) throws IOException { } + @Override public void write(int c) throws IOException { } }; + @Override public void start(IProject project) { } + @Override public ConsoleOutputStream getOutputStream() { return nullStream; } + @Override public ConsoleOutputStream getInfoStream() { return nullStream; } + @Override public ConsoleOutputStream getErrorStream() { return nullStream; @@ -262,7 +277,9 @@ public ConsoleOutputStream getErrorStream() { } /** - * Returns the shared working copies currently registered for the default buffer factory. + * Returns the shared working copies currently registered for the default + * buffer factory. + * * @since 5.1 */ public static IWorkingCopy[] getSharedWorkingCopies() { @@ -296,9 +313,9 @@ public static ResourceBundle getResourceBundle() { return fgResourceBundle; } - public static IPositionTrackerManager getPositionTrackerManager() { - return PositionTrackerManager.getInstance(); - } + public static IPositionTrackerManager getPositionTrackerManager() { + return PositionTrackerManager.getInstance(); + } public static CCorePlugin getDefault() { return fgCPlugin; @@ -312,11 +329,11 @@ public void stop(BundleContext context) throws Exception { try { pdomManager.shutdown(); - PositionTrackerManager.getInstance().uninstall(); + PositionTrackerManager.getInstance().uninstall(); -// if (fDescriptorManager != null) { -// fDescriptorManager.shutdown(); -// } + // if (fDescriptorManager != null) { + // fDescriptorManager.shutdown(); + // } if (fCoreModel != null) { fCoreModel.shutdown(); @@ -330,10 +347,10 @@ public void stop(BundleContext context) throws Exception { fPathEntryVariableManager.shutdown(); } - fNewCProjectDescriptionManager.shutdown(); - ResourceLookup.shutdown(); + fNewCProjectDescriptionManager.shutdown(); + ResourceLookup.shutdown(); - savePluginPreferences(); + savePluginPreferences(); } finally { super.stop(context); } @@ -349,11 +366,11 @@ public void start(BundleContext context) throws Exception { // do harmless stuff first. cdtLog = new CDTLogWriter(CCorePlugin.getDefault().getStateLocation().append(".log").toFile()); //$NON-NLS-1$ configurePluginDebugOptions(); - PositionTrackerManager.getInstance().install(); - ResourceLookup.startup(); + PositionTrackerManager.getInstance().install(); + ResourceLookup.startup(); - // new project model needs to register the resource listener first. - CProjectDescriptionManager descManager = CProjectDescriptionManager.getInstance(); + // new project model needs to register the resource listener first. + CProjectDescriptionManager descManager = CProjectDescriptionManager.getInstance(); final Job post1 = descManager.startup(); fNewCProjectDescriptionManager = descManager; @@ -364,172 +381,198 @@ public void start(BundleContext context) throws Exception { fCoreModel.startup(); pdomManager = new PDOMManager(); - final Job post2= pdomManager.startup(); - - // bug 186755, when started after the platform has been started the job manager - // is no longer suspended. So we have to start a job at the very end to make - // sure we don't trigger a concurrent plug-in activation from within the job. + final Job post2 = pdomManager.startup(); + + // bug 186755, when started after the platform has been started the job + // manager + // is no longer suspended. So we have to start a job at the very end to + // make + // sure we don't trigger a concurrent plug-in activation from within the + // job. post1.schedule(); post2.schedule(); + + // Save participant for toolchain data + ResourcesPlugin.getWorkspace().addSaveParticipant(PLUGIN_ID, new ScannerInfoSaveParticipant()); + } + + /** + * TODO: Add all options here Returns a table of all known configurable + * options with their default values. These options allow to configure the + * behavior of the underlying components. The client may safely use the + * result as a template that they can modify and then pass to + * setOptions. + * + * Helper constants have been defined on CCorePlugin for each of the option + * ID and their possible constant values. + * + * Note: more options might be added in further releases. + * + *
+	 * RECOGNIZED OPTIONS:
+	 *
+	 * CORE / Specify Default Source Encoding Format
+	 *    Get the encoding format for translated sources. This setting is read-only, it is equivalent
+	 *    to 'ResourcesPlugin.getEncoding()'.
+	 *     - option id:         "org.eclipse.cdt.core.encoding"
+	 *     - possible values:   { any of the supported encoding names}.
+	 *     - default:           
+	 * 
+ * + * @return a mutable map containing the default settings of all known + * options (key type: String; value type: + * String) + * @see #setOptions + */ + public static HashMap getDefaultOptions() { + HashMap defaultOptions = new HashMap(10); + + // see #initializeDefaultPluginPreferences() for changing default + // settings + Preferences preferences = getDefault().getPluginPreferences(); + HashSet optionNames = CModelManager.OptionNames; + + // get preferences set to their default + for (String propertyName : preferences.defaultPropertyNames()) { + if (optionNames.contains(propertyName)) + defaultOptions.put(propertyName, preferences.getDefaultString(propertyName)); + } + // get preferences not set to their default + for (String propertyName : preferences.propertyNames()) { + if (optionNames.contains(propertyName)) + defaultOptions.put(propertyName, preferences.getDefaultString(propertyName)); + } + // get encoding through resource plugin + defaultOptions.put(CORE_ENCODING, ResourcesPlugin.getEncoding()); + + return defaultOptions; } /** - * TODO: Add all options here - * Returns a table of all known configurable options with their default values. - * These options allow to configure the behavior of the underlying components. - * The client may safely use the result as a template that they can modify and - * then pass to setOptions. - * - * Helper constants have been defined on CCorePlugin for each of the option ID and - * their possible constant values. - * - * Note: more options might be added in further releases. - *
-     * RECOGNIZED OPTIONS:
-     *
-     * CORE / Specify Default Source Encoding Format
-     *    Get the encoding format for translated sources. This setting is read-only, it is equivalent
-     *    to 'ResourcesPlugin.getEncoding()'.
-     *     - option id:         "org.eclipse.cdt.core.encoding"
-     *     - possible values:   { any of the supported encoding names}.
-     *     - default:           
-     * 
- * - * @return a mutable map containing the default settings of all known options - * (key type: String; value type: String) - * @see #setOptions - */ - public static HashMap getDefaultOptions() { - HashMap defaultOptions = new HashMap(10); - - // see #initializeDefaultPluginPreferences() for changing default settings - Preferences preferences = getDefault().getPluginPreferences(); - HashSet optionNames = CModelManager.OptionNames; - - // get preferences set to their default - for (String propertyName : preferences.defaultPropertyNames()) { - if (optionNames.contains(propertyName)) - defaultOptions.put(propertyName, preferences.getDefaultString(propertyName)); - } - // get preferences not set to their default - for (String propertyName : preferences.propertyNames()) { - if (optionNames.contains(propertyName)) - defaultOptions.put(propertyName, preferences.getDefaultString(propertyName)); - } - // get encoding through resource plugin - defaultOptions.put(CORE_ENCODING, ResourcesPlugin.getEncoding()); - - return defaultOptions; - } - - /** - * Helper method for returning one option value only. Equivalent to (String)CCorePlugin.getOptions().get(optionName) - * Note that it may answer null if this option does not exist. - *

- * For a complete description of the configurable options, see getDefaultOptions. - *

- * - * @param optionName the name of an option - * @return the String value of a given option - * @see CCorePlugin#getDefaultOptions - */ - public static String getOption(String optionName) { - - if (CORE_ENCODING.equals(optionName)) { - return ResourcesPlugin.getEncoding(); - } - if (CModelManager.OptionNames.contains(optionName)) { - Preferences preferences = getDefault().getPluginPreferences(); - return preferences.getString(optionName).trim(); - } - return null; - } - - /** - * Returns the table of the current options. Initially, all options have their default values, - * and this method returns a table that includes all known options. - *

- * For a complete description of the configurable options, see getDefaultOptions. - *

- * - * @return table of current settings of all options - * (key type: String; value type: String) - * @see CCorePlugin#getDefaultOptions - */ - public static HashMap getOptions() { - HashMap options = new HashMap(10); - - // see #initializeDefaultPluginPreferences() for changing default settings - Plugin plugin = getDefault(); - if (plugin != null) { - Preferences preferences = plugin.getPluginPreferences(); - HashSet optionNames = CModelManager.OptionNames; - - // get preferences set to their default - for (String propertyName : preferences.defaultPropertyNames()) { - if (optionNames.contains(propertyName)) { - options.put(propertyName, preferences.getDefaultString(propertyName)); - } - } - // get preferences not set to their default - for (String propertyName : preferences.propertyNames()) { - if (optionNames.contains(propertyName)) { - options.put(propertyName, preferences.getString(propertyName).trim()); - } - } - // get encoding through resource plugin - options.put(CORE_ENCODING, ResourcesPlugin.getEncoding()); - } - return options; - } - - /** - * Sets the current table of options. All and only the options explicitly included in the given table - * are remembered; all previous option settings are forgotten, including ones not explicitly - * mentioned. - *

- * For a complete description of the configurable options, see getDefaultOptions. - *

- * - * @param newOptions the new options (key type: String; value type: String), - * or null to reset all options to their default values - * @see CCorePlugin#getDefaultOptions - */ - public static void setOptions(HashMap newOptions) { - - // see #initializeDefaultPluginPreferences() for changing default settings - Preferences preferences = getDefault().getPluginPreferences(); - - if (newOptions == null) { - newOptions = getDefaultOptions(); - } - for (String key : newOptions.keySet()) { - if (!CModelManager.OptionNames.contains(key)) continue; // unrecognized option - if (key.equals(CORE_ENCODING)) continue; // skipped, contributed by resource prefs - String value = newOptions.get(key); - preferences.setValue(key, value); - } - - // persist options - getDefault().savePluginPreferences(); - } - - /** - * Create CDT console adapter for build console defined as an extension. - * See {@code org.eclipse.cdt.core.CBuildConsole} extension point. - * If the console class is instance of {@link ICConsole} it is initialized - * with context id, name and icon to be shown in the list of consoles in the + * Helper method for returning one option value only. Equivalent to + * (String)CCorePlugin.getOptions().get(optionName) Note that + * it may answer null if this option does not exist. + *

+ * For a complete description of the configurable options, see + * getDefaultOptions. + *

+ * + * @param optionName + * the name of an option + * @return the String value of a given option + * @see CCorePlugin#getDefaultOptions + */ + public static String getOption(String optionName) { + + if (CORE_ENCODING.equals(optionName)) { + return ResourcesPlugin.getEncoding(); + } + if (CModelManager.OptionNames.contains(optionName)) { + Preferences preferences = getDefault().getPluginPreferences(); + return preferences.getString(optionName).trim(); + } + return null; + } + + /** + * Returns the table of the current options. Initially, all options have + * their default values, and this method returns a table that includes all + * known options. + *

+ * For a complete description of the configurable options, see + * getDefaultOptions. + *

+ * + * @return table of current settings of all options (key type: + * String; value type: String) + * @see CCorePlugin#getDefaultOptions + */ + public static HashMap getOptions() { + HashMap options = new HashMap(10); + + // see #initializeDefaultPluginPreferences() for changing default + // settings + Plugin plugin = getDefault(); + if (plugin != null) { + Preferences preferences = plugin.getPluginPreferences(); + HashSet optionNames = CModelManager.OptionNames; + + // get preferences set to their default + for (String propertyName : preferences.defaultPropertyNames()) { + if (optionNames.contains(propertyName)) { + options.put(propertyName, preferences.getDefaultString(propertyName)); + } + } + // get preferences not set to their default + for (String propertyName : preferences.propertyNames()) { + if (optionNames.contains(propertyName)) { + options.put(propertyName, preferences.getString(propertyName).trim()); + } + } + // get encoding through resource plugin + options.put(CORE_ENCODING, ResourcesPlugin.getEncoding()); + } + return options; + } + + /** + * Sets the current table of options. All and only the options explicitly + * included in the given table are remembered; all previous option settings + * are forgotten, including ones not explicitly mentioned. + *

+ * For a complete description of the configurable options, see + * getDefaultOptions. + *

+ * + * @param newOptions + * the new options (key type: String; value type: + * String), or null to reset all + * options to their default values + * @see CCorePlugin#getDefaultOptions + */ + public static void setOptions(HashMap newOptions) { + + // see #initializeDefaultPluginPreferences() for changing default + // settings + Preferences preferences = getDefault().getPluginPreferences(); + + if (newOptions == null) { + newOptions = getDefaultOptions(); + } + for (String key : newOptions.keySet()) { + if (!CModelManager.OptionNames.contains(key)) + continue; // unrecognized option + if (key.equals(CORE_ENCODING)) + continue; // skipped, contributed by resource prefs + String value = newOptions.get(key); + preferences.setValue(key, value); + } + + // persist options + getDefault().savePluginPreferences(); + } + + /** + * Create CDT console adapter for build console defined as an extension. See + * {@code org.eclipse.cdt.core.CBuildConsole} extension point. If the + * console class is instance of {@link ICConsole} it is initialized with + * context id, name and icon to be shown in the list of consoles in the * Console view. * - * @param extConsoleId - console id defined in the extension point. - * @param contextId - context menu id in the Console view. A caller needs to define - * a distinct one for own use. - * @param name - name of console to appear in the list of consoles in context menu - * in the Console view. - * @param iconUrl - a {@link URL} of the icon for the context menu of the Console - * view. The url is expected to point to an image in eclipse OSGi bundle. - * Here is an example how to retrieve URL:
- * + * @param extConsoleId + * - console id defined in the extension point. + * @param contextId + * - context menu id in the Console view. A caller needs to + * define a distinct one for own use. + * @param name + * - name of console to appear in the list of consoles in context + * menu in the Console view. + * @param iconUrl + * - a {@link URL} of the icon for the context menu of the + * Console view. The url is expected to point to an image in + * eclipse OSGi bundle. Here is an example how to retrieve URL: + *
+ * * URL iconUrl = CUIPlugin.getDefault().getBundle().getEntry("icons/obj16/flask.png"); * * @@ -539,14 +582,16 @@ public static void setOptions(HashMap newOptions) { */ public IConsole getConsole(String extConsoleId, String contextId, String name, URL iconUrl) { try { - IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(CCorePlugin.PLUGIN_ID, "CBuildConsole"); //$NON-NLS-1$ + IExtensionPoint extensionPoint = Platform.getExtensionRegistry() + .getExtensionPoint(CCorePlugin.PLUGIN_ID, "CBuildConsole"); //$NON-NLS-1$ if (extensionPoint != null) { IExtension[] extensions = extensionPoint.getExtensions(); for (IExtension extension : extensions) { IConfigurationElement[] configElements = extension.getConfigurationElements(); for (IConfigurationElement configElement : configElements) { String consoleID = configElement.getAttribute("id"); //$NON-NLS-1$ - if ((extConsoleId == null && consoleID == null) || (extConsoleId != null && extConsoleId.equals(consoleID))) { + if ((extConsoleId == null && consoleID == null) + || (extConsoleId != null && extConsoleId.equals(consoleID))) { IConsole console = (IConsole) configElement.createExecutableExtension("class"); //$NON-NLS-1$ if (console instanceof ICConsole) { ((ICConsole) console).init(contextId, name, iconUrl); @@ -563,12 +608,13 @@ public IConsole getConsole(String extConsoleId, String contextId, String name, U } /** - * Create CDT console adapter. - * The adapter serves as a bridge between core plugin and UI console API in a way that - * a user can create a UI console from plugins having no dependencies to UI. + * Create CDT console adapter. The adapter serves as a bridge between core + * plugin and UI console API in a way that a user can create a UI console + * from plugins having no dependencies to UI. * - * @param id - id of the console specified in extension point to instantiate - * console adapter. + * @param id + * - id of the console specified in extension point to + * instantiate console adapter. * @return CDT console adapter. */ public IConsole getConsole(String id) { @@ -580,19 +626,23 @@ public IConsole getConsole(String id) { * {@code org.eclipse.cdt.internal.ui.buildconsole.CBuildConsole} is created * and initialized with the parameters. * - * @param contextId - context menu id in the Console view. A caller needs to define - * a distinct one for own use. - * @param name - name of console to appear in the list of consoles in context menu - * in the Console view. - * @param iconUrl - a {@link URL} of the icon for the context menu of the Console - * view. The url is expected to point to an image in eclipse OSGi bundle. - * Here is an example how to retrieve URL:
- * + * @param contextId + * - context menu id in the Console view. A caller needs to + * define a distinct one for own use. + * @param name + * - name of console to appear in the list of consoles in context + * menu in the Console view. + * @param iconUrl + * - a {@link URL} of the icon for the context menu of the + * Console view. The url is expected to point to an image in + * eclipse OSGi bundle. Here is an example how to retrieve URL: + *
+ * * URL iconUrl = CUIPlugin.getDefault().getBundle().getResource("icons/obj16/flask.png"); - * - *
- * {@code iconUrl} can be null, in that case the default image is used. - * See {@code org.eclipse.cdt.internal.ui.buildconsole.BuildConsole(IBuildConsoleManager, String, String, URL)} + *

+ * {@code iconUrl} can be null, in that case the default + * image is used. See + * {@code org.eclipse.cdt.internal.ui.buildconsole.BuildConsole(IBuildConsoleManager, String, String, URL)} * * @return CDT console adapter. * @@ -611,7 +661,8 @@ public IConsole getConsole() { } /** - * @deprecated Use {@link #getDefaultBinaryParserExtensions(IProject)} instead. + * @deprecated Use {@link #getDefaultBinaryParserExtensions(IProject)} + * instead. */ @Deprecated public ICExtensionReference[] getBinaryParserExtensions(IProject project) throws CoreException { @@ -619,7 +670,7 @@ public ICExtensionReference[] getBinaryParserExtensions(IProject project) throws if (project != null) { try { ICDescriptor cdesc = getCProjectDescription(project, false); - if (cdesc==null) + if (cdesc == null) return ext; ICExtensionReference[] cextensions = cdesc.get(BINARY_PARSER_UNIQ_ID, true); if (cextensions != null && cextensions.length > 0) @@ -632,10 +683,13 @@ public ICExtensionReference[] getBinaryParserExtensions(IProject project) throws } /** - * Returns the binary parser extensions for the default settings configuration. + * Returns the binary parser extensions for the default settings + * configuration. + * * @since 5.2 */ - public ICConfigExtensionReference[] getDefaultBinaryParserExtensions(IProject project) throws CoreException { + public ICConfigExtensionReference[] getDefaultBinaryParserExtensions(IProject project) + throws CoreException { ICConfigExtensionReference ext[] = new ICConfigExtensionReference[0]; if (project != null) { ICProjectDescription desc = CCorePlugin.getDefault().getProjectDescription(project, false); @@ -664,7 +718,7 @@ public IBinaryParser[] getBinaryParser(IProject project) throws CoreException { for (ICExtensionReference ref : cextensions) { IBinaryParser parser = null; try { - parser = (IBinaryParser)ref.createExtension(); + parser = (IBinaryParser) ref.createExtension(); } catch (ClassCastException e) { log(e); // wrong binary parser definition ? } @@ -682,7 +736,7 @@ public IBinaryParser[] getBinaryParser(IProject project) throws CoreException { if (parsers == null) { IBinaryParser parser = getDefaultBinaryParser(); if (parser != null) { - parsers = new IBinaryParser[] {parser}; + parsers = new IBinaryParser[] { parser }; } } return parsers; @@ -694,7 +748,8 @@ public IBinaryParser getDefaultBinaryParser() throws CoreException { if (id == null || id.isEmpty()) { id = DEFAULT_BINARY_PARSER_UNIQ_ID; } - IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(CCorePlugin.PLUGIN_ID, BINARY_PARSER_SIMPLE_ID); + IExtensionPoint extensionPoint = Platform.getExtensionRegistry() + .getExtensionPoint(CCorePlugin.PLUGIN_ID, BINARY_PARSER_SIMPLE_ID); IExtension extension = extensionPoint.getExtension(id); if (extension != null) { IConfigurationElement element[] = extension.getConfigurationElements(); @@ -705,7 +760,8 @@ public IBinaryParser getDefaultBinaryParser() throws CoreException { } } } else { - IStatus s = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, -1, CCorePlugin.getResourceString("CCorePlugin.exception.noBinaryFormat"), null); //$NON-NLS-1$ + IStatus s = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, -1, + CCorePlugin.getResourceString("CCorePlugin.exception.noBinaryFormat"), null); //$NON-NLS-1$ throw new CoreException(s); } return parser; @@ -740,14 +796,16 @@ public ICDescriptor getCProjectDescription(IProject project) throws CoreExceptio /** * Please use {@link #getProjectDescription(IProject, boolean)} to fetch the - * ICProjectDescription for the project. And use {@link ICProjectDescription#getConfigurations()} - * to get an array of ICConfigurationDescriptions, which have similar API to ICDescriptor, - * allowing you to store settings and configure extensions at the Configuration level - * rather than at the project level. + * ICProjectDescription for the project. And use + * {@link ICProjectDescription#getConfigurations()} to get an array of + * ICConfigurationDescriptions, which have similar API to ICDescriptor, + * allowing you to store settings and configure extensions at the + * Configuration level rather than at the project level. * * @param project * @param create - * @return ICDescriptor or null if create is false and no .cdtproject file exists on disk. + * @return ICDescriptor or null if create is false and + * no .cdtproject file exists on disk. * @throws CoreException * @deprecated */ @@ -758,24 +816,26 @@ public ICDescriptor getCProjectDescription(IProject project, boolean create) thr public void mapCProjectOwner(IProject project, String id, boolean override) throws CoreException { try { - if (!override) { - fNewCProjectDescriptionManager.getDescriptorManager().configure(project, id); - } else { - fNewCProjectDescriptionManager.getDescriptorManager().convert(project, id); - } + if (!override) { + fNewCProjectDescriptionManager.getDescriptorManager().configure(project, id); + } else { + fNewCProjectDescriptionManager.getDescriptorManager().convert(project, id); + } } catch (Exception e) { throw ExceptionFactory.createCoreException(e); } } /** - * @deprecated Settings should be set per ICConfigurationDescription rather than - * global to the project. Please use {@link #getProjectDescription(IProject, boolean)} - * to fetch the ICProjectDescription for the project. And use - * {@link ICProjectDescription#getConfigurations()} to get an array of - * ICConfigurationDescriptions, which have similar API to ICDescriptor, - * allowing you to store settings and configure extensions at the Configuration level - * rather than at the project level. + * @deprecated Settings should be set per ICConfigurationDescription rather + * than global to the project. Please use + * {@link #getProjectDescription(IProject, boolean)} to fetch + * the ICProjectDescription for the project. And use + * {@link ICProjectDescription#getConfigurations()} to get an + * array of ICConfigurationDescriptions, which have similar API + * to ICDescriptor, allowing you to store settings and configure + * extensions at the Configuration level rather than at the + * project level. */ @Deprecated public ICDescriptorManager getCDescriptorManager() { @@ -785,20 +845,23 @@ public ICDescriptorManager getCDescriptorManager() { /** * Creates a C project resource given the project handle and description. * - * @param description the project description to create a project resource for - * @param projectHandle the project handle to create a project resource for - * @param monitor the progress monitor to show visual progress with - * @param projectID required for mapping the project to an owner + * @param description + * the project description to create a project resource for + * @param projectHandle + * the project handle to create a project resource for + * @param monitor + * the progress monitor to show visual progress with + * @param projectID + * required for mapping the project to an owner * - * @exception CoreException if the operation fails - * @exception OperationCanceledException if the operation is canceled + * @exception CoreException + * if the operation fails + * @exception OperationCanceledException + * if the operation is canceled */ - public IProject createCProject( - final IProjectDescription description, - final IProject projectHandle, - IProgressMonitor monitor, - final String projectID) - throws CoreException, OperationCanceledException { + public IProject createCProject(final IProjectDescription description, final IProject projectHandle, + IProgressMonitor monitor, final String projectID) + throws CoreException, OperationCanceledException { getWorkspace().run(new IWorkspaceRunnable() { @Override @@ -831,19 +894,13 @@ public void run(IProgressMonitor monitor) throws CoreException { return projectHandle; } - public IProject createCDTProject( - final IProjectDescription description, - final IProject projectHandle, - IProgressMonitor monitor) throws CoreException, OperationCanceledException{ + public IProject createCDTProject(final IProjectDescription description, final IProject projectHandle, + IProgressMonitor monitor) throws CoreException, OperationCanceledException { return createCDTProject(description, projectHandle, null, monitor); } - public IProject createCDTProject( - final IProjectDescription description, - final IProject projectHandle, - final String bsId, - IProgressMonitor monitor) - throws CoreException, OperationCanceledException { + public IProject createCDTProject(final IProjectDescription description, final IProject projectHandle, + final String bsId, IProgressMonitor monitor) throws CoreException, OperationCanceledException { getWorkspace().run(new IWorkspaceRunnable() { @Override @@ -864,7 +921,7 @@ public void run(IProgressMonitor monitor) throws CoreException { // Open first. projectHandle.open(IResource.BACKGROUND_REFRESH, new SubProgressMonitor(monitor, 1)); - // mapCProjectOwner(projectHandle, projectID, false); + // mapCProjectOwner(projectHandle, projectID, false); // Add C Nature ... does not add duplicates CProjectNature.addCNature(projectHandle, new SubProgressMonitor(monitor, 1)); @@ -883,7 +940,8 @@ public void run(IProgressMonitor monitor) throws CoreException { if (cfg == null) { ICConfigurationDescription prefCfg = getPreferenceConfiguration(bsId); if (prefCfg != null) { - cfg = projDes.createConfiguration(CDataUtil.genId(prefCfg.getId()), prefCfg.getName(), prefCfg); + cfg = projDes.createConfiguration(CDataUtil.genId(prefCfg.getId()), + prefCfg.getName(), prefCfg); } } @@ -900,32 +958,30 @@ public void run(IProgressMonitor monitor) throws CoreException { } /** - * Method convertProjectFromCtoCC converts - * a C Project to a C++ Project - * The newProject MUST, not be null, already have a C Nature - * && must NOT already have a C++ Nature + * Method convertProjectFromCtoCC converts a C Project to a C++ Project The + * newProject MUST, not be null, already have a C Nature && must NOT already + * have a C++ Nature * * @param projectHandle * @param monitor * @throws CoreException */ - public void convertProjectFromCtoCC(IProject projectHandle, IProgressMonitor monitor) throws CoreException { - if ((projectHandle != null) - && projectHandle.hasNature(CProjectNature.C_NATURE_ID) - && !projectHandle.hasNature(CCProjectNature.CC_NATURE_ID)) { + public void convertProjectFromCtoCC(IProject projectHandle, IProgressMonitor monitor) + throws CoreException { + if ((projectHandle != null) && projectHandle.hasNature(CProjectNature.C_NATURE_ID) + && !projectHandle.hasNature(CCProjectNature.CC_NATURE_ID)) { // Add C++ Nature ... does not add duplicates CCProjectNature.addCCNature(projectHandle, monitor); } } /** - * Method to convert a project to a C nature - * All checks should have been done externally - * (as in the Conversion Wizards). - * This method blindly does the conversion. + * Method to convert a project to a C nature All checks should have been + * done externally (as in the Conversion Wizards). This method blindly does + * the conversion. */ public void convertProjectToC(IProject projectHandle, IProgressMonitor monitor, String projectID) - throws CoreException { + throws CoreException { if ((projectHandle == null) || (monitor == null) || (projectID == null)) { return; } @@ -936,7 +992,7 @@ public void convertProjectToC(IProject projectHandle, IProgressMonitor monitor, } public void convertProjectToNewC(IProject projectHandle, String bsId, IProgressMonitor monitor) - throws CoreException { + throws CoreException { if ((projectHandle == null) || (monitor == null) || (bsId == null)) { throw new NullPointerException(); } @@ -950,7 +1006,7 @@ public void convertProjectToNewC(IProject projectHandle, String bsId, IProgressM * Method to convert a project to a C++ nature */ public void convertProjectToCC(IProject projectHandle, IProgressMonitor monitor, String projectID) - throws CoreException { + throws CoreException { if ((projectHandle == null) || (monitor == null) || (projectID == null)) { return; } @@ -960,7 +1016,7 @@ public void convertProjectToCC(IProject projectHandle, IProgressMonitor monitor, } public void convertProjectToNewCC(IProject projectHandle, String bsId, IProgressMonitor monitor) - throws CoreException { + throws CoreException { if ((projectHandle == null) || (monitor == null) || (bsId == null)) { throw new NullPointerException(); } @@ -971,10 +1027,12 @@ public void convertProjectToNewCC(IProject projectHandle, String bsId, IProgress /** * Get the IProcessList contributed interface for the platform. + * * @return IProcessList */ public IProcessList getProcessList() throws CoreException { - IExtensionPoint extension = Platform.getExtensionRegistry().getExtensionPoint(CCorePlugin.PLUGIN_ID, "ProcessList"); //$NON-NLS-1$ + IExtensionPoint extension = Platform.getExtensionRegistry().getExtensionPoint(CCorePlugin.PLUGIN_ID, + "ProcessList"); //$NON-NLS-1$ if (extension != null) { IExtension[] extensions = extension.getExtensions(); IConfigurationElement defaultContributor = null; @@ -983,7 +1041,8 @@ public IProcessList getProcessList() throws CoreException { for (IConfigurationElement configElement : configElements) { if (configElement.getName().equals("processList")) { //$NON-NLS-1$ String platform = configElement.getAttribute("platform"); //$NON-NLS-1$ - if (platform == null) { // first contributor found with not platform will be default. + if (platform == null) { // first contributor found with + // not platform will be default. if (defaultContributor == null) { defaultContributor = configElement; } @@ -1002,18 +1061,23 @@ public IProcessList getProcessList() throws CoreException { } /** - * @deprecated since CDT 6.1. Use {@link ErrorParserManager#getErrorParserAvailableIds()} instead + * @deprecated since CDT 6.1. Use + * {@link ErrorParserManager#getErrorParserAvailableIds()} + * instead * @return array of error parsers ids */ @Deprecated public String[] getAllErrorParsersIDs() { ErrorParserExtensionManager.loadErrorParserExtensions(); - return ErrorParserExtensionManager.getErrorParserAvailableIdsInContext(ErrorParserManager.BUILD_CONTEXT); + return ErrorParserExtensionManager + .getErrorParserAvailableIdsInContext(ErrorParserManager.BUILD_CONTEXT); } /** - * @deprecated since CDT 6.1. Use {@link ErrorParserManager#getErrorParserCopy(String)} instead - * @param id - id of error parser + * @deprecated since CDT 6.1. Use + * {@link ErrorParserManager#getErrorParserCopy(String)} instead + * @param id + * - id of error parser * @return array of error parsers */ @Deprecated @@ -1036,11 +1100,13 @@ public IScannerInfoProvider getScannerInfoProvider(IProject project) { if (provider != null) return provider; - // Next search the extension registry to see if a provider is registered with a build command + // Next search the extension registry to see if a provider is + // registered with a build command provider = getExtensionScannerInfoProvider2(project); // Regular usage is where Language Settings Providers are employed - if (provider == null && ScannerDiscoveryLegacySupport.isLanguageSettingsProvidersFunctionalityEnabled(project)) { + if (provider == null && ScannerDiscoveryLegacySupport + .isLanguageSettingsProvidersFunctionalityEnabled(project)) { provider = new LanguageSettingsScannerInfoProvider(); } @@ -1055,14 +1121,15 @@ public IScannerInfoProvider getScannerInfoProvider(IProject project) { return null; log(e); - } + } return provider; } /** - * Clears cached scanner info provider for the given project so that the next call to - * {@link #getScannerInfoProvider(IProject)} would return an up to date scanner info provider. + * Clears cached scanner info provider for the given project so that the + * next call to {@link #getScannerInfoProvider(IProject)} would return an up + * to date scanner info provider. * * @noreference This method is not intended to be referenced by clients. */ @@ -1078,8 +1145,8 @@ public void resetCachedScannerInfoProvider(IProject project) { } /** - * Find {@link IScannerInfoProvider} registered as extension via extension point - * org.eclipse.cdt.core.ScannerInfoProvider2. + * Find {@link IScannerInfoProvider} registered as extension via extension + * point org.eclipse.cdt.core.ScannerInfoProvider2. */ private IScannerInfoProvider getExtensionScannerInfoProvider2(IProject project) throws CoreException { IScannerInfoProvider provider = null; @@ -1096,7 +1163,7 @@ private IScannerInfoProvider getExtensionScannerInfoProvider2(IProject project) ICommand[] commands = desc.getBuildSpec(); for (ICommand command : commands) if (builder.equals(command.getBuilderName())) - provider = (IScannerInfoProvider)elem.createExecutableExtension("class"); //$NON-NLS-1$ + provider = (IScannerInfoProvider) elem.createExecutableExtension("class"); //$NON-NLS-1$ } } } @@ -1105,10 +1172,12 @@ private IScannerInfoProvider getExtensionScannerInfoProvider2(IProject project) } /** - * Helper function, returning the content type for a filename - * Same as:
-	 * 	getContentType(null, filename)
+	 * Helper function, returning the content type for a filename Same as:
+	 * 
+	 * 
+	 * getContentType(null, filename)
 	 * 
+ * * @param filename * @return the content type found, or null */ @@ -1117,11 +1186,15 @@ public static IContentType getContentType(String filename) { } /** - * Returns the content type for a filename. The method respects - * project specific content type definitions. The lookup prefers case- - * sensitive matches over the others. - * @param project a project with possible project specific settings. Can be null - * @param filename a filename to compute the content type for + * Returns the content type for a filename. The method respects project + * specific content type definitions. The lookup prefers case- sensitive + * matches over the others. + * + * @param project + * a project with possible project specific settings. Can be + * null + * @param filename + * a filename to compute the content type for * @return the content type found or null */ public static IContentType getContentType(IProject project, String filename) { @@ -1142,35 +1215,42 @@ public static void setUseProjectSpecificContentTypes(IProject project, boolean v CContentTypes.setUseProjectSpecificContentTypes(project, val); } - private static final String MODEL = CCorePlugin.PLUGIN_ID + "/debug/model" ; //$NON-NLS-1$ - private static final String PARSER = CCorePlugin.PLUGIN_ID + "/debug/parser" ; //$NON-NLS-1$ - private static final String PARSER_EXCEPTIONS = CCorePlugin.PLUGIN_ID + "/debug/parser/exceptions" ; //$NON-NLS-1$ + private static final String MODEL = CCorePlugin.PLUGIN_ID + "/debug/model"; //$NON-NLS-1$ + private static final String PARSER = CCorePlugin.PLUGIN_ID + "/debug/parser"; //$NON-NLS-1$ + private static final String PARSER_EXCEPTIONS = CCorePlugin.PLUGIN_ID + "/debug/parser/exceptions"; //$NON-NLS-1$ private static final String SCANNER = CCorePlugin.PLUGIN_ID + "/debug/scanner"; //$NON-NLS-1$ - private static final String DELTA = CCorePlugin.PLUGIN_ID + "/debug/deltaprocessor" ; //$NON-NLS-1$ + private static final String DELTA = CCorePlugin.PLUGIN_ID + "/debug/deltaprocessor"; //$NON-NLS-1$ /** - * Configure the plug-in with respect to option settings defined in ".options" file + * Configure the plug-in with respect to option settings defined in + * ".options" file */ public void configurePluginDebugOptions() { if (CCorePlugin.getDefault().isDebugging()) { String option = Platform.getDebugOption(PARSER); - if (option != null) Util.VERBOSE_PARSER = option.equalsIgnoreCase("true") ; //$NON-NLS-1$ + if (option != null) + Util.VERBOSE_PARSER = option.equalsIgnoreCase("true"); //$NON-NLS-1$ option = Platform.getDebugOption(PARSER_EXCEPTIONS); - if (option != null) Util.PARSER_EXCEPTIONS = option.equalsIgnoreCase("true"); //$NON-NLS-1$ + if (option != null) + Util.PARSER_EXCEPTIONS = option.equalsIgnoreCase("true"); //$NON-NLS-1$ option = Platform.getDebugOption(SCANNER); - if (option != null) Util.VERBOSE_SCANNER = option.equalsIgnoreCase("true"); //$NON-NLS-1$ + if (option != null) + Util.VERBOSE_SCANNER = option.equalsIgnoreCase("true"); //$NON-NLS-1$ option = Platform.getDebugOption(MODEL); - if (option != null) Util.VERBOSE_MODEL = option.equalsIgnoreCase("true") ; //$NON-NLS-1$ + if (option != null) + Util.VERBOSE_MODEL = option.equalsIgnoreCase("true"); //$NON-NLS-1$ option = Platform.getDebugOption(DELTA); - if (option != null) Util.VERBOSE_DELTA= option.equalsIgnoreCase("true") ; //$NON-NLS-1$ + if (option != null) + Util.VERBOSE_DELTA = option.equalsIgnoreCase("true"); //$NON-NLS-1$ } } - // Preference to turn on/off the use of structural parse mode to build the CModel. + // Preference to turn on/off the use of structural parse mode to build the + // CModel. public void setStructuralParseMode(boolean useNewParser) { getPluginPreferences().setValue(PREF_USE_STRUCTURAL_PARSE_MODE, useNewParser); savePluginPreferences(); @@ -1181,11 +1261,12 @@ public boolean useStructuralParseMode() { } /** - * @deprecated use {@link ITranslationUnit} or {@link ILanguage} to construct ASTs, instead. + * @deprecated use {@link ITranslationUnit} or {@link ILanguage} to + * construct ASTs, instead. */ @Deprecated public org.eclipse.cdt.core.dom.CDOM getDOM() { - return org.eclipse.cdt.core.dom.CDOM.getInstance(); + return org.eclipse.cdt.core.dom.CDOM.getInstance(); } public ICdtVariableManager getCdtVariableManager() { @@ -1196,62 +1277,77 @@ public IEnvironmentVariableManager getBuildEnvironmentManager() { return EnvironmentVariableManager.getDefault(); } - public ICConfigurationDescription getPreferenceConfiguration(String buildSystemId) throws CoreException{ + public ICConfigurationDescription getPreferenceConfiguration(String buildSystemId) throws CoreException { return fNewCProjectDescriptionManager.getPreferenceConfiguration(buildSystemId); } - public ICConfigurationDescription getPreferenceConfiguration(String buildSystemId, boolean write) throws CoreException{ + public ICConfigurationDescription getPreferenceConfiguration(String buildSystemId, boolean write) + throws CoreException { return fNewCProjectDescriptionManager.getPreferenceConfiguration(buildSystemId, write); } - public void setPreferenceConfiguration(String buildSystemId, ICConfigurationDescription des) throws CoreException { + public void setPreferenceConfiguration(String buildSystemId, ICConfigurationDescription des) + throws CoreException { fNewCProjectDescriptionManager.setPreferenceConfiguration(buildSystemId, des); } /** - * Equivalent to createProjectDescription(IProject, boolean, false). + * Equivalent to + * createProjectDescription(IProject, boolean, false). * * @see #createProjectDescription(IProject, boolean, boolean) */ - public ICProjectDescription createProjectDescription(IProject project, boolean loadIfExists) throws CoreException{ + public ICProjectDescription createProjectDescription(IProject project, boolean loadIfExists) + throws CoreException { return fNewCProjectDescriptionManager.createProjectDescription(project, loadIfExists); } /** * Creates and returns a writable project description. * - * @param project project for which the project description is requested - * @param loadIfExists if true the method first tries to load and return the project description - * from the settings file (.cproject), - * if false, the stored settings are ignored and the new (empty) project description is - * created - * @param creating if true the created project description will be contain the true - * "isCdtProjectCreating" state. - *
NOTE: in case the project already contains the project description AND its - * "isCdtProjectCreating" is false the resulting description will be created with the false - * "isCdtProjectCreating" state. + * @param project + * project for which the project description is requested + * @param loadIfExists + * if true the method first tries to load and return the project + * description from the settings file (.cproject), if false, the + * stored settings are ignored and the new (empty) project + * description is created + * @param creating + * if true the created project description will be contain the + * true "isCdtProjectCreating" state.
+ * NOTE: in case the project already contains the project + * description AND its "isCdtProjectCreating" is false the + * resulting description will be created with the false + * "isCdtProjectCreating" state. * - *
NOTE: changes made to the returned project description will not be applied until - * the {@link #setProjectDescription(IProject, ICProjectDescription)} is called. + *
+ * NOTE: changes made to the returned project description will + * not be applied until the + * {@link #setProjectDescription(IProject, ICProjectDescription)} + * is called. * @return {@link ICProjectDescription} * @throws CoreException */ - public ICProjectDescription createProjectDescription(IProject project, boolean loadIfExists, boolean creating) throws CoreException{ + public ICProjectDescription createProjectDescription(IProject project, boolean loadIfExists, + boolean creating) throws CoreException { return fNewCProjectDescriptionManager.createProjectDescription(project, loadIfExists, creating); } /** - * Returns the project description associated with this project or null if the project does not - * contain the CDT data associated with it. + * Returns the project description associated with this project or null if + * the project does not contain the CDT data associated with it. * - * This is a convenience method fully equivalent to getProjectDescription(project, true) - * see {@link #getProjectDescription(IProject, boolean)} for more detail. + * This is a convenience method fully equivalent to + * getProjectDescription(project, true) see + * {@link #getProjectDescription(IProject, boolean)} for more detail. * * @param project - * @return a writable copy of the ICProjectDescription or null if the project does not contain - * the CDT data associated with it. - *
Note: changes to the project description will not be reflected/used by the core - * until the {@link #setProjectDescription(IProject, ICProjectDescription)} is called. + * @return a writable copy of the ICProjectDescription or null if the + * project does not contain the CDT data associated with it.
+ * Note: changes to the project description will not be + * reflected/used by the core until the + * {@link #setProjectDescription(IProject, ICProjectDescription)} is + * called. * * @see #getProjectDescription(IProject, boolean) */ @@ -1260,9 +1356,9 @@ public ICProjectDescription getProjectDescription(IProject project) { } /** - * Called to save/apply the project description. - * The method should be called to apply changes made to the project description - * returned by the {@link #getProjectDescription(IProject, boolean)} or + * Called to save/apply the project description. The method should be called + * to apply changes made to the project description returned by the + * {@link #getProjectDescription(IProject, boolean)} or * {@link #createProjectDescription(IProject, boolean)} * * @param project @@ -1276,37 +1372,46 @@ public void setProjectDescription(IProject project, ICProjectDescription des) th fNewCProjectDescriptionManager.setProjectDescription(project, des); } - public void setProjectDescription(IProject project, ICProjectDescription des, boolean force, IProgressMonitor monitor) throws CoreException { + public void setProjectDescription(IProject project, ICProjectDescription des, boolean force, + IProgressMonitor monitor) throws CoreException { fNewCProjectDescriptionManager.setProjectDescription(project, des, force, monitor); } /** - * Returns the project description associated with this project or null if the project - * does not contain the CDT data associated with it. + * Returns the project description associated with this project or null if + * the project does not contain the CDT data associated with it. * - * @param project project for which the description is requested - * @param write if true, the writable description copy is returned. - * If false the cached read-only description is returned. + * @param project + * project for which the description is requested + * @param write + * if true, the writable description copy is returned. If false + * the cached read-only description is returned. * - *
CDT core maintains the cached project description settings. If only read access is needed - * to description, then the read-only project description should be obtained. - * This description always operates with cached data and thus it is better to use it for - * performance reasons. All set* calls to the read-only description result in - * the {@link WriteAccessException}. + *
+ * CDT core maintains the cached project description settings. If + * only read access is needed to description, then the read-only + * project description should be obtained. This description + * always operates with cached data and thus it is better to use + * it for performance reasons. All set* calls to the read-only + * description result in the {@link WriteAccessException}. * - * When the writable description is requested, the description copy is created. Changes to this - * description will not be reflected/used by the core and the Build System until the - * {@link #setProjectDescription(IProject, ICProjectDescription)} is called. + * When the writable description is requested, the description + * copy is created. Changes to this description will not be + * reflected/used by the core and the Build System until the + * {@link #setProjectDescription(IProject, ICProjectDescription)} + * is called. * - * Each getProjectDescription(project, true) returns a new copy of the project description. + * Each getProjectDescription(project, true) returns a new copy + * of the project description. * - * The writable description uses the cached data until the first set call - * after that the description communicates directly to the Build System - * i.e. the implementer of the org.eclipse.cdt.core.CConfigurationDataProvider extension - * This ensures the Core<->Build System settings integrity. + * The writable description uses the cached data until the first + * set call after that the description communicates directly to + * the Build System i.e. the implementer of the + * org.eclipse.cdt.core.CConfigurationDataProvider extension This + * ensures the Core<->Build System settings integrity. * - * @return {@link ICProjectDescription} or null if the project does not contain the - * CDT data associated with it. + * @return {@link ICProjectDescription} or null if the project does not + * contain the CDT data associated with it. */ public ICProjectDescription getProjectDescription(IProject project, boolean write) { return fNewCProjectDescriptionManager.getProjectDescription(project, write); @@ -1315,11 +1420,14 @@ public ICProjectDescription getProjectDescription(IProject project, boolean writ /** * Forces the cached data of the specified projects to be re-calculated. * - * @param projects if null, all projects within the workspace are updated + * @param projects + * if null, all projects within the workspace are + * updated * @param monitor * @throws CoreException */ - public void updateProjectDescriptions(IProject projects[], IProgressMonitor monitor) throws CoreException{ + public void updateProjectDescriptions(IProject projects[], IProgressMonitor monitor) + throws CoreException { fNewCProjectDescriptionManager.updateProjectDescriptions(projects, monitor); } @@ -1332,7 +1440,8 @@ public boolean isNewStyleProject(IProject project) { } /** - * Answers whether the given project is a new-style project, i.e. CConfigurationDataProvider-driven + * Answers whether the given project is a new-style project, i.e. + * CConfigurationDataProvider-driven */ public boolean isNewStyleProject(ICProjectDescription des) { return fNewCProjectDescriptionManager.isNewStyleProject(des); @@ -1352,7 +1461,8 @@ public static IUserVarSupplier getUserVarSupplier() { // NON-API /** - * @noreference This constructor is not intended to be referenced by clients. + * @noreference This constructor is not intended to be referenced by + * clients. */ public CCorePlugin() { super(); @@ -1369,9 +1479,12 @@ public static void log(String e) { /** * Prints a message in the log * - * @param severity - desired severity of the message in the log, - * one of {@link IStatus#INFO}, {@link IStatus#WARNING} or {@link IStatus#ERROR} - * @param msg - message + * @param severity + * - desired severity of the message in the log, one of + * {@link IStatus#INFO}, {@link IStatus#WARNING} or + * {@link IStatus#ERROR} + * @param msg + * - message * * @since 5.5 * @noreference This method is not intended to be referenced by clients. @@ -1379,13 +1492,16 @@ public static void log(String e) { public static void log(int severity, String msg) { log(new Status(severity, PLUGIN_ID, msg)); } - + /** * Prints a message in the log accompanied by stack trace * - * @param severity - desired severity of the message in the log, - * one of {@link IStatus#INFO}, {@link IStatus#WARNING} or {@link IStatus#ERROR} - * @param msg - message + * @param severity + * - desired severity of the message in the log, one of + * {@link IStatus#INFO}, {@link IStatus#WARNING} or + * {@link IStatus#ERROR} + * @param msg + * - message * * @since 5.5 * @noreference This method is not intended to be referenced by clients. @@ -1393,12 +1509,12 @@ public static void log(int severity, String msg) { public static void logStackTrace(int severity, String msg) { log(new Status(severity, PLUGIN_ID, msg, new Exception())); } - + /** * @noreference This method is not intended to be referenced by clients. */ public static void log(Throwable e) { - String msg= e.getMessage(); + String msg = e.getMessage(); if (msg == null) { log("Error", e); //$NON-NLS-1$ } else { @@ -1449,14 +1565,15 @@ public static IPDOMManager getPDOMManager() { } /** - * Returns the preference controlling whether source roots are shown at the top of projects - * or embedded within the resource tree of projects when they are not top level folders. + * Returns the preference controlling whether source roots are shown at the + * top of projects or embedded within the resource tree of projects when + * they are not top level folders. * * @return boolean preference value * @since 5.2 */ public static boolean showSourceRootsAtTopOfProject() { return InstanceScope.INSTANCE.getNode(PLUGIN_ID) - .getBoolean(CCorePreferenceConstants.SHOW_SOURCE_ROOTS_AT_TOP_LEVEL_OF_PROJECT, true); + .getBoolean(CCorePreferenceConstants.SHOW_SOURCE_ROOTS_AT_TOP_LEVEL_OF_PROJECT, true); } } diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/CBuildConfiguration.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/CBuildConfiguration.java new file mode 100644 index 00000000000..f7535045101 --- /dev/null +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/CBuildConfiguration.java @@ -0,0 +1,139 @@ +package org.eclipse.cdt.core.build; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.parser.IScannerInfo; +import org.eclipse.core.resources.IBuildConfiguration; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IProjectDescription; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ProjectScope; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtension; +import org.eclipse.core.runtime.IExtensionPoint; +import org.eclipse.core.runtime.IExtensionRegistry; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.PlatformObject; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.preferences.IEclipsePreferences; +import org.osgi.service.prefs.BackingStoreException; + +/** + * Root class for CDT build configurations. Provides access to the build + * settings for subclasses. + * + * @since 5.12 + */ +public abstract class CBuildConfiguration extends PlatformObject { + + private static final String TOOLCHAIN = "cdt.toolChain"; //$NON-NLS-1$ + + private final IBuildConfiguration config; + private CToolChain toolChain; + + protected CBuildConfiguration(IBuildConfiguration config) { + this.config = config; + } + + public IBuildConfiguration getBuildConfiguration() { + return config; + } + + public String getName() { + return config.getName(); + } + + public IProject getProject() { + return config.getProject(); + } + + public void setActive(IProgressMonitor monitor) throws CoreException { + IProject project = config.getProject(); + if (config.equals(project.getActiveBuildConfig())) { + // already set + return; + } + + IProjectDescription projectDesc = project.getDescription(); + projectDesc.setActiveBuildConfig(config.getName()); + project.setDescription(projectDesc, monitor); + } + + protected IEclipsePreferences getSettings() { + return (IEclipsePreferences) new ProjectScope(config.getProject()).getNode("org.eclipse.cdt.core") //$NON-NLS-1$ + .node("config") //$NON-NLS-1$ + .node(config.getName()); + } + + private synchronized CToolChain getToolChain(String id) throws CoreException { + IExtensionRegistry registry = Platform.getExtensionRegistry(); + IExtensionPoint point = registry.getExtensionPoint(CCorePlugin.PLUGIN_ID + ".ToolChain"); //$NON-NLS-1$ + for (IExtension extension : point.getExtensions()) { + for (IConfigurationElement element : extension.getConfigurationElements()) { + String eid = element.getAttribute("id"); //$NON-NLS-1$ + if (id.equals(eid)) { + String clsName = element.getAttribute("adaptor"); //$NON-NLS-1$ + if (clsName != null) { + try { + Class cls = Class.forName(clsName); + return (CToolChain) getAdapter(cls); + } catch (ClassNotFoundException e) { + throw new CoreException(new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, + "creating toolchain", e)); //$NON-NLS-1$ + } + } + } + } + } + return null; + } + + public synchronized void setToolChain(String id) throws CoreException { + CToolChain newtc = getToolChain(id); + if (newtc == null) { + throw new CoreException( + new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, "unknown toolchain: " + id)); //$NON-NLS-1$ + } + + IEclipsePreferences settings = getSettings(); + settings.put(TOOLCHAIN, id); + try { + settings.flush(); + } catch (BackingStoreException e) { + throw new CoreException( + new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, "saving toolchain id", e)); //$NON-NLS-1$ + } + + toolChain = newtc; + } + + public CToolChain getToolChain() throws CoreException { + if (toolChain == null) { + IEclipsePreferences settings = getSettings(); + String id = settings.get(TOOLCHAIN, ""); //$NON-NLS-1$ + if (id.isEmpty()) { + return null; + } else { + toolChain = getToolChain(id); + } + } + return toolChain; + } + + public IScannerInfo getScannerInfo(IResource resource) throws CoreException { + // By default, get it from the toolchain. + CToolChain toolChain = getToolChain(); + return toolChain != null ? toolChain.getScannerInfo(resource) : null; + } + + public void clearScannerInfo() throws CoreException { + } + + public CConsoleParser[] getConsoleParsers() throws CoreException { + CToolChain toolChain = getToolChain(); + return toolChain != null ? toolChain.getConsoleParsers() : null; + } + +} diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/CConsoleParser.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/CConsoleParser.java new file mode 100644 index 00000000000..49b8a0f7ab9 --- /dev/null +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/CConsoleParser.java @@ -0,0 +1,121 @@ +package org.eclipse.cdt.core.build; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.model.ICModelMarker; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.runtime.CoreException; + +/** + * This could be temporary. Provides a core parser for the TextConsole's + * IPatternMatchListener. + * + * TODO that framework doesn't work well for builds that need to use different + * parsers at different times. Should consider taking that architecture and + * making it work well for our needs. + * + * @since 5.12 + */ +public abstract class CConsoleParser { + + private final String pattern; + private final int flags; + private final String lineQualifier; + + private final Pattern errorPattern; + + public static final String LINK_OFFSET = "cdt.link.offset"; //$NON-NLS-1$ + public static final String LINK_LENGTH = "cdt.link.length"; //$NON-NLS-1$ + + protected CConsoleParser(String pattern, int flags, String lineQualifier) { + this.pattern = pattern; + this.flags = flags; + this.lineQualifier = lineQualifier; + this.errorPattern = Pattern.compile(pattern); + } + + protected CConsoleParser(String pattern) { + this(pattern, 0, null); + } + + /** + * Returns the pattern to be used for matching. The pattern is a string + * representing a regular expression. + * + * @return the regular expression to be used for matching + */ + public String getPattern() { + return pattern; + } + + /** + * Returns the flags to use when compiling this pattern match listener's + * regular expression, as defined by by + * Pattern.compile(String regex, int flags) + * + * @return the flags to use when compiling this pattern match listener's + * regular expression + * @see java.util.regex.Pattern#compile(java.lang.String, int) + */ + public int getCompilerFlags() { + return flags; + } + + /** + * Returns a simple regular expression used to identify lines that may match + * this pattern matcher's complete pattern, or null. Use of + * this attribute can improve performance by disqualifying lines from the + * search. When a line is found containing a match for this expression, the + * line is searched from the beginning for this pattern matcher's complete + * pattern. Lines not containing this pattern are discarded. + * + * @return a simple regular expression used to identify lines that may match + * this pattern matcher's complete pattern, or null + */ + public String getLineQualifier() { + return lineQualifier; + } + + protected abstract String getFileName(Matcher matcher); + + protected abstract int getLineNumber(Matcher matcher); + + protected abstract String getMessage(Matcher matcher); + + protected abstract int getSeverity(Matcher matcher); + + protected abstract int getLinkOffset(Matcher matcher); + + protected abstract int getLinkLength(Matcher matcher); + + public IMarker generateMarker(IFolder buildDirectory, String text) { + Matcher matcher = errorPattern.matcher(text); + if (matcher.matches()) { + String fileName = getFileName(matcher); + + IFile file = buildDirectory.getFile(fileName); + if (file.exists()) { + try { + IMarker marker = file.createMarker(ICModelMarker.C_MODEL_PROBLEM_MARKER); + marker.setAttribute(IMarker.MESSAGE, getMessage(matcher)); + marker.setAttribute(IMarker.SEVERITY, getSeverity(matcher)); + marker.setAttribute(IMarker.LINE_NUMBER, getLineNumber(matcher)); + marker.setAttribute(IMarker.CHAR_START, -1); + marker.setAttribute(IMarker.CHAR_END, -1); + marker.setAttribute(LINK_OFFSET, getLinkOffset(matcher)); + marker.setAttribute(LINK_LENGTH, getLinkLength(matcher)); + return marker; + } catch (CoreException e) { + CCorePlugin.log(e); + return null; + } + } + } + return null; + } + +} diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/CToolChain.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/CToolChain.java new file mode 100644 index 00000000000..c09a6166744 --- /dev/null +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/CToolChain.java @@ -0,0 +1,119 @@ +package org.eclipse.cdt.core.build; + +import java.util.List; +import java.util.Map; + +import org.eclipse.cdt.core.model.ILanguage; +import org.eclipse.cdt.core.parser.IScannerInfo; +import org.eclipse.cdt.internal.core.build.ScannerInfoData; +import org.eclipse.cdt.internal.core.build.ToolChainScannerInfo; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.PlatformObject; + +/** + * Root class for CDT toolchains. + * + * @since 5.12 + */ +public abstract class CToolChain extends PlatformObject { + + private final CBuildConfiguration config; + + private ScannerInfoData scannerInfo; + + protected CToolChain(CBuildConfiguration config) { + this.config = config; + } + + public static String[] splitCommand(String command) { + // TODO deal with quotes properly, for now just strip + return command.replace("\"", "").split("\\s+"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + + public CBuildConfiguration getBuildConfiguration() { + return config; + } + + /** + * Update the given environment to run the toolchain. + * + * @param env + */ + public void setEnvironment(Map env) { + // default, nothing + } + + /** + * Scan the commandLine and save the scanner info for the resource being + * built, or if perProject is true, for all resources in the project. The + * buildFolder to help find the resource is where the command ran. + * + * @param buildFolder + * @param commandLine + * @throws CoreException + */ + public void scanBuildOutput(IFolder buildFolder, String commandLine, boolean perProject) + throws CoreException { + // default, nothing + } + + protected void putScannerInfo(IResource resource, Map definedSymbols, + List includePaths, List macroFiles, List includeFiles, + List localIncludePath) throws CoreException { + if (scannerInfo == null) { + loadScannerInfo(); + } + scannerInfo.putScannerInfo(resource, new ToolChainScannerInfo(definedSymbols, includePaths, + macroFiles, includeFiles, localIncludePath)); + } + + protected void putScannerInfo(ILanguage language, Map definedSymbols, + List includePaths, List macroFiles, List includeFiles, + List localIncludePath) throws CoreException { + if (scannerInfo == null) { + loadScannerInfo(); + } + scannerInfo.putScannerInfo(language, new ToolChainScannerInfo(definedSymbols, includePaths, + macroFiles, includeFiles, localIncludePath)); + } + + private void loadScannerInfo() { + if (scannerInfo == null) { + scannerInfo = ScannerInfoData.load(this); + } + } + + /** + * Return the scanner info for the given resource. + * + * @param resource + * @return scanner info for the resource + * @throws CoreException + */ + public IScannerInfo getScannerInfo(IResource resource) throws CoreException { + loadScannerInfo(); + return scannerInfo.getScannerInfo(resource); + } + + public void clearScannerInfo() throws CoreException { + if (scannerInfo == null) { + scannerInfo = new ScannerInfoData(); + scannerInfo.queueSave(); + } else { + scannerInfo.clear(); + } + } + + /** + * Return the console parsers to be used when this toolchain is being used + * for a build. + * + * @return console parsers + */ + public CConsoleParser[] getConsoleParsers() { + return null; + } + +} diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/GCCToolChain.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/GCCToolChain.java new file mode 100644 index 00000000000..f62d7b0643f --- /dev/null +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/GCCToolChain.java @@ -0,0 +1,224 @@ +package org.eclipse.cdt.core.build; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.file.FileAlreadyExistsException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.model.ILanguage; +import org.eclipse.cdt.core.model.LanguageManager; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IAdapterFactory; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.content.IContentType; + +/** + * The GCC toolchain. Placing it in cdt.core for now. + * + * TODO move to it's own plug-in. + * + * @since 5.12 + */ +public class GCCToolChain extends CToolChain { + + public static final String ID = "org.eclipse.cdt.core.gcc"; //$NON-NLS-1$ + + public GCCToolChain(CBuildConfiguration config) { + super(config); + } + + private static Map cache = new HashMap<>(); + + public static class Factory implements IAdapterFactory { + @SuppressWarnings("unchecked") + @Override + public T getAdapter(Object adaptableObject, Class adapterType) { + if (adapterType.equals(GCCToolChain.class) && adaptableObject instanceof CBuildConfiguration) { + CBuildConfiguration config = (CBuildConfiguration) adaptableObject; + GCCToolChain toolChain = cache.get(config); + if (toolChain == null) { + toolChain = new GCCToolChain(config); + cache.put(config, toolChain); + } + return (T) toolChain; + } + return null; + } + + @Override + public Class[] getAdapterList() { + return new Class[] { GCCToolChain.class }; + } + } + + @Override + public void scanBuildOutput(IFolder buildFolder, String commandLine, boolean perProject) + throws CoreException { + try { + if (Platform.getOS().equals(Platform.OS_WIN32)) { + // Need to flip over the slashes on Windows + commandLine = commandLine.replace('\\', '/'); + } + String[] command = splitCommand(commandLine); + + // Change output to stdout + for (int i = 0; i < command.length - 1; ++i) { + if (command[i].equals("-o")) { //$NON-NLS-1$ + command[i + 1] = "-"; //$NON-NLS-1$ + break; + } + } + + // Change source file to a tmp file (needs to be empty) + Path tmpFile = null; + IFile file = null; + for (int i = 1; i < command.length; ++i) { + if (!command[i].startsWith("-")) { //$NON-NLS-1$ + // TODO optimize by dealing with multi arg options like -o + IFile f = buildFolder.getFile(command[i]); + if (f.exists() && CoreModel.isTranslationUnit(f)) { + // replace it with a temp file + Path parentPath = new File(((IFolder) f.getParent()).getLocationURI()).toPath(); + int n = 0; + while (true) { + tmpFile = parentPath.resolve(".sc" + n + "." + f.getFileExtension()); //$NON-NLS-1$ //$NON-NLS-2$ + command[i] = tmpFile.toString(); + try { + Files.createFile(tmpFile); + break; + } catch (FileAlreadyExistsException e) { + // try again + ++n; + } + } + file = f; + break; + } + } + } + + if (file == null) { + // can't do much without the source file + CCorePlugin.log("No source file for scanner discovery"); //$NON-NLS-1$ + return; + } + + // Add in the magic potion: -E -P -v -dD + String[] fullCmd = new String[command.length + 4]; + fullCmd[0] = command[0]; + fullCmd[1] = "-E"; //$NON-NLS-1$ + fullCmd[2] = "-P"; //$NON-NLS-1$ + fullCmd[3] = "-v"; //$NON-NLS-1$ + fullCmd[4] = "-dD"; //$NON-NLS-1$ + System.arraycopy(command, 1, fullCmd, 5, command.length - 1); + + File buildDir = new File(buildFolder.getLocationURI()); + Files.createDirectories(buildDir.toPath()); + + // Startup the command + ProcessBuilder processBuilder = new ProcessBuilder(fullCmd).directory(buildDir) + .redirectErrorStream(true); + setEnvironment(processBuilder.environment()); + Process process = processBuilder.start(); + + // Scan for the scanner info + Map symbols = new HashMap<>(); + List includePath = new ArrayList<>(); + Pattern definePattern = Pattern.compile("#define (.*)\\s(.*)"); //$NON-NLS-1$ + boolean inIncludePaths = false; + try (BufferedReader reader = new BufferedReader( + new InputStreamReader(process.getInputStream()))) { + for (String line = reader.readLine(); line != null; line = reader.readLine()) { + if (inIncludePaths) { + if (line.equals("End of search list.")) { //$NON-NLS-1$ + inIncludePaths = false; + } else { + includePath.add(line.trim()); + } + } else if (line.startsWith("#define ")) { //$NON-NLS-1$ + Matcher matcher = definePattern.matcher(line); + if (matcher.matches()) { + symbols.put(matcher.group(1), matcher.group(2)); + } + } else if (line.equals("#include <...> search starts here:")) { //$NON-NLS-1$ + inIncludePaths = true; + } + } + } + + if (perProject) { + IProject project = buildFolder.getProject(); + IContentType contentType = CCorePlugin.getContentType(project, file.getName()); + if (contentType != null) { + ILanguage language = LanguageManager.getInstance().getLanguage(contentType, project); + putScannerInfo(language, symbols, includePath, null, null, null); + } + } else { + putScannerInfo(file, symbols, includePath, null, null, null); + } + + if (tmpFile != null) { + Files.delete(tmpFile); + } + } catch (IOException e) { + throw new CoreException( + new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, "Scanning build output", e)); //$NON-NLS-1$ + } + } + + @Override + public CConsoleParser[] getConsoleParsers() { + // ../src/Test.cpp:4:1: error: 'x' was not declared in this scope + + return new CConsoleParser[] { new CConsoleParser("(.*?):(\\d+):(\\d+:)? (fatal )?error: (.*)") { //$NON-NLS-1$ + @Override + protected int getSeverity(Matcher matcher) { + return IMarker.SEVERITY_ERROR; + } + + @Override + protected String getMessage(Matcher matcher) { + return matcher.group(5); + } + + @Override + protected int getLineNumber(Matcher matcher) { + return Integer.parseInt(matcher.group(2)); + } + + @Override + protected String getFileName(Matcher matcher) { + return matcher.group(1); + } + + @Override + protected int getLinkOffset(Matcher matcher) { + return 0; + } + + @Override + protected int getLinkLength(Matcher matcher) { + return matcher.group(1).length() + 1 + matcher.group(2).length() + 1 + + matcher.group(3).length(); + } + } }; + } + +} diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/IConsoleService.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/IConsoleService.java new file mode 100644 index 00000000000..cacc1e264d6 --- /dev/null +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/IConsoleService.java @@ -0,0 +1,45 @@ +package org.eclipse.cdt.core.build; + +import java.io.IOException; + +import org.eclipse.core.resources.IFolder; + +/** + * This may be temporary. It's uses the TextConsole's parsing and hyperlink + * framework to parse build output for errors. + * + * TODO Should we replace all CDT build consoles with this. + * + * @since 5.12 + */ +public interface IConsoleService { + + /** + * Display the stdout and stderr of the process in the console. Use the + * console parsers to parse that output to mark errors and warnings and + * such. The build directory helps to find resources for markers. + * + * @param process + * @param consoleParsers + * @param buildDirectory + * @throws IOException + */ + void monitor(Process process, CConsoleParser[] consoleParsers, IFolder buildDirectory) throws IOException; + + /** + * Write a message on the console stdout. + * + * @param msg + * @throws IOException + */ + void writeOutput(String msg) throws IOException; + + /** + * Write a message on the console stderr. + * + * @param msg + * @throws IOException + */ + void writeError(String msg) throws IOException; + +} diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/build/ScannerInfoData.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/build/ScannerInfoData.java new file mode 100644 index 00000000000..6de24163102 --- /dev/null +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/build/ScannerInfoData.java @@ -0,0 +1,166 @@ +package org.eclipse.cdt.internal.core.build; + +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.Reader; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.build.CBuildConfiguration; +import org.eclipse.cdt.core.build.CToolChain; +import org.eclipse.cdt.core.model.ILanguage; +import org.eclipse.cdt.core.model.LanguageManager; +import org.eclipse.cdt.core.parser.IScannerInfo; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.content.IContentType; + +import com.google.gson.Gson; + +public class ScannerInfoData { + + private Set perResourceInfo; + private Map perLanguageInfo; + + private transient Path savePath; + private transient Map infoCache; + private transient Map resourceCache; + + public void createCache() { + infoCache = new HashMap<>(); + resourceCache = new HashMap<>(); + if (perResourceInfo != null) { + for (ToolChainScannerInfo info : perResourceInfo) { + infoCache.put(info, info); + for (String path : info.getResourcePaths()) { + resourceCache.put(path, info); + } + } + } + } + + private boolean perResource() { + return perResourceInfo != null && !perResourceInfo.isEmpty(); + } + + private boolean perLanguage() { + return perLanguageInfo != null && !perLanguageInfo.isEmpty(); + } + + public IScannerInfo getScannerInfo(IResource resource) { + if (perResource()) { + ToolChainScannerInfo info = resourceCache.get(resource.getFullPath().toString()); + if (info != null) { + return info.getScannerInfo(); + } + } + + // Else try language + if (perLanguage()) { + IProject project = resource.getProject(); + IContentType contentType = CCorePlugin.getContentType(project, resource.getName()); + if (contentType != null) { + ILanguage language = LanguageManager.getInstance().getLanguage(contentType, project); + ToolChainScannerInfo info = perLanguageInfo.get(language.getId()); + if (info != null) { + return info.getScannerInfo(); + } + } + } + + return null; + } + + public IScannerInfo getScannerInfo(ILanguage language) { + if (perLanguage()) { + ToolChainScannerInfo info = perLanguageInfo.get(language.getId()); + if (info != null) { + return info.getScannerInfo(); + } + } + return null; + } + + public void putScannerInfo(IResource resource, ToolChainScannerInfo info) { + if (perResourceInfo == null) { + perResourceInfo = new HashSet<>(); + infoCache = new HashMap<>(); + infoCache.put(info, info); + } else { + ToolChainScannerInfo existing = infoCache.get(info); + if (existing != null) { + info = existing; + } else { + perResourceInfo.add(info); + infoCache.put(info, info); + } + } + + info.addResource(resource); + resourceCache.put(resource.getFullPath().toString(), info); + queueSave(); + } + + public void putScannerInfo(ILanguage language, ToolChainScannerInfo info) { + if (perLanguageInfo == null) { + perLanguageInfo = new HashMap<>(); + } + perLanguageInfo.put(language.getId(), info); + queueSave(); + } + + public static ScannerInfoData load(CToolChain toolChain) { + IPath stateLoc = Platform.getStateLocation(CCorePlugin.getDefault().getBundle()); + CBuildConfiguration config = toolChain.getBuildConfiguration(); + IPath scannerInfoPath = stateLoc.append(config.getProject().getName()) + .append(config.getName() + ".scInfo"); //$NON-NLS-1$ + File scannerInfoFile = scannerInfoPath.toFile(); + ScannerInfoData info = null; + if (scannerInfoFile.canRead()) { + try (Reader reader = new FileReader(scannerInfoFile)) { + info = new Gson().fromJson(reader, ScannerInfoData.class); + } catch (Exception e) { + CCorePlugin.log(e); + } + } + + if (info == null) { + info = new ScannerInfoData(); + } + + info.savePath = scannerInfoFile.toPath(); + info.createCache(); + return info; + } + + public void save() { + try { + String json = new Gson().toJson(this); + Files.createDirectories(savePath.getParent()); + Files.write(savePath, json.getBytes(StandardCharsets.UTF_8)); + } catch (IOException e) { + CCorePlugin.log(e); + } + } + + public void queueSave() { + ScannerInfoSaveParticipant.getInstance().save(this); + } + + public void clear() { + perLanguageInfo = null; + perResourceInfo = null; + createCache(); + queueSave(); + } + +} diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/build/ScannerInfoSaveParticipant.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/build/ScannerInfoSaveParticipant.java new file mode 100644 index 00000000000..cac8016956c --- /dev/null +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/build/ScannerInfoSaveParticipant.java @@ -0,0 +1,50 @@ +package org.eclipse.cdt.internal.core.build; + +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.core.resources.ISaveContext; +import org.eclipse.core.resources.ISaveParticipant; +import org.eclipse.core.runtime.CoreException; + +public class ScannerInfoSaveParticipant implements ISaveParticipant { + + private static ScannerInfoSaveParticipant instance; + private Set toBeSaved = new HashSet<>(); + + public ScannerInfoSaveParticipant() { + assert instance == null; + instance = this; + } + + public static ScannerInfoSaveParticipant getInstance() { + return instance; + } + + public void save(ScannerInfoData info) { + toBeSaved.add(info); + } + + @Override + public void doneSaving(ISaveContext context) { + } + + @Override + public void prepareToSave(ISaveContext context) throws CoreException { + } + + @Override + public void rollback(ISaveContext context) { + // TODO Auto-generated method stub + + } + + @Override + public void saving(ISaveContext context) throws CoreException { + for (ScannerInfoData info : toBeSaved) { + info.save(); + } + toBeSaved.clear(); + } + +} diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/build/ToolChainScannerInfo.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/build/ToolChainScannerInfo.java new file mode 100644 index 00000000000..34ed440785f --- /dev/null +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/build/ToolChainScannerInfo.java @@ -0,0 +1,56 @@ +package org.eclipse.cdt.internal.core.build; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.cdt.core.parser.ExtendedScannerInfo; +import org.eclipse.cdt.core.parser.IScannerInfo; +import org.eclipse.core.resources.IResource; + +public class ToolChainScannerInfo { + private Map definedSymbols; + private List includePaths; + private List macroFiles; + private List includeFiles; + private List localIncludePath; + private Set resourcePaths; + + private transient IScannerInfo scannerInfo; + + public ToolChainScannerInfo(Map definedSymbols, List includePaths, + List macroFiles, List includeFiles, List localIncludePath) { + this.definedSymbols = definedSymbols; + this.includePaths = includePaths; + this.macroFiles = macroFiles; + this.includeFiles = includeFiles; + this.localIncludePath = localIncludePath; + } + + public IScannerInfo getScannerInfo() { + if (scannerInfo == null) { + scannerInfo = new ExtendedScannerInfo(definedSymbols, + includePaths != null ? includePaths.toArray(new String[includePaths.size()]) : null, + macroFiles != null ? macroFiles.toArray(new String[includePaths.size()]) : null, + includeFiles != null ? includeFiles.toArray(new String[includePaths.size()]) : null, + localIncludePath != null ? localIncludePath.toArray(new String[includePaths.size()]) + : null); + } + return scannerInfo; + } + + public Collection getResourcePaths() { + return resourcePaths != null ? resourcePaths : Collections. emptySet(); + } + + public void addResource(IResource resource) { + if (resourcePaths == null) { + resourcePaths = new HashSet<>(); + } + resourcePaths.add(resource.getFullPath().toString()); + } + +} diff --git a/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF b/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF index 9b97619ec8b..0c0eda18f02 100644 --- a/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF +++ b/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.cdt.ui; singleton:=true -Bundle-Version: 5.11.0.qualifier +Bundle-Version: 5.12.0.qualifier Bundle-Activator: org.eclipse.cdt.ui.CUIPlugin Bundle-Vendor: %providerName Bundle-Localization: plugin @@ -126,3 +126,4 @@ Require-Bundle: org.eclipse.cdt.core;bundle-version="[5.2.0,6.0.0)", org.eclipse.e4.ui.css.swt.theme Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: JavaSE-1.7 +Service-Component: OSGI-INF/consoleservice.xml diff --git a/core/org.eclipse.cdt.ui/OSGI-INF/consoleservice.xml b/core/org.eclipse.cdt.ui/OSGI-INF/consoleservice.xml new file mode 100644 index 00000000000..bedd5d36824 --- /dev/null +++ b/core/org.eclipse.cdt.ui/OSGI-INF/consoleservice.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/core/org.eclipse.cdt.ui/pom.xml b/core/org.eclipse.cdt.ui/pom.xml index fb7a8ba58e1..3ed7481ec3e 100644 --- a/core/org.eclipse.cdt.ui/pom.xml +++ b/core/org.eclipse.cdt.ui/pom.xml @@ -11,7 +11,7 @@ ../../pom.xml - 5.11.0-SNAPSHOT + 5.12.0-SNAPSHOT org.eclipse.cdt.ui eclipse-plugin diff --git a/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/QtConsoleService.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/build/CConsoleService.java similarity index 64% rename from qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/QtConsoleService.java rename to core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/build/CConsoleService.java index 0a5756cccbc..89e3a2aaece 100644 --- a/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/QtConsoleService.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/build/CConsoleService.java @@ -1,12 +1,13 @@ -package org.eclipse.cdt.internal.qt.ui; +package org.eclipse.cdt.internal.ui.build; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.CountDownLatch; -import org.eclipse.cdt.internal.qt.core.QtPlugin; -import org.eclipse.cdt.internal.qt.core.build.IConsoleService; +import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IResourceChangeEvent; import org.eclipse.core.resources.IResourceChangeListener; import org.eclipse.core.resources.IncrementalProjectBuilder; @@ -18,14 +19,21 @@ import org.eclipse.ui.console.MessageConsole; import org.eclipse.ui.console.MessageConsoleStream; -public class QtConsoleService implements IConsoleService, IResourceChangeListener { +import org.eclipse.cdt.core.build.CConsoleParser; +import org.eclipse.cdt.core.build.IConsoleService; +import org.eclipse.cdt.ui.CUIPlugin; + +public class CConsoleService implements IConsoleService, IResourceChangeListener { private MessageConsole console; private MessageConsoleStream out; private MessageConsoleStream err; + private IFolder buildDirectory; + List listeners = new ArrayList<>(); + private void initConsole() { - console = new MessageConsole("Qt Builds", null); + console = new MessageConsole("C/C++", null); ConsolePlugin.getDefault().getConsoleManager().addConsoles(new IConsole[] { console }); out = console.newMessageStream(); err = console.newMessageStream(); @@ -57,19 +65,39 @@ public void resourceChanged(IResourceChangeEvent event) { } @Override - public void monitor(final Process process) throws IOException { + public void monitor(final Process process, CConsoleParser[] consoleParsers, IFolder buildDirectory) + throws IOException { if (console == null) { initConsole(); } + this.buildDirectory = buildDirectory; + + // Clear the old listeners + for (CPatternMatchListener listener : listeners) { + console.removePatternMatchListener(listener); + } + listeners.clear(); + + // Add in the new ones if any + if (consoleParsers != null) { + for (CConsoleParser parser : consoleParsers) { + CPatternMatchListener listener = new CPatternMatchListener(this, parser); + listeners.add(listener); + console.addPatternMatchListener(listener); + } + } + console.activate(); final CountDownLatch latch = new CountDownLatch(2); // Output stream reader - new Thread("Qt Build Console Output") { + new Thread("C/C++ Build Console Output") { //$NON-NLS-1$ + @Override public void run() { - try (BufferedReader processOut = new BufferedReader(new InputStreamReader(process.getInputStream()))) { + try (BufferedReader processOut = new BufferedReader( + new InputStreamReader(process.getInputStream()))) { for (String line = processOut.readLine(); line != null; line = processOut.readLine()) { out.write(line); out.write('\n'); @@ -83,9 +111,11 @@ public void run() { }.start(); // Error stream reader - new Thread("Qt Build Console Error") { + new Thread("C/C++ Build Console Error") { //$NON-NLS-1$ + @Override public void run() { - try (BufferedReader processErr = new BufferedReader(new InputStreamReader(process.getErrorStream()))) { + try (BufferedReader processErr = new BufferedReader( + new InputStreamReader(process.getErrorStream()))) { for (String line = processErr.readLine(); line != null; line = processErr.readLine()) { err.write(line); out.write('\n'); @@ -102,7 +132,7 @@ public void run() { latch.await(); process.waitFor(); } catch (InterruptedException e) { - QtPlugin.log(e); + CUIPlugin.log(e); } } @@ -122,4 +152,8 @@ public void writeError(String msg) throws IOException { err.write(msg); } + public IFolder getBuildDirectory() { + return buildDirectory; + } + } diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/launch/ArduinoHyperlink.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/build/CHyperlink.java similarity index 72% rename from toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/launch/ArduinoHyperlink.java rename to core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/build/CHyperlink.java index 155f3b89c10..a29ea02d746 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/launch/ArduinoHyperlink.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/build/CHyperlink.java @@ -1,6 +1,5 @@ -package org.eclipse.cdt.arduino.ui.internal.launch; +package org.eclipse.cdt.internal.ui.build; -import org.eclipse.cdt.arduino.ui.internal.Activator; import org.eclipse.core.resources.IMarker; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.PartInitException; @@ -8,11 +7,13 @@ import org.eclipse.ui.console.IHyperlink; import org.eclipse.ui.ide.IDE; -public class ArduinoHyperlink implements IHyperlink { +import org.eclipse.cdt.ui.CUIPlugin; + +public class CHyperlink implements IHyperlink { private final IMarker marker; - public ArduinoHyperlink(IMarker marker) { + public CHyperlink(IMarker marker) { this.marker = marker; } @@ -30,7 +31,7 @@ public void linkActivated() { try { IDE.openEditor(page, marker); } catch (PartInitException e) { - Activator.log(e); + CUIPlugin.log(e); } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/build/CPatternMatchListener.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/build/CPatternMatchListener.java new file mode 100644 index 00000000000..f06099fc1c8 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/build/CPatternMatchListener.java @@ -0,0 +1,63 @@ +package org.eclipse.cdt.internal.ui.build; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.ui.console.IPatternMatchListener; +import org.eclipse.ui.console.PatternMatchEvent; +import org.eclipse.ui.console.TextConsole; + +import org.eclipse.cdt.core.build.CConsoleParser; +import org.eclipse.cdt.ui.CUIPlugin; + +public class CPatternMatchListener implements IPatternMatchListener { + + protected final CConsoleService console; + protected final CConsoleParser parser; + + protected TextConsole textConsole; + + public CPatternMatchListener(CConsoleService console, CConsoleParser parser) { + this.console = console; + this.parser = parser; + } + + @Override + public void connect(TextConsole console) { + this.textConsole = console; + } + + @Override + public void disconnect() { + } + + @Override + public void matchFound(PatternMatchEvent event) { + try { + String text = textConsole.getDocument().get(event.getOffset(), event.getLength()); + IMarker marker = parser.generateMarker(console.getBuildDirectory(), text); + if (marker != null) { + textConsole.addHyperlink(new CHyperlink(marker), + event.getOffset() + marker.getAttribute(CConsoleParser.LINK_OFFSET, 0), + marker.getAttribute(CConsoleParser.LINK_LENGTH, event.getLength())); + } + } catch (BadLocationException e) { + CUIPlugin.log(e); + } + } + + @Override + public String getPattern() { + return parser.getPattern(); + } + + @Override + public int getCompilerFlags() { + return parser.getCompilerFlags(); + } + + @Override + public String getLineQualifier() { + return parser.getLineQualifier(); + } + +} diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/IConsoleService.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/IConsoleService.java deleted file mode 100644 index bac8e25d50b..00000000000 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/IConsoleService.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.eclipse.cdt.internal.qt.core.build; - -import java.io.IOException; - -public interface IConsoleService { - - // TODO add error parsers - void monitor(Process process) throws IOException; - - void writeOutput(String msg) throws IOException; - - void writeError(String msg) throws IOException; - -} diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtBuilder.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtBuilder.java index 83c0d5b8042..06ef2941907 100644 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtBuilder.java +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtBuilder.java @@ -4,6 +4,7 @@ import java.io.IOException; import java.util.Map; +import org.eclipse.cdt.core.build.IConsoleService; import org.eclipse.cdt.internal.qt.core.QtPlugin; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; @@ -43,12 +44,12 @@ protected IProject[] build(int kind, Map args, IProgressMonitor } msg.append('\n'); console.writeOutput(msg.toString()); - console.monitor(process); + console.monitor(process, null, buildFolder); } // run make Process process = new ProcessBuilder("make").directory(new File(buildFolder.getLocationURI())).start(); //$NON-NLS-1$ - console.monitor(process); + console.monitor(process, null, buildFolder); buildFolder.refreshLocal(IResource.DEPTH_INFINITE, monitor); return new IProject[] { project }; diff --git a/qt/org.eclipse.cdt.qt.ui/META-INF/MANIFEST.MF b/qt/org.eclipse.cdt.qt.ui/META-INF/MANIFEST.MF index f2a8ef978f0..71c77dfb49b 100644 --- a/qt/org.eclipse.cdt.qt.ui/META-INF/MANIFEST.MF +++ b/qt/org.eclipse.cdt.qt.ui/META-INF/MANIFEST.MF @@ -20,4 +20,3 @@ Require-Bundle: org.eclipse.core.runtime, Bundle-RequiredExecutionEnvironment: JavaSE-1.7 Bundle-ActivationPolicy: lazy Export-Package: org.eclipse.cdt.internal.qt.ui.assist;x-friends:="org.eclipse.cdt.qt.tests" -Service-Component: OSGI-INF/consoleservice.xml diff --git a/qt/org.eclipse.cdt.qt.ui/OSGI-INF/consoleservice.xml b/qt/org.eclipse.cdt.qt.ui/OSGI-INF/consoleservice.xml deleted file mode 100644 index 06dbdbbc437..00000000000 --- a/qt/org.eclipse.cdt.qt.ui/OSGI-INF/consoleservice.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/QtUIPlugin.java b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/QtUIPlugin.java index 62edffb37a8..8e2daf6091a 100644 --- a/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/QtUIPlugin.java +++ b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/QtUIPlugin.java @@ -44,9 +44,6 @@ public static Image getQtLogoLarge() { public void start(BundleContext context) throws Exception { super.start(context); plugin = this; - - // context.registerService(IConsoleService.class, new - // QtConsoleService(), null); } @Override diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/META-INF/MANIFEST.MF b/toolchains/arduino/org.eclipse.cdt.arduino.core/META-INF/MANIFEST.MF index 6231695e45f..454e80cf257 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/META-INF/MANIFEST.MF +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/META-INF/MANIFEST.MF @@ -22,6 +22,5 @@ Bundle-ClassPath: libs/freemarker-2.3.22.jar, Export-Package: org.eclipse.cdt.arduino.core.internal;x-friends:="org.eclipse.cdt.arduino.ui", org.eclipse.cdt.arduino.core.internal.board;x-friends:="org.eclipse.cdt.arduino.ui", org.eclipse.cdt.arduino.core.internal.build;x-friends:="org.eclipse.cdt.arduino.ui", - org.eclipse.cdt.arduino.core.internal.console;x-friends:="org.eclipse.cdt.arduino.ui", org.eclipse.cdt.arduino.core.internal.remote;x-friends:="org.eclipse.cdt.arduino.ui" Bundle-Localization: plugin diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/build.properties b/toolchains/arduino/org.eclipse.cdt.arduino.core/build.properties index a20aa47b2f0..73094ad4b81 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/build.properties +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/build.properties @@ -4,6 +4,5 @@ bin.includes = META-INF/,\ plugin.xml,\ templates/,\ about.html,\ - schema/,\ plugin.properties,\ libs/ diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/plugin.xml b/toolchains/arduino/org.eclipse.cdt.arduino.core/plugin.xml index 676505ab53b..170aa8240e1 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/plugin.xml +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/plugin.xml @@ -1,7 +1,6 @@ - T getService(Class service) { return ref != null ? context.getService(ref) : null; } - public static ArduinoConsoleService getConsoleService() throws CoreException { - IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(Activator.getId(), "consoleService"); //$NON-NLS-1$ - IExtension extension = point.getExtensions()[0]; // should only be one - return (ArduinoConsoleService) extension.getConfigurationElements()[0].createExecutableExtension("class"); //$NON-NLS-1$ - } - } diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoManager.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoManager.java index d712bc4d463..ca6c26cc1fa 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoManager.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoManager.java @@ -195,7 +195,7 @@ protected IStatus run(IProgressMonitor monitor) { try { for (IBuildConfiguration config : project.getBuildConfigs()) { ArduinoBuildConfiguration arduinoConfig = config.getAdapter(ArduinoBuildConfiguration.class); - arduinoConfig.clearScannerInfoCache(); + arduinoConfig.clearScannerInfo(); } } catch (CoreException e) { mstatus.add(e.getStatus()); diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoBuildConfiguration.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoBuildConfiguration.java index bda0b06460f..fa7495fb067 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoBuildConfiguration.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoBuildConfiguration.java @@ -1,11 +1,7 @@ package org.eclipse.cdt.arduino.core.internal.build; -import java.io.BufferedReader; import java.io.File; import java.io.FilenameFilter; -import java.io.IOException; -import java.io.InputStreamReader; -import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; @@ -15,8 +11,6 @@ import java.util.Map; import java.util.Properties; import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import org.eclipse.cdt.arduino.core.internal.Activator; import org.eclipse.cdt.arduino.core.internal.ArduinoPreferences; @@ -28,26 +22,24 @@ import org.eclipse.cdt.arduino.core.internal.board.ArduinoPlatform; import org.eclipse.cdt.arduino.core.internal.board.ArduinoTool; import org.eclipse.cdt.arduino.core.internal.board.ToolDependency; -import org.eclipse.cdt.arduino.core.internal.console.ArduinoConsoleParser; -import org.eclipse.cdt.arduino.core.internal.console.ArduinoErrorParser; import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.build.CBuildConfiguration; +import org.eclipse.cdt.core.build.CToolChain; +import org.eclipse.cdt.core.build.GCCToolChain; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.core.model.IOutputEntry; import org.eclipse.cdt.core.model.IPathEntry; import org.eclipse.cdt.core.model.ISourceRoot; -import org.eclipse.cdt.core.parser.ExtendedScannerInfo; import org.eclipse.cdt.core.parser.IScannerInfo; import org.eclipse.core.resources.IBuildConfiguration; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; -import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceProxy; import org.eclipse.core.resources.IResourceProxyVisitor; -import org.eclipse.core.resources.ProjectScope; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdapterFactory; import org.eclipse.core.runtime.IProgressMonitor; @@ -57,25 +49,29 @@ import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.osgi.service.prefs.BackingStoreException; -public class ArduinoBuildConfiguration { +public class ArduinoBuildConfiguration extends CBuildConfiguration { private static final String PACKAGE_NAME = "packageName"; //$NON-NLS-1$ private static final String PLATFORM_NAME = "platformName"; //$NON-NLS-1$ private static final String BOARD_NAME = "boardName"; //$NON-NLS-1$ - private final IBuildConfiguration config; - private ArduinoBoard board; private Properties properties; - // Cache for scanner info - private IScannerInfo cScannerInfo; - private IScannerInfo cppScannerInfo; - private final static boolean isWindows = Platform.getOS().equals(Platform.OS_WIN32); private ArduinoBuildConfiguration(IBuildConfiguration config) { - this.config = config; + super(config); + + try { + if (getToolChain() == null) { + // For now, assume GCC is the toolchain, + // not sure it's ever not. + setToolChain(GCCToolChain.ID); + } + } catch (CoreException e) { + Activator.log(e); + } } private static Map cache = new HashMap<>(); @@ -135,23 +131,6 @@ public static ArduinoBuildConfiguration getConfig(IProject project, ArduinoBoard return arduinoConfig; } - public void setActive(IProgressMonitor monitor) throws CoreException { - IProject project = config.getProject(); - if (config.equals(project.getActiveBuildConfig())) { - // already set - return; - } - - IProjectDescription projectDesc = project.getDescription(); - projectDesc.setActiveBuildConfig(config.getName()); - project.setDescription(projectDesc, monitor); - } - - public IEclipsePreferences getSettings() { - return (IEclipsePreferences) new ProjectScope(config.getProject()).getNode(Activator.getId()).node("config") //$NON-NLS-1$ - .node(config.getName()); - } - public void setBoard(ArduinoBoard board) throws CoreException { this.board = board; @@ -165,7 +144,7 @@ public void setBoard(ArduinoBoard board) throws CoreException { try { settings.flush(); } catch (BackingStoreException e) { - throw new CoreException(new Status(IStatus.ERROR, Activator.getId(), "Saving preferences", e)); + throw new CoreException(new Status(IStatus.ERROR, Activator.getId(), "Saving preferences", e)); //$NON-NLS-1$ } } @@ -191,15 +170,15 @@ private Properties getProperties() throws CoreException { } properties.put("runtime.ide.version", "10607"); //$NON-NLS-1$ //$NON-NLS-2$ properties.put("build.arch", platform.getArchitecture().toUpperCase()); //$NON-NLS-1$ - properties.put("build.path", config.getName()); //$NON-NLS-1$ + properties.put("build.path", getName()); //$NON-NLS-1$ } // always do this in case the project changes names - properties.put("build.project_name", config.getProject().getName()); //$NON-NLS-1$ + properties.put("build.project_name", getProject().getName()); //$NON-NLS-1$ return properties; } public IFolder getBuildFolder() throws CoreException { - IProject project = config.getProject(); + IProject project = getProject(); return project.getFolder("build"); //$NON-NLS-1$ } @@ -215,7 +194,7 @@ public IFile getMakeFile() throws CoreException { } public IFile generateMakeFile(IProgressMonitor monitor) throws CoreException { - final IProject project = config.getProject(); + final IProject project = getProject(); IFolder buildFolder = getBuildFolder(); if (!buildFolder.exists()) { @@ -368,7 +347,7 @@ public void setEnvironment(Map env) throws CoreException { List toolPaths = new ArrayList<>(); if (isWindows) { // Add in the tools/make directory to pick up make - toolPaths.add(ArduinoPreferences.getArduinoHome().resolve("tools/make")); + toolPaths.add(ArduinoPreferences.getArduinoHome().resolve("tools/make")); //$NON-NLS-1$ } ArduinoBoard board = getBoard(); ArduinoPlatform platform = board.getPlatform(); @@ -444,57 +423,40 @@ public String[] getUploadCommand(String serialPort) throws CoreException { String command = resolveProperty("tools." + toolName + ".upload.pattern", properties); //$NON-NLS-1$ //$NON-NLS-2$ if (isWindows) { - return splitCommand(command); + return CToolChain.splitCommand(command); } else { return new String[] { "sh", "-c", command }; //$NON-NLS-1$ //$NON-NLS-2$ } } public IScannerInfo getScannerInfo(IResource resource) throws CoreException { - // what language is this resource and pick the right path; - switch (CCorePlugin.getContentType(resource.getProject(), resource.getName()).getId()) { - case CCorePlugin.CONTENT_TYPE_CXXSOURCE: - case CCorePlugin.CONTENT_TYPE_CXXHEADER: - if (cppScannerInfo == null) { - cppScannerInfo = calculateScannerInfo("recipe.cpp.o.pattern", resource); //$NON-NLS-1$ - } - return cppScannerInfo; - default: - if (cScannerInfo == null) { - cScannerInfo = calculateScannerInfo("recipe.c.o.pattern", resource); //$NON-NLS-1$ + IScannerInfo info = super.getScannerInfo(resource); + if (info == null) { + // what language is this resource and pick the right recipe + String recipe; + switch (CCorePlugin.getContentType(resource.getProject(), resource.getName()).getId()) { + case CCorePlugin.CONTENT_TYPE_CXXSOURCE: + case CCorePlugin.CONTENT_TYPE_CXXHEADER: + recipe = "recipe.cpp.o.pattern"; //$NON-NLS-1$ + break; + default: + recipe = "recipe.c.o.pattern"; //$NON-NLS-1$ } - return cScannerInfo; - } - } - - public void clearScannerInfoCache() { - cppScannerInfo = null; - cScannerInfo = null; - } - public static String pathString(Path path) { - String str = path.toString(); - if (isWindows) { - str = str.replaceAll("\\\\", "/"); - } - return str; - } - - private IScannerInfo calculateScannerInfo(String recipe, IResource resource) throws CoreException { - try { ArduinoPlatform platform = getBoard().getPlatform(); Properties properties = new Properties(); properties.putAll(getProperties()); - Path tmpFile = Files.createTempFile("cdt", ".cpp"); //$NON-NLS-1$ //$NON-NLS-2$ - properties.put("source_file", pathString(tmpFile)); //$NON-NLS-1$ + Path resourcePath = new File(resource.getLocationURI()).toPath(); + Path sourcePath = getBuildDirectory().toPath().relativize(resourcePath); + properties.put("source_file", pathString(sourcePath)); //$NON-NLS-1$ properties.put("object_file", "-"); //$NON-NLS-1$ //$NON-NLS-2$ - String includes = "-E -P -v -dD"; //$NON-NLS-1$ + String includes = ""; //$NON-NLS-1$ for (Path include : platform.getIncludePath()) { includes += " -I\"" + pathString(include) + '"'; //$NON-NLS-1$ } - Collection libs = ArduinoManager.instance.getLibraries(config.getProject()); + Collection libs = ArduinoManager.instance.getLibraries(getProject()); for (ArduinoLibrary lib : libs) { for (Path path : lib.getIncludePath()) { includes += " -I\"" + pathString(path) + '"'; //$NON-NLS-1$ @@ -502,87 +464,18 @@ private IScannerInfo calculateScannerInfo(String recipe, IResource resource) thr } properties.put("includes", includes); //$NON-NLS-1$ - String[] command; - if (isWindows) { - command = splitCommand(resolveProperty(recipe, properties)); - } else { - command = new String[] { "sh", "-c", resolveProperty(recipe, properties) }; //$NON-NLS-1$ //$NON-NLS-2$ - } - ProcessBuilder processBuilder = new ProcessBuilder(command).directory(tmpFile.getParent().toFile()) - .redirectErrorStream(true); - setEnvironment(processBuilder.environment()); - Process process = processBuilder.start(); - - Map symbols = new HashMap<>(); - List includePath = new ArrayList<>(); - Pattern definePattern = Pattern.compile("#define (.*)\\s(.*)"); //$NON-NLS-1$ - boolean inIncludePaths = false; - try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { - for (String line = reader.readLine(); line != null; line = reader.readLine()) { - if (inIncludePaths) { - if (line.equals("End of search list.")) { //$NON-NLS-1$ - inIncludePaths = false; - } else { - includePath.add(line.trim()); - } - } else if (line.startsWith("#define ")) { //$NON-NLS-1$ - Matcher matcher = definePattern.matcher(line); - if (matcher.matches()) { - symbols.put(matcher.group(1), matcher.group(2)); - } - } else if (line.equals("#include <...> search starts here:")) { //$NON-NLS-1$ - inIncludePaths = true; - } - } - } - Files.delete(tmpFile); - ExtendedScannerInfo scannerInfo = new ExtendedScannerInfo(symbols, - includePath.toArray(new String[includePath.size()])); - return scannerInfo; - } catch (IOException e) { - throw new CoreException(new Status(IStatus.ERROR, Activator.getId(), "Compiler built-ins", e)); + getToolChain().scanBuildOutput(getBuildFolder(), resolveProperty(recipe, properties), true); + info = super.getScannerInfo(resource); } + return info; } - private String[] splitCommand(String command) { - // TODO deal with quotes properly, for now just strip - return command.replaceAll("\"", "").split("\\s+"); - } - - public ArduinoConsoleParser[] getBuildConsoleParsers() { - // ../src/Test.cpp:4:1: error: 'x' was not declared in this scope - - return new ArduinoConsoleParser[] { new ArduinoErrorParser("(.*?):(\\d+):(\\d+:)? (fatal )?error: (.*)") { //$NON-NLS-1$ - @Override - protected int getSeverity(Matcher matcher) { - return IMarker.SEVERITY_ERROR; - } - - @Override - protected String getMessage(Matcher matcher) { - return matcher.group(5); - } - - @Override - protected int getLineNumber(Matcher matcher) { - return Integer.parseInt(matcher.group(2)); - } - - @Override - protected String getFileName(Matcher matcher) { - return matcher.group(1); - } - - @Override - protected int getLinkOffset(Matcher matcher) { - return 0; - } - - @Override - protected int getLinkLength(Matcher matcher) { - return matcher.group(1).length() + 1 + matcher.group(2).length() + 1 + matcher.group(3).length(); - } - } }; + public static String pathString(Path path) { + String str = path.toString(); + if (isWindows) { + str = str.replaceAll("\\\\", "/"); //$NON-NLS-1$ //$NON-NLS-2$ + } + return str; } } diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoBuilder.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoBuilder.java index a4f55b5dc0a..0275c0c4a26 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoBuilder.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoBuilder.java @@ -15,7 +15,7 @@ import java.util.regex.Pattern; import org.eclipse.cdt.arduino.core.internal.Activator; -import org.eclipse.cdt.arduino.core.internal.console.ArduinoConsoleService; +import org.eclipse.cdt.core.build.IConsoleService; import org.eclipse.cdt.core.model.ICModelMarker; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; @@ -39,8 +39,8 @@ protected IProject[] build(int kind, Map args, IProgressMonitor try { project.deleteMarkers(ICModelMarker.C_MODEL_PROBLEM_MARKER, true, IResource.DEPTH_INFINITE); - ArduinoConsoleService consoleService = Activator.getConsoleService(); - consoleService.writeOutput(String.format("\nBuilding %s\n", project.getName())); + IConsoleService consoleService = Activator.getService(IConsoleService.class); + consoleService.writeOutput(String.format("Building %s\n", project.getName())); ArduinoBuildConfiguration config = getBuildConfig().getAdapter(ArduinoBuildConfiguration.class); config.generateMakeFile(monitor); @@ -50,15 +50,16 @@ protected IProject[] build(int kind, Map args, IProgressMonitor config.setEnvironment(processBuilder.environment()); Process process = processBuilder.start(); - consoleService.monitor(process, config.getBuildConsoleParsers(), config.getBuildFolder()); + consoleService.monitor(process, config.getConsoleParsers(), config.getBuildFolder()); if (process.exitValue() == 0) { showSizes(config, consoleService); } config.getBuildFolder().refreshLocal(IResource.DEPTH_INFINITE, monitor); + consoleService.writeOutput("\n"); //$NON-NLS-1$ } catch (IOException e) { - throw new CoreException(new Status(IStatus.ERROR, Activator.getId(), "Build error", e)); + throw new CoreException(new Status(IStatus.ERROR, Activator.getId(), "Build error", e)); //$NON-NLS-1$ } // TODO if there are references we want to watch, return them here @@ -71,8 +72,8 @@ protected void clean(IProgressMonitor monitor) throws CoreException { IProject project = getProject(); project.deleteMarkers(ICModelMarker.C_MODEL_PROBLEM_MARKER, true, IResource.DEPTH_INFINITE); - ArduinoConsoleService consoleService = Activator.getConsoleService(); - consoleService.writeOutput(String.format("\nCleaning %s\n", project.getName())); + IConsoleService consoleService = Activator.getService(IConsoleService.class); + consoleService.writeOutput(String.format("Cleaning %s\n", project.getName())); ArduinoBuildConfiguration config = getBuildConfig().getAdapter(ArduinoBuildConfiguration.class); @@ -81,15 +82,16 @@ protected void clean(IProgressMonitor monitor) throws CoreException { config.setEnvironment(processBuilder.environment()); Process process = processBuilder.start(); - consoleService.monitor(process, config.getBuildConsoleParsers(), config.getBuildFolder()); + consoleService.monitor(process, config.getConsoleParsers(), config.getBuildFolder()); config.getBuildFolder().refreshLocal(IResource.DEPTH_INFINITE, monitor); + consoleService.writeOutput("\n"); //$NON-NLS-1$ } catch (IOException e) { - throw new CoreException(new Status(IStatus.ERROR, Activator.getId(), "Build error", e)); + throw new CoreException(new Status(IStatus.ERROR, Activator.getId(), "Build error", e)); //$NON-NLS-1$ } } - private void showSizes(ArduinoBuildConfiguration config, ArduinoConsoleService console) throws CoreException { + private void showSizes(ArduinoBuildConfiguration config, IConsoleService console) throws CoreException { try { int codeSize = -1; int dataSize = -1; diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/console/ArduinoConsoleParser.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/console/ArduinoConsoleParser.java deleted file mode 100644 index 62329eb68c5..00000000000 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/console/ArduinoConsoleParser.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.eclipse.cdt.arduino.core.internal.console; - -public abstract class ArduinoConsoleParser { - - private final String pattern; - private final int flags; - private final String lineQualifier; - - protected ArduinoConsoleParser(String pattern, int flags, String lineQualifier) { - this.pattern = pattern; - this.flags = flags; - this.lineQualifier = lineQualifier; - } - - /** - * Returns the pattern to be used for matching. The pattern is a string - * representing a regular expression. - * - * @return the regular expression to be used for matching - */ - public String getPattern() { - return pattern; - } - - /** - * Returns the flags to use when compiling this pattern match listener's - * regular expression, as defined by by - * Pattern.compile(String regex, int flags) - * - * @return the flags to use when compiling this pattern match listener's - * regular expression - * @see java.util.regex.Pattern#compile(java.lang.String, int) - */ - public int getCompilerFlags() { - return flags; - } - - /** - * Returns a simple regular expression used to identify lines that may match - * this pattern matcher's complete pattern, or null. Use of - * this attribute can improve performance by disqualifying lines from the - * search. When a line is found containing a match for this expression, the - * line is searched from the beginning for this pattern matcher's complete - * pattern. Lines not containing this pattern are discarded. - * - * @return a simple regular expression used to identify lines that may match - * this pattern matcher's complete pattern, or null - */ - public String getLineQualifier() { - return lineQualifier; - } - -} diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/console/ArduinoConsoleService.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/console/ArduinoConsoleService.java deleted file mode 100644 index 5ac7dba8731..00000000000 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/console/ArduinoConsoleService.java +++ /dev/null @@ -1,25 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 QNX Software Systems 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: - * QNX Software Systems - Initial API and implementation - *******************************************************************************/ -package org.eclipse.cdt.arduino.core.internal.console; - -import java.io.IOException; - -import org.eclipse.core.resources.IFolder; - -public interface ArduinoConsoleService { - - void monitor(Process process, ArduinoConsoleParser[] consoleParsers, IFolder buildDirectory) throws IOException; - - void writeOutput(String msg) throws IOException; - - void writeError(String msg) throws IOException; - -} diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/console/ArduinoErrorParser.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/console/ArduinoErrorParser.java deleted file mode 100644 index 96031b72aef..00000000000 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/console/ArduinoErrorParser.java +++ /dev/null @@ -1,67 +0,0 @@ -package org.eclipse.cdt.arduino.core.internal.console; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.eclipse.cdt.arduino.core.internal.Activator; -import org.eclipse.cdt.core.model.ICModelMarker; -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IFolder; -import org.eclipse.core.resources.IMarker; -import org.eclipse.core.runtime.CoreException; - -public abstract class ArduinoErrorParser extends ArduinoConsoleParser { - - public static final String LINK_OFFSET = "arduino.link.offset"; //$NON-NLS-1$ - public static final String LINK_LENGTH = "arduino.link.length"; //$NON-NLS-1$ - - private final Pattern errorPattern; - - public ArduinoErrorParser(String pattern, int flags, String lineQualifier) { - super(pattern, flags, lineQualifier); - this.errorPattern = Pattern.compile(pattern); - } - - public ArduinoErrorParser(String pattern) { - this(pattern, 0, null); - } - - protected abstract String getFileName(Matcher matcher); - - protected abstract int getLineNumber(Matcher matcher); - - protected abstract String getMessage(Matcher matcher); - - protected abstract int getSeverity(Matcher matcher); - - protected abstract int getLinkOffset(Matcher matcher); - - protected abstract int getLinkLength(Matcher matcher); - - public IMarker generateMarker(IFolder buildDirectory, String text) { - Matcher matcher = errorPattern.matcher(text); - if (matcher.matches()) { - String fileName = getFileName(matcher); - - IFile file = buildDirectory.getFile(fileName); - if (file.exists()) { - try { - IMarker marker = file.createMarker(ICModelMarker.C_MODEL_PROBLEM_MARKER); - marker.setAttribute(IMarker.MESSAGE, getMessage(matcher)); - marker.setAttribute(IMarker.SEVERITY, getSeverity(matcher)); - marker.setAttribute(IMarker.LINE_NUMBER, getLineNumber(matcher)); - marker.setAttribute(IMarker.CHAR_START, -1); - marker.setAttribute(IMarker.CHAR_END, -1); - marker.setAttribute(LINK_OFFSET, getLinkOffset(matcher)); - marker.setAttribute(LINK_LENGTH, getLinkLength(matcher)); - return marker; - } catch (CoreException e) { - Activator.log(e); - return null; - } - } - } - return null; - } - -} diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/launch/ArduinoLaunchConfigurationDelegate.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/launch/ArduinoLaunchConfigurationDelegate.java index 0b02d6f995c..e6dc733cd0b 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/launch/ArduinoLaunchConfigurationDelegate.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/launch/ArduinoLaunchConfigurationDelegate.java @@ -16,8 +16,8 @@ import org.eclipse.cdt.arduino.core.internal.Messages; import org.eclipse.cdt.arduino.core.internal.board.ArduinoBoard; import org.eclipse.cdt.arduino.core.internal.build.ArduinoBuildConfiguration; -import org.eclipse.cdt.arduino.core.internal.console.ArduinoConsoleService; import org.eclipse.cdt.arduino.core.internal.remote.ArduinoRemoteConnection; +import org.eclipse.cdt.core.build.IConsoleService; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; @@ -76,7 +76,7 @@ public void launch(final ILaunchConfiguration configuration, String mode, final new Job(Messages.ArduinoLaunchConfigurationDelegate_0) { protected IStatus run(IProgressMonitor monitor) { try { - ArduinoConsoleService consoleService = Activator.getConsoleService(); + IConsoleService consoleService = Activator.getService(IConsoleService.class); IRemoteConnection target = getTarget(configuration); if (target == null) { return new Status(IStatus.ERROR, Activator.getId(), diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.ui/plugin.xml b/toolchains/arduino/org.eclipse.cdt.arduino.ui/plugin.xml index 7971aae6958..a453e907a50 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.ui/plugin.xml +++ b/toolchains/arduino/org.eclipse.cdt.arduino.ui/plugin.xml @@ -30,12 +30,6 @@ project="true"> - - - - listeners = new ArrayList<>(); - - public ArduinoConsole() { - if (console == null) { - console = new MessageConsole(Messages.ArduinoLaunchConsole_0, null); - ConsolePlugin.getDefault().getConsoleManager().addConsoles(new IConsole[] { console }); - out = console.newMessageStream(); - err = console.newMessageStream(); - - // set the colors - final Display display = Display.getDefault(); - display.syncExec(new Runnable() { - @Override - public void run() { - out.setColor(display.getSystemColor(SWT.COLOR_BLACK)); - err.setColor(display.getSystemColor(SWT.COLOR_RED)); - } - }); - ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.PRE_BUILD); - } - } - - @Override - public void resourceChanged(IResourceChangeEvent event) { - switch (event.getType()) { - case IResourceChangeEvent.PRE_BUILD: - if (event.getBuildKind() != IncrementalProjectBuilder.AUTO_BUILD) { - // TODO this really should be done from the core and only when - // our projects are being built - console.clearConsole(); - } - break; - } - } - - public IFolder getBuildDirectory() { - return buildDirectory; - } - - @Override - public void monitor(final Process process, ArduinoConsoleParser[] consoleParsers, IFolder buildDirectory) - throws IOException { - this.buildDirectory = buildDirectory; - - // Clear the old listeners - for (ArduinoPatternMatchListener listener : listeners) { - console.removePatternMatchListener(listener); - } - listeners.clear(); - - // Add in the new ones if any - if (consoleParsers != null) { - for (ArduinoConsoleParser parser : consoleParsers) { - ArduinoPatternMatchListener listener; - if (parser instanceof ArduinoErrorParser) { - listener = new ArduinoErrorMatchListener(this, (ArduinoErrorParser) parser); - } else { - continue; - } - listeners.add(listener); - console.addPatternMatchListener(listener); - } - } - - console.activate(); - - final Semaphore sema = new Semaphore(-1); - - // Output stream reader - new Thread(Messages.ArduinoLaunchConsole_2) { - public void run() { - try (BufferedReader processOut = new BufferedReader(new InputStreamReader(process.getInputStream()))) { - for (String line = processOut.readLine(); line != null; line = processOut.readLine()) { - out.write(line); - out.write('\n'); - } - } catch (IOException e) { - e.printStackTrace(); - } finally { - sema.release(); - } - } - }.start(); - - // Error stream reader - new Thread(Messages.ArduinoLaunchConsole_2) { - public void run() { - try (BufferedReader processErr = new BufferedReader(new InputStreamReader(process.getErrorStream()))) { - for (String line = processErr.readLine(); line != null; line = processErr.readLine()) { - err.write(line); - out.write('\n'); - } - } catch (IOException e) { - e.printStackTrace(); - } finally { - sema.release(); - } - } - }.start(); - - try { - sema.acquire(); - process.waitFor(); - } catch (InterruptedException e) { - Activator.log(e); - } - } - - @Override - public void writeOutput(String msg) throws IOException { - out.write(msg); - } - - @Override - public void writeError(String msg) throws IOException { - err.write(msg); - } - -} diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/launch/ArduinoErrorMatchListener.java b/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/launch/ArduinoErrorMatchListener.java deleted file mode 100644 index 839d16f2a78..00000000000 --- a/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/launch/ArduinoErrorMatchListener.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.eclipse.cdt.arduino.ui.internal.launch; - -import org.eclipse.cdt.arduino.core.internal.console.ArduinoErrorParser; -import org.eclipse.cdt.arduino.ui.internal.Activator; -import org.eclipse.core.resources.IMarker; -import org.eclipse.jface.text.BadLocationException; -import org.eclipse.ui.console.PatternMatchEvent; - -public class ArduinoErrorMatchListener extends ArduinoPatternMatchListener { - - public ArduinoErrorMatchListener(ArduinoConsole arduinoConsole, ArduinoErrorParser parser) { - super(arduinoConsole, parser); - } - - @Override - public void matchFound(PatternMatchEvent event) { - try { - String text = textConsole.getDocument().get(event.getOffset(), event.getLength()); - IMarker marker = ((ArduinoErrorParser) parser).generateMarker(arduinoConsole.getBuildDirectory(), text); - if (marker != null) { - textConsole.addHyperlink(new ArduinoHyperlink(marker), - event.getOffset() + marker.getAttribute(ArduinoErrorParser.LINK_OFFSET, 0), - marker.getAttribute(ArduinoErrorParser.LINK_LENGTH, event.getLength())); - } - } catch (BadLocationException e) { - Activator.log(e); - } - } - -} diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/launch/ArduinoPatternMatchListener.java b/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/launch/ArduinoPatternMatchListener.java deleted file mode 100644 index 1b6f40f854c..00000000000 --- a/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/launch/ArduinoPatternMatchListener.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.eclipse.cdt.arduino.ui.internal.launch; - -import org.eclipse.cdt.arduino.core.internal.console.ArduinoConsoleParser; -import org.eclipse.ui.console.IPatternMatchListener; -import org.eclipse.ui.console.TextConsole; - -public abstract class ArduinoPatternMatchListener implements IPatternMatchListener { - - protected final ArduinoConsole arduinoConsole; - protected final ArduinoConsoleParser parser; - - protected TextConsole textConsole; - - public ArduinoPatternMatchListener(ArduinoConsole arduinoConsole, ArduinoConsoleParser parser) { - this.arduinoConsole = arduinoConsole; - this.parser = parser; - } - - @Override - public void connect(TextConsole console) { - this.textConsole = console; - } - - @Override - public void disconnect() { - } - - @Override - public String getPattern() { - return parser.getPattern(); - } - - @Override - public int getCompilerFlags() { - return parser.getCompilerFlags(); - } - - @Override - public String getLineQualifier() { - return parser.getLineQualifier(); - } - -}