1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-22 14:12:10 +02:00

bug 371797: [sd90] Implement language settings providers in build

plugins
This commit is contained in:
Andrew Gvozdev 2012-04-12 01:01:23 -04:00
parent 1a0bdf2d5d
commit b1b320f94e
42 changed files with 6403 additions and 129 deletions

View file

@ -26,8 +26,17 @@ import org.eclipse.cdt.core.CommandLauncher;
import org.eclipse.cdt.core.ErrorParserManager;
import org.eclipse.cdt.core.ICommandLauncher;
import org.eclipse.cdt.core.IConsoleParser;
import org.eclipse.cdt.core.language.settings.providers.ICBuildOutputParser;
import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvider;
import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvidersKeeper;
import org.eclipse.cdt.core.language.settings.providers.IWorkingDirectoryTracker;
import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsManager;
import org.eclipse.cdt.core.language.settings.providers.ScannerDiscoveryLegacySupport;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.resources.ACBuilder;
import org.eclipse.cdt.core.resources.IConsole;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.internal.core.BuildRunnerHelper;
import org.eclipse.cdt.make.core.scannerconfig.IScannerInfoConsoleParser;
import org.eclipse.cdt.make.internal.core.MakeMessages;
@ -175,6 +184,7 @@ public class MakeBuilder extends ACBuilder {
String[] targets = getTargets(kind, info);
if (targets.length != 0 && targets[targets.length - 1].equals(info.getCleanBuildTarget()))
isClean = true;
boolean isOnlyClean = isClean && (targets.length == 1);
String[] args = getCommandArguments(info, targets);
@ -187,8 +197,17 @@ public class MakeBuilder extends ACBuilder {
ErrorParserManager epm = new ErrorParserManager(getProject(), workingDirectoryURI, this, errorParsers);
List<IConsoleParser> parsers = new ArrayList<IConsoleParser>();
if (!isOnlyClean) {
ICProjectDescription prjDescription = CoreModel.getDefault().getProjectDescription(project);
if (prjDescription != null) {
ICConfigurationDescription cfgDescription = prjDescription.getActiveConfiguration();
collectLanguageSettingsConsoleParsers(cfgDescription, epm, parsers);
}
if (ScannerDiscoveryLegacySupport.isLegacyScannerDiscoveryOn(project)) {
IScannerInfoConsoleParser parserSD = ScannerInfoConsoleParserFactory.getScannerInfoConsoleParser(project, workingDirectoryURI, this);
parsers.add(parserSD);
}
}
buildRunnerHelper.setLaunchParameters(launcher, buildCommand, args, workingDirectoryURI, envp);
buildRunnerHelper.prepareStreams(epm, parsers, console, new SubProgressMonitor(monitor, TICKS_STREAM_PROGRESS_MONITOR, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK));
@ -307,4 +326,26 @@ public class MakeBuilder extends ACBuilder {
private String[] makeArray(String string) {
return CommandLineUtil.argumentsToArray(string);
}
private static void collectLanguageSettingsConsoleParsers(ICConfigurationDescription cfgDescription, IWorkingDirectoryTracker cwdTracker, List<IConsoleParser> parsers) {
if (cfgDescription instanceof ILanguageSettingsProvidersKeeper) {
List<ILanguageSettingsProvider> lsProviders = ((ILanguageSettingsProvidersKeeper) cfgDescription).getLanguageSettingProviders();
for (ILanguageSettingsProvider lsProvider : lsProviders) {
ILanguageSettingsProvider rawProvider = LanguageSettingsManager.getRawProvider(lsProvider);
if (rawProvider instanceof ICBuildOutputParser) {
ICBuildOutputParser consoleParser = (ICBuildOutputParser) rawProvider;
try {
consoleParser.startup(cfgDescription, cwdTracker);
parsers.add(consoleParser);
} catch (CoreException e) {
MakeCorePlugin.log(new Status(IStatus.ERROR, MakeCorePlugin.PLUGIN_ID,
"Language Settings Provider failed to start up", e)); //$NON-NLS-1$
}
}
}
}
}
}

View file

@ -13,6 +13,8 @@ package org.eclipse.cdt.make.core.scannerconfig;
import java.util.Map;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.language.settings.providers.ScannerDiscoveryLegacySupport;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.resources.ACBuilder;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
@ -60,6 +62,11 @@ public class ScannerConfigBuilder extends ACBuilder {
// boolean autodiscoveryEnabled;
if(buildNewStyle(getProject(), monitor))
return getProject().getReferencedProjects();
if (!ScannerDiscoveryLegacySupport.isLegacyScannerDiscoveryOn(getProject())) {
return getProject().getReferencedProjects();
}
boolean autodiscoveryEnabled2;
IScannerConfigBuilderInfo2 buildInfo2 = null;
try {
@ -128,8 +135,8 @@ public class ScannerConfigBuilder extends ACBuilder {
}
protected boolean build(IProject project, InfoContext context, IScannerConfigBuilderInfo2 buildInfo2, IProgressMonitor monitor){
if (ScannerDiscoveryLegacySupport.isLegacyScannerDiscoveryOn(getProject())) {
boolean autodiscoveryEnabled2 = buildInfo2.isAutoDiscoveryEnabled();
if (autodiscoveryEnabled2) {
monitor.beginTask(MakeMessages.getString("ScannerConfigBuilder.Invoking_Builder"), 100); //$NON-NLS-1$
monitor.subTask(MakeMessages.getString("ScannerConfigBuilder.Invoking_Builder") + //$NON-NLS-1$
@ -142,6 +149,7 @@ public class ScannerConfigBuilder extends ACBuilder {
SCJobsUtil.updateScannerConfiguration(getProject(), context, buildInfo2, new SubProgressMonitor(monitor, 30));
return true;
}
}
return false;
}

View file

@ -7,6 +7,7 @@ Bundle-Activator: org.eclipse.cdt.managedbuilder.testplugin.CTestPlugin
Bundle-Vendor: Eclipse CDT
Bundle-Localization: plugin
Export-Package: org.eclipse.cdt.managedbuilder.core.tests,
org.eclipse.cdt.managedbuilder.language.settings.providers.tests,
org.eclipse.cdt.managedbuilder.templateengine.tests,
org.eclipse.cdt.managedbuilder.testplugin,
org.eclipse.cdt.managedbuilder.tests.suite,

View file

@ -9301,4 +9301,14 @@
</matchObject>
</conflictDefinition>
</extension>
<extension
id="org.eclipse.cdt.managedbuilder.core.tests.ErrorParsers"
name="org.eclipse.cdt.managedbuilder.core.tests ErrorParsers"
point="org.eclipse.cdt.core.ErrorParser">
<errorparser
class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuildCommandParser$GCCBuildCommandPatternHighlighter"
id="org.eclipse.cdt.core.tests.managedbuilder.core.GCCBuildCommandPatternHighlighter"
name="Test Plugin GCC BOP Patterns Highlighter">
</errorparser>
</extension>
</plugin>

View file

@ -39,6 +39,7 @@ import org.eclipse.cdt.managedbuilder.core.tests.OptionCategoryEnablementTests;
import org.eclipse.cdt.managedbuilder.core.tests.OptionEnablementTests;
import org.eclipse.cdt.managedbuilder.core.tests.PathConverterTest;
import org.eclipse.cdt.managedbuilder.core.tests.ResourceBuildCoreTests;
import org.eclipse.cdt.managedbuilder.language.settings.providers.tests.AllLanguageSettingsProvidersMBSTests;
import org.eclipse.cdt.managedbuilder.templateengine.tests.AllTemplateEngineTests;
import org.eclipse.cdt.projectmodel.tests.BackwardCompatiblityTests;
import org.eclipse.cdt.projectmodel.tests.CProjectDescriptionSerializationTests;
@ -61,6 +62,9 @@ public class AllManagedBuildTests {
suite.addTest(CfgScannerConfigProfileManagerTests.suite());
suite.addTestSuite(GCCSpecsConsoleParserTest.class);
// language settings providers tests
suite.addTest(AllLanguageSettingsProvidersMBSTests.suite());
// managedbuilder.core.tests
suite.addTest(ManagedBuildDependencyLibsTests.suite());
suite.addTest(ManagedBuildCoreTests20.suite());

View file

@ -0,0 +1,32 @@
/*******************************************************************************
* Copyright (c) 2010, 2012 Andrew Gvozdev 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:
* Andrew Gvozdev - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.managedbuilder.language.settings.providers.tests;
import junit.framework.TestSuite;
/**
* Test suite to test language settings providers defined in cdt.managedbuilder.core.
*/
public class AllLanguageSettingsProvidersMBSTests extends TestSuite {
public static TestSuite suite() {
return new AllLanguageSettingsProvidersMBSTests();
}
public AllLanguageSettingsProvidersMBSTests() {
super(AllLanguageSettingsProvidersMBSTests.class.getName());
addTestSuite(GCCBuildCommandParserTest.class);
addTestSuite(BuiltinSpecsDetectorTest.class);
addTestSuite(GCCBuiltinSpecsDetectorTest.class);
}
}

View file

@ -0,0 +1,569 @@
/*******************************************************************************
* Copyright (c) 2010, 2012 Andrew Gvozdev 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:
* Andrew Gvozdev - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.managedbuilder.language.settings.providers.tests;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.cdt.core.ICommandLauncher;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.settings.model.CIncludeFileEntry;
import org.eclipse.cdt.core.settings.model.CIncludePathEntry;
import org.eclipse.cdt.core.settings.model.CLibraryFileEntry;
import org.eclipse.cdt.core.settings.model.CLibraryPathEntry;
import org.eclipse.cdt.core.settings.model.CMacroEntry;
import org.eclipse.cdt.core.settings.model.CMacroFileEntry;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescriptionManager;
import org.eclipse.cdt.core.settings.model.ICSettingEntry;
import org.eclipse.cdt.core.testplugin.ResourceHelper;
import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
import org.eclipse.cdt.internal.core.XmlUtil;
import org.eclipse.cdt.managedbuilder.language.settings.providers.AbstractBuiltinSpecsDetector;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.jobs.Job;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
/**
* Test cases to test built-in specs detectors.
*/
public class BuiltinSpecsDetectorTest extends BaseTestCase {
private static final String PROVIDER_ID = "provider.id";
private static final String PROVIDER_NAME = "provider name";
private static final String LANGUAGE_ID = "language.test.id";
private static final String CUSTOM_PARAMETER = "customParameter";
private static final String CUSTOM_PARAMETER_2 = "customParameter2";
private static final String ELEM_TEST = "test";
// those attributes must match that in AbstractBuiltinSpecsDetector
private static final String ATTR_PARAMETER = "parameter"; //$NON-NLS-1$
private static final String ATTR_CONSOLE = "console"; //$NON-NLS-1$
/**
* Mock built-in specs detector to test basic functionality of {@link AbstractBuiltinSpecsDetector}.
*/
private class MockBuiltinSpecsDetector extends AbstractBuiltinSpecsDetector {
@Override
protected List<String> parseOptions(String line) {
return null;
}
@Override
protected AbstractOptionParser[] getOptionParsers() {
return null;
}
@Override
protected String getCompilerCommand(String languageId) {
return null;
}
@Override
protected void startupForLanguage(String languageId) throws CoreException {
super.startupForLanguage(languageId);
}
@Override
protected void shutdownForLanguage() {
super.shutdownForLanguage();
}
}
/**
* Mock built-in specs detector to test execute() functionality.
*/
private class MockBuiltinSpecsDetectorExecutedFlag extends AbstractBuiltinSpecsDetector {
@Override
protected List<String> parseOptions(String line) {
return null;
}
@Override
protected AbstractOptionParser[] getOptionParsers() {
return null;
}
@Override
protected String getCompilerCommand(String languageId) {
return null;
}
@Override
protected void execute() {
super.execute();
}
protected boolean isExecuted() {
return isExecuted;
}
}
/**
* Mock built-in specs detector to test parsing functionality.
*/
private class MockConsoleBuiltinSpecsDetector extends AbstractBuiltinSpecsDetector {
@SuppressWarnings("nls")
private final AbstractOptionParser[] optionParsers = {
new MacroOptionParser("#define (\\S*) *(\\S*)", "$1", "$2", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY),
};
@Override
protected int runProgramForLanguage(String languageId, String command, String[] envp, URI workingDirectoryURI, OutputStream consoleOut, OutputStream consoleErr, IProgressMonitor monitor) throws CoreException, IOException {
String line = "#define MACRO VALUE";
consoleOut.write((line + '\n').getBytes());
consoleOut.flush();
return ICommandLauncher.OK;
}
@Override
protected IStatus runForEachLanguage(IProgressMonitor monitor) {
return super.runForEachLanguage(monitor);
}
@Override
protected List<String> parseOptions(final String line) {
return new ArrayList<String>() {{ add(line); }};
}
@Override
protected AbstractOptionParser[] getOptionParsers() {
return optionParsers;
}
@Override
protected String getCompilerCommand(String languageId) {
return null;
}
}
@Override
protected void setUp() throws Exception {
super.setUp();
}
@Override
protected void tearDown() throws Exception {
try {
Job.getJobManager().join(AbstractBuiltinSpecsDetector.JOB_FAMILY_BUILTIN_SPECS_DETECTOR, null);
} catch (Exception e) {
// ignore
}
super.tearDown();
}
/**
* Helper method to fetch configuration descriptions.
*/
private ICConfigurationDescription[] getConfigurationDescriptions(IProject project) {
CoreModel coreModel = CoreModel.getDefault();
ICProjectDescriptionManager mngr = coreModel.getProjectDescriptionManager();
// project description
ICProjectDescription projectDescription = mngr.getProjectDescription(project, false);
assertNotNull(projectDescription);
assertEquals(1, projectDescription.getConfigurations().length);
// configuration description
ICConfigurationDescription[] cfgDescriptions = projectDescription.getConfigurations();
return cfgDescriptions;
}
/**
* Test configure, getters and setters.
*/
public void testAbstractBuiltinSpecsDetector_GettersSetters() throws Exception {
{
// provider configured with null parameters
MockBuiltinSpecsDetectorExecutedFlag provider = new MockBuiltinSpecsDetectorExecutedFlag();
provider.configureProvider(PROVIDER_ID, PROVIDER_NAME, null, null, null);
assertEquals(PROVIDER_ID, provider.getId());
assertEquals(PROVIDER_NAME, provider.getName());
assertEquals(null, provider.getLanguageScope());
assertEquals(null, provider.getSettingEntries(null, null, null));
assertEquals("", provider.getCommand());
assertEquals(false, provider.isExecuted());
assertEquals(false, provider.isConsoleEnabled());
}
{
// provider configured with non-null parameters
MockBuiltinSpecsDetectorExecutedFlag provider = new MockBuiltinSpecsDetectorExecutedFlag();
List<String> languages = new ArrayList<String>();
languages.add(LANGUAGE_ID);
Map<String, String> properties = new HashMap<String, String>();
properties.put(ATTR_PARAMETER, CUSTOM_PARAMETER);
List<ICLanguageSettingEntry> entries = new ArrayList<ICLanguageSettingEntry>();
ICLanguageSettingEntry entry = new CMacroEntry("MACRO", "VALUE", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY);
entries.add(entry);
provider.configureProvider(PROVIDER_ID, PROVIDER_NAME, languages, entries, properties);
assertEquals(PROVIDER_ID, provider.getId());
assertEquals(PROVIDER_NAME, provider.getName());
assertEquals(languages, provider.getLanguageScope());
assertEquals(entries, provider.getSettingEntries(null, null, null));
assertEquals(CUSTOM_PARAMETER, provider.getCommand());
assertEquals(false, provider.isConsoleEnabled());
assertEquals(false, provider.isExecuted());
// setters
provider.setCommand(CUSTOM_PARAMETER_2);
assertEquals(CUSTOM_PARAMETER_2, provider.getCommand());
provider.setConsoleEnabled(true);
assertEquals(true, provider.isConsoleEnabled());
provider.execute();
assertEquals(true, provider.isExecuted());
}
}
/**
* Test clone() and equals().
*/
public void testAbstractBuiltinSpecsDetector_CloneAndEquals() throws Exception {
// define mock detector
class MockDetectorCloneable extends MockBuiltinSpecsDetectorExecutedFlag implements Cloneable {
@Override
public MockDetectorCloneable clone() throws CloneNotSupportedException {
return (MockDetectorCloneable) super.clone();
}
@Override
public MockDetectorCloneable cloneShallow() throws CloneNotSupportedException {
return (MockDetectorCloneable) super.cloneShallow();
}
}
// create instance to compare to
MockDetectorCloneable provider = new MockDetectorCloneable();
List<String> languages = new ArrayList<String>();
languages.add(LANGUAGE_ID);
List<ICLanguageSettingEntry> entries = new ArrayList<ICLanguageSettingEntry>();
ICLanguageSettingEntry entry = new CMacroEntry("MACRO", "VALUE", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY);
entries.add(entry);
// check clone after initialization
MockDetectorCloneable clone0 = provider.clone();
assertTrue(provider.equals(clone0));
// configure provider
Map<String, String> properties = new HashMap<String, String>();
properties.put(ATTR_PARAMETER, CUSTOM_PARAMETER);
provider.configureProvider(PROVIDER_ID, PROVIDER_NAME, languages, entries, properties);
assertEquals(false, provider.isConsoleEnabled());
provider.setConsoleEnabled(true);
provider.execute();
assertEquals(true, provider.isExecuted());
assertFalse(provider.equals(clone0));
// check another clone after configuring
{
MockDetectorCloneable clone = provider.clone();
assertTrue(provider.equals(clone));
}
// check custom parameter
{
MockDetectorCloneable clone = provider.clone();
clone.setCommand("changed");
assertFalse(provider.equals(clone));
}
// check language scope
{
MockDetectorCloneable clone = provider.clone();
clone.setLanguageScope(null);
assertFalse(provider.equals(clone));
}
// check console flag
{
MockDetectorCloneable clone = provider.clone();
boolean isConsoleEnabled = clone.isConsoleEnabled();
clone.setConsoleEnabled( ! isConsoleEnabled );
assertFalse(provider.equals(clone));
}
// check isExecuted flag
{
MockDetectorCloneable clone = provider.clone();
assertEquals(true, clone.isExecuted());
clone.clear();
assertEquals(false, clone.isExecuted());
assertFalse(provider.equals(clone));
}
// check entries
{
MockDetectorCloneable clone = provider.clone();
clone.setSettingEntries(null, null, null, null);
assertFalse(provider.equals(clone));
}
// check cloneShallow()
{
MockDetectorCloneable provider2 = provider.clone();
MockDetectorCloneable clone = provider2.cloneShallow();
assertEquals(false, clone.isExecuted());
assertFalse(provider2.equals(clone));
provider2.setSettingEntries(null, null, null, null);
assertFalse(provider2.equals(clone));
clone.execute();
assertTrue(provider2.equals(clone));
}
}
/**
* Test basic serialization functionality.
*/
public void testAbstractBuiltinSpecsDetector_SerializeDOM() throws Exception {
{
// create empty XML
Document doc = XmlUtil.newDocument();
Element rootElement = XmlUtil.appendElement(doc, ELEM_TEST);
// initialize provider
MockBuiltinSpecsDetectorExecutedFlag provider = new MockBuiltinSpecsDetectorExecutedFlag();
assertEquals(false, provider.isExecuted());
// load the XML to new provider
provider.load(rootElement);
assertEquals(false, provider.isConsoleEnabled());
assertEquals(false, provider.isExecuted());
}
Element elementProvider;
{
// define mock detector
MockBuiltinSpecsDetectorExecutedFlag provider = new MockBuiltinSpecsDetectorExecutedFlag();
assertEquals(false, provider.isConsoleEnabled());
assertEquals(false, provider.isExecuted());
// redefine the settings
provider.setConsoleEnabled(true);
assertEquals(true, provider.isConsoleEnabled());
// serialize in XML
Document doc = XmlUtil.newDocument();
Element rootElement = XmlUtil.appendElement(doc, ELEM_TEST);
elementProvider = provider.serialize(rootElement);
String xmlString = XmlUtil.toString(doc);
assertTrue(xmlString.contains(ATTR_CONSOLE));
}
{
// create another instance of the provider
MockBuiltinSpecsDetectorExecutedFlag provider = new MockBuiltinSpecsDetectorExecutedFlag();
assertEquals(false, provider.isConsoleEnabled());
assertEquals(false, provider.isExecuted());
// load element
provider.load(elementProvider);
assertEquals(true, provider.isConsoleEnabled());
assertEquals(false, provider.isExecuted());
}
}
/**
* Test serialization of entries and "isExecuted" flag handling.
*/
public void testAbstractBuiltinSpecsDetector_SerializeEntriesDOM() throws Exception {
Element rootElement;
{
// create provider
MockBuiltinSpecsDetectorExecutedFlag provider = new MockBuiltinSpecsDetectorExecutedFlag();
List<ICLanguageSettingEntry> entries = new ArrayList<ICLanguageSettingEntry>();
entries.add(new CIncludePathEntry("path0", 1));
provider.setSettingEntries(null, null, null, entries);
// serialize entries
Document doc = XmlUtil.newDocument();
rootElement = XmlUtil.appendElement(doc, ELEM_TEST);
provider.serializeEntries(rootElement);
// check XML
String xmlString = XmlUtil.toString(doc);
assertTrue(xmlString.contains("path0"));
}
{
// create new provider
MockBuiltinSpecsDetectorExecutedFlag provider = new MockBuiltinSpecsDetectorExecutedFlag();
assertEquals(true, provider.isEmpty());
assertEquals(false, provider.isExecuted());
// load the XML to the new provider
provider.load(rootElement);
List<ICLanguageSettingEntry> entries = provider.getSettingEntries(null, null, null);
assertNotNull(entries);
assertTrue(entries.size() > 0);
assertEquals(new CIncludePathEntry("path0", 1), entries.get(0));
assertEquals(false, provider.isEmpty());
assertEquals(true, provider.isExecuted());
// clear the new provider
provider.clear();
assertEquals(true, provider.isEmpty());
assertEquals(false, provider.isExecuted());
}
{
// create new provider
MockBuiltinSpecsDetectorExecutedFlag provider = new MockBuiltinSpecsDetectorExecutedFlag();
assertEquals(true, provider.isEmpty());
assertEquals(false, provider.isExecuted());
// execute provider
provider.execute();
List<ICLanguageSettingEntry> entries = provider.getSettingEntries(null, null, null);
assertEquals(null, entries);
// executed provider should NOT appear as empty even with no entries set
assertEquals(false, provider.isEmpty());
assertEquals(true, provider.isExecuted());
}
}
/**
* Smoke test exercising passing {@code null} to the functions.
*/
public void testAbstractBuiltinSpecsDetector_Nulls() throws Exception {
{
// test AbstractBuiltinSpecsDetector.processLine(...) flow
MockBuiltinSpecsDetector provider = new MockBuiltinSpecsDetector();
provider.startup(null, null);
provider.startupForLanguage(null);
provider.processLine(null);
provider.shutdownForLanguage();
provider.shutdown();
}
{
// test AbstractBuiltinSpecsDetector.processLine(...) flow
MockConsoleBuiltinSpecsDetector provider = new MockConsoleBuiltinSpecsDetector();
provider.startup(null, null);
provider.runForEachLanguage(null);
provider.shutdown();
}
}
/**
* Test basic parsing functionality.
*/
public void testAbstractBuiltinSpecsDetector_RunConfiguration() throws Exception {
// Create model project and accompanied descriptions
String projectName = getName();
IProject project = ResourceHelper.createCDTProjectWithConfig(projectName);
ICConfigurationDescription[] cfgDescriptions = getConfigurationDescriptions(project);
ICConfigurationDescription cfgDescription = cfgDescriptions[0];
MockConsoleBuiltinSpecsDetector provider = new MockConsoleBuiltinSpecsDetector();
provider.setLanguageScope(new ArrayList<String>() {{add(LANGUAGE_ID);}});
// Run provider
provider.startup(cfgDescription, null);
provider.runForEachLanguage(null);
provider.shutdown();
assertFalse(provider.isEmpty());
List<ICLanguageSettingEntry> noentries = provider.getSettingEntries(null, null, null);
assertNull(noentries);
// Check parsed entries
List<ICLanguageSettingEntry> entries = provider.getSettingEntries(cfgDescription, null, LANGUAGE_ID);
ICLanguageSettingEntry expected = new CMacroEntry("MACRO", "VALUE", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY);
assertEquals(expected, entries.get(0));
}
/**
* Smoke test running as global provider on workspace level.
*/
public void testAbstractBuiltinSpecsDetector_RunGlobal() throws Exception {
// Create provider
MockConsoleBuiltinSpecsDetector provider = new MockConsoleBuiltinSpecsDetector();
provider.setLanguageScope(new ArrayList<String>() {{add(LANGUAGE_ID);}});
// Run provider
provider.startup(null, null);
provider.runForEachLanguage(null);
provider.shutdown();
assertFalse(provider.isEmpty());
// Check parsed entries
List<ICLanguageSettingEntry> entries = provider.getSettingEntries(null, null, LANGUAGE_ID);
ICLanguageSettingEntry expected = new CMacroEntry("MACRO", "VALUE", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY);
assertEquals(expected, entries.get(0));
}
/**
* Check that entries get grouped by kinds by stock built-in specs detector.
*/
public void testAbstractBuiltinSpecsDetector_GroupSettings() throws Exception {
// define benchmarks
final CIncludePathEntry includePath_1 = new CIncludePathEntry("/include/path_1", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY);
final CIncludePathEntry includePath_2 = new CIncludePathEntry("/include/path_2", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY);
final CIncludeFileEntry includeFile_1 = new CIncludeFileEntry(new Path("/include.file1"), ICSettingEntry.BUILTIN | ICSettingEntry.READONLY);
final CIncludeFileEntry includeFile_2 = new CIncludeFileEntry(new Path("/include.file2"), ICSettingEntry.BUILTIN | ICSettingEntry.READONLY);
final CMacroEntry macro_1 = new CMacroEntry("MACRO_1", "", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY);
final CMacroEntry macro_2 = new CMacroEntry("MACRO_2", "", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY |ICSettingEntry.UNDEFINED);
final CMacroFileEntry macroFile_1 = new CMacroFileEntry(new Path("/macro.file1"), ICSettingEntry.BUILTIN | ICSettingEntry.READONLY);
final CMacroFileEntry macroFile_2 = new CMacroFileEntry(new Path("/macro.file2"), ICSettingEntry.BUILTIN | ICSettingEntry.READONLY);
final CLibraryPathEntry libraryPath_1 = new CLibraryPathEntry(new Path("/lib/path_1"), ICSettingEntry.BUILTIN | ICSettingEntry.READONLY);
final CLibraryPathEntry libraryPath_2 = new CLibraryPathEntry(new Path("/lib/path_2"), ICSettingEntry.BUILTIN | ICSettingEntry.READONLY);
final CLibraryFileEntry libraryFile_1 = new CLibraryFileEntry("lib_1.a", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY);
final CLibraryFileEntry libraryFile_2 = new CLibraryFileEntry("lib_2.a", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY);
// Define mock detector adding unorganized entries
MockBuiltinSpecsDetector provider = new MockBuiltinSpecsDetector() {
@Override
public boolean processLine(String line) {
detectedSettingEntries.add(libraryFile_1);
detectedSettingEntries.add(libraryPath_1);
detectedSettingEntries.add(macroFile_1);
detectedSettingEntries.add(macro_1);
detectedSettingEntries.add(includeFile_1);
detectedSettingEntries.add(includePath_1);
detectedSettingEntries.add(includePath_2);
detectedSettingEntries.add(includeFile_2);
detectedSettingEntries.add(macro_2);
detectedSettingEntries.add(macroFile_2);
detectedSettingEntries.add(libraryPath_2);
detectedSettingEntries.add(libraryFile_2);
return true;
}
};
// run specs detector
provider.startup(null, null);
provider.startupForLanguage(null);
provider.processLine("");
provider.shutdownForLanguage();
provider.shutdown();
// compare benchmarks, expected well-sorted
List<ICLanguageSettingEntry> entries = provider.getSettingEntries(null, null, null);
int i = 0;
assertEquals(includePath_1, entries.get(i++));
assertEquals(includePath_2, entries.get(i++));
assertEquals(includeFile_1, entries.get(i++));
assertEquals(includeFile_2, entries.get(i++));
assertEquals(macro_1, entries.get(i++));
assertEquals(macro_2, entries.get(i++));
assertEquals(macroFile_1, entries.get(i++));
assertEquals(macroFile_2, entries.get(i++));
assertEquals(libraryPath_1, entries.get(i++));
assertEquals(libraryPath_2, entries.get(i++));
assertEquals(libraryFile_1, entries.get(i++));
assertEquals(libraryFile_2, entries.get(i++));
assertEquals(12, entries.size());
}
}

View file

@ -0,0 +1,366 @@
/*******************************************************************************
* Copyright (c) 2010, 2012 Andrew Gvozdev 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:
* Andrew Gvozdev - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.managedbuilder.language.settings.providers.tests;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.cdt.core.dom.ast.gnu.c.GCCLanguage;
import org.eclipse.cdt.core.settings.model.CIncludePathEntry;
import org.eclipse.cdt.core.settings.model.CMacroEntry;
import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry;
import org.eclipse.cdt.core.settings.model.ICSettingEntry;
import org.eclipse.cdt.core.testplugin.ResourceHelper;
import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
import org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
/**
* Test cases to test GCC built-in specs detector.
*/
public class GCCBuiltinSpecsDetectorTest extends BaseTestCase {
private static final String LANGUAGE_ID_C = GCCLanguage.ID;
/**
* Mock GCCBuiltinSpecsDetector to gain access to protected methods.
*/
class MockGCCBuiltinSpecsDetector extends GCCBuiltinSpecsDetector {
@Override
public void startupForLanguage(String languageId) throws CoreException {
super.startupForLanguage(languageId);
}
@Override
public void shutdownForLanguage() {
super.shutdownForLanguage();
}
}
@Override
protected void setUp() throws Exception {
super.setUp();
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
}
/**
* Test expansion of variables in build command.
*/
public void testGCCBuiltinSpecsDetector_ResolvedCommand() throws Exception {
class MockGCCBuiltinSpecsDetectorLocal extends GCCBuiltinSpecsDetector {
@Override
public String resolveCommand(String languageId) throws CoreException {
return super.resolveCommand(languageId);
}
}
{
MockGCCBuiltinSpecsDetectorLocal detector = new MockGCCBuiltinSpecsDetectorLocal();
detector.setLanguageScope(new ArrayList<String>() {{add(LANGUAGE_ID_C);}});
detector.setCommand("${COMMAND} -E -P -v -dD ${INPUTS}");
String resolvedCommand = detector.resolveCommand(LANGUAGE_ID_C);
assertTrue(resolvedCommand.startsWith("gcc -E -P -v -dD "));
assertTrue(resolvedCommand.endsWith("spec.c"));
}
{
MockGCCBuiltinSpecsDetectorLocal detector = new MockGCCBuiltinSpecsDetectorLocal();
detector.setLanguageScope(new ArrayList<String>() {{add(LANGUAGE_ID_C);}});
detector.setCommand("${COMMAND} -E -P -v -dD file.${EXT}");
String resolvedCommand = detector.resolveCommand(LANGUAGE_ID_C);
assertTrue(resolvedCommand.startsWith("gcc -E -P -v -dD "));
assertTrue(resolvedCommand.endsWith("file.c"));
}
}
/**
* Test parsing of macro without value.
*/
public void testGCCBuiltinSpecsDetector_Macro_NoValue() throws Exception {
MockGCCBuiltinSpecsDetector detector = new MockGCCBuiltinSpecsDetector();
detector.startup(null, null);
detector.startupForLanguage(null);
detector.processLine("#define MACRO");
detector.shutdownForLanguage();
detector.shutdown();
List<ICLanguageSettingEntry> entries = detector.getSettingEntries(null, null, null);
assertEquals(new CMacroEntry("MACRO", null, ICSettingEntry.BUILTIN | ICSettingEntry.READONLY), entries.get(0));
assertEquals(1, entries.size());
}
/**
* Test parsing of macro with ordinary value.
*/
public void testGCCBuiltinSpecsDetector_Macro_Simple() throws Exception {
MockGCCBuiltinSpecsDetector detector = new MockGCCBuiltinSpecsDetector();
detector.startup(null, null);
detector.startupForLanguage(null);
detector.processLine("#define MACRO VALUE");
detector.shutdownForLanguage();
detector.shutdown();
List<ICLanguageSettingEntry> entries = detector.getSettingEntries(null, null, null);
assertEquals(new CMacroEntry("MACRO", "VALUE", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY), entries.get(0));
assertEquals(1, entries.size());
}
/**
* Test parsing of macro with value in round brackets.
*/
public void testGCCBuiltinSpecsDetector_Macro_Const() throws Exception {
MockGCCBuiltinSpecsDetector detector = new MockGCCBuiltinSpecsDetector();
detector.startup(null, null);
detector.startupForLanguage(null);
detector.processLine("#define MACRO (3)");
detector.shutdownForLanguage();
detector.shutdown();
List<ICLanguageSettingEntry> entries = detector.getSettingEntries(null, null, null);
assertEquals(new CMacroEntry("MACRO", "(3)", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY), entries.get(0));
assertEquals(1, entries.size());
}
/**
* Test parsing of macro definition with tabs.
*/
public void testGCCBuiltinSpecsDetector_Macro_WhiteSpaces() throws Exception {
MockGCCBuiltinSpecsDetector detector = new MockGCCBuiltinSpecsDetector();
detector.startup(null, null);
detector.startupForLanguage(null);
detector.processLine("#define \t MACRO_1 VALUE");
detector.processLine("#define MACRO_2 \t VALUE");
detector.processLine("#define MACRO_3 VALUE \t");
detector.shutdownForLanguage();
detector.shutdown();
List<ICLanguageSettingEntry> entries = detector.getSettingEntries(null, null, null);
int index = 0;
assertEquals(new CMacroEntry("MACRO_1", "VALUE", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY), entries.get(index++));
assertEquals(new CMacroEntry("MACRO_2", "VALUE", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY), entries.get(index++));
assertEquals(new CMacroEntry("MACRO_3", "VALUE", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY), entries.get(index++));
assertEquals(index, entries.size());
}
/**
* Test parsing of macro definition with empty argument list.
*/
public void testGCCBuiltinSpecsDetector_Macro_EmptyArgList() throws Exception {
MockGCCBuiltinSpecsDetector detector = new MockGCCBuiltinSpecsDetector();
detector.startup(null, null);
detector.startupForLanguage(null);
detector.processLine("#define MACRO() VALUE");
detector.shutdownForLanguage();
detector.shutdown();
List<ICLanguageSettingEntry> entries = detector.getSettingEntries(null, null, null);
assertEquals(new CMacroEntry("MACRO()", "VALUE", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY), entries.get(0));
assertEquals(1, entries.size());
}
/**
* Test parsing of macro definition with unused parameter.
*/
public void testGCCBuiltinSpecsDetector_Macro_ParamUnused() throws Exception {
MockGCCBuiltinSpecsDetector detector = new MockGCCBuiltinSpecsDetector();
detector.startup(null, null);
detector.startupForLanguage(null);
detector.processLine("#define MACRO(X) VALUE");
detector.shutdownForLanguage();
detector.shutdown();
List<ICLanguageSettingEntry> entries = detector.getSettingEntries(null, null, null);
assertEquals(new CMacroEntry("MACRO(X)", "VALUE", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY), entries.get(0));
assertEquals(1, entries.size());
}
/**
* Test parsing of macro definition with multiple parameters.
*/
public void testGCCBuiltinSpecsDetector_Macro_ParamSpace() throws Exception {
MockGCCBuiltinSpecsDetector detector = new MockGCCBuiltinSpecsDetector();
detector.startup(null, null);
detector.startupForLanguage(null);
detector.processLine("#define MACRO(P1, P2) VALUE(P1, P2)");
detector.shutdownForLanguage();
detector.shutdown();
List<ICLanguageSettingEntry> entries = detector.getSettingEntries(null, null, null);
assertEquals(new CMacroEntry("MACRO(P1, P2)", "VALUE(P1, P2)", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY), entries.get(0));
assertEquals(1, entries.size());
}
/**
* Test parsing of macro definition with multiple parameters and no value.
*/
public void testGCCBuiltinSpecsDetector_Macro_ArgsNoValue() throws Exception {
MockGCCBuiltinSpecsDetector detector = new MockGCCBuiltinSpecsDetector();
detector.startup(null, null);
detector.startupForLanguage(null);
detector.processLine("#define MACRO(P1, P2) ");
detector.shutdownForLanguage();
detector.shutdown();
List<ICLanguageSettingEntry> entries = detector.getSettingEntries(null, null, null);
assertEquals(new CMacroEntry("MACRO(P1, P2)", null, ICSettingEntry.BUILTIN | ICSettingEntry.READONLY), entries.get(0));
assertEquals(1, entries.size());
}
/**
* Test parsing of macro definition having white spaces in various places.
*/
public void testGCCBuiltinSpecsDetector_Macro_Args_WhiteSpaces() throws Exception {
MockGCCBuiltinSpecsDetector detector = new MockGCCBuiltinSpecsDetector();
detector.startup(null, null);
detector.startupForLanguage(null);
detector.processLine("#define \t MACRO_1(P1, P2) VALUE(P1, P2)");
detector.processLine("#define MACRO_2(P1, P2) \t VALUE(P1, P2)");
detector.processLine("#define MACRO_3(P1, P2) VALUE(P1, P2) \t");
detector.shutdownForLanguage();
detector.shutdown();
List<ICLanguageSettingEntry> entries = detector.getSettingEntries(null, null, null);
int index = 0;
assertEquals(new CMacroEntry("MACRO_1(P1, P2)", "VALUE(P1, P2)", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY), entries.get(index++));
assertEquals(new CMacroEntry("MACRO_2(P1, P2)", "VALUE(P1, P2)", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY), entries.get(index++));
assertEquals(new CMacroEntry("MACRO_3(P1, P2)", "VALUE(P1, P2)", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY), entries.get(index++));
assertEquals(index, entries.size());
}
/**
* Test parsing of include directives.
*/
public void testGCCBuiltinSpecsDetector_Includes() throws Exception {
// Create model project and folders to test
String projectName = getName();
IProject project = ResourceHelper.createCDTProject(projectName);
IPath tmpPath = ResourceHelper.createTemporaryFolder();
ResourceHelper.createFolder(project, "/misplaced/include1");
ResourceHelper.createFolder(project, "/local/include");
ResourceHelper.createFolder(project, "/usr/include");
ResourceHelper.createFolder(project, "/usr/include2");
ResourceHelper.createFolder(project, "/misplaced/include2");
ResourceHelper.createFolder(project, "/System/Library/Frameworks");
ResourceHelper.createFolder(project, "/Library/Frameworks");
ResourceHelper.createFolder(project, "/misplaced/include3");
String loc = tmpPath.toString();
MockGCCBuiltinSpecsDetector detector = new MockGCCBuiltinSpecsDetector();
detector.startup(null, null);
detector.startupForLanguage(null);
detector.processLine(" "+loc+"/misplaced/include1");
detector.processLine("#include \"...\" search starts here:");
detector.processLine(" "+loc+"/local/include");
detector.processLine("#include <...> search starts here:");
detector.processLine(" "+loc+"/usr/include");
detector.processLine(" "+loc+"/usr/include/../include2");
detector.processLine(" "+loc+"/missing/folder");
detector.processLine(" "+loc+"/Library/Frameworks (framework directory)");
detector.processLine("End of search list.");
detector.processLine(" "+loc+"/misplaced/include2");
detector.processLine("Framework search starts here:");
detector.processLine(" "+loc+"/System/Library/Frameworks");
detector.processLine("End of framework search list.");
detector.processLine(" "+loc+"/misplaced/include3");
detector.shutdownForLanguage();
detector.shutdown();
List<ICLanguageSettingEntry> entries = detector.getSettingEntries(null, null, null);
int index = 0;
assertEquals(new CIncludePathEntry(loc+"/local/include", ICSettingEntry.LOCAL | ICSettingEntry.BUILTIN | ICSettingEntry.READONLY), entries.get(index++));
assertEquals(new CIncludePathEntry(loc+"/usr/include", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY), entries.get(index++));
assertEquals(new CIncludePathEntry(loc+"/usr/include2", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY), entries.get(index++));
assertEquals(new CIncludePathEntry(loc+"/missing/folder", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY), entries.get(index++));
assertEquals(new CIncludePathEntry(loc+"/Library/Frameworks", ICSettingEntry.FRAMEWORKS_MAC | ICSettingEntry.BUILTIN | ICSettingEntry.READONLY), entries.get(index++));
assertEquals(new CIncludePathEntry(loc+"/System/Library/Frameworks", ICSettingEntry.FRAMEWORKS_MAC | ICSettingEntry.BUILTIN | ICSettingEntry.READONLY), entries.get(index++));
assertEquals(index, entries.size());
}
/**
* Test parsing of macro definition of include directives having white spaces.
*/
public void testGCCBuiltinSpecsDetector_Includes_WhiteSpaces() throws Exception {
String loc = ResourceHelper.createTemporaryFolder().toString();
MockGCCBuiltinSpecsDetector detector = new MockGCCBuiltinSpecsDetector();
detector.startup(null, null);
detector.startupForLanguage(null);
detector.processLine("#include \"...\" search starts here:");
detector.processLine(" \t "+loc+"/local/include");
detector.processLine("#include <...> search starts here:");
detector.processLine(loc+"/usr/include");
detector.processLine(" "+loc+"/Library/Frameworks \t (framework directory)");
detector.processLine("End of search list.");
detector.processLine("Framework search starts here:");
detector.processLine(" "+loc+"/System/Library/Frameworks \t ");
detector.processLine("End of framework search list.");
detector.shutdownForLanguage();
detector.shutdown();
List<ICLanguageSettingEntry> entries = detector.getSettingEntries(null, null, null);
int index = 0;
assertEquals(new CIncludePathEntry(loc+"/local/include", ICSettingEntry.LOCAL | ICSettingEntry.BUILTIN | ICSettingEntry.READONLY), entries.get(index++));
assertEquals(new CIncludePathEntry(loc+"/usr/include", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY), entries.get(index++));
assertEquals(new CIncludePathEntry(loc+"/Library/Frameworks", ICSettingEntry.FRAMEWORKS_MAC | ICSettingEntry.BUILTIN | ICSettingEntry.READONLY), entries.get(index++));
assertEquals(new CIncludePathEntry(loc+"/System/Library/Frameworks", ICSettingEntry.FRAMEWORKS_MAC | ICSettingEntry.BUILTIN | ICSettingEntry.READONLY), entries.get(index++));
assertEquals(index, entries.size());
}
/**
* Test parsing of include directives incorporating symbolic links.
*/
public void testGCCBuiltinSpecsDetector_Includes_SymbolicLinkUp() throws Exception {
// do not test on systems where symbolic links are not supported
if (!ResourceHelper.isSymbolicLinkSupported())
return;
// Create model project and folders to test
String projectName = getName();
@SuppressWarnings("unused")
IProject project = ResourceHelper.createCDTProject(projectName);
// create link on the filesystem
IPath dir1 = ResourceHelper.createTemporaryFolder();
IPath dir2 = dir1.removeLastSegments(1);
IPath linkPath = dir1.append("linked");
ResourceHelper.createSymbolicLink(linkPath, dir2);
MockGCCBuiltinSpecsDetector detector = new MockGCCBuiltinSpecsDetector();
detector.startup(null, null);
detector.startupForLanguage(null);
detector.processLine("#include <...> search starts here:");
detector.processLine(" "+linkPath.toString()+"/..");
detector.processLine("End of search list.");
detector.shutdownForLanguage();
detector.shutdown();
// check populated entries
List<ICLanguageSettingEntry> entries = detector.getSettingEntries(null, null, null);
assertEquals(new CIncludePathEntry(dir2.removeLastSegments(1), ICSettingEntry.BUILTIN | ICSettingEntry.READONLY), entries.get(0));
assertEquals(1, entries.size());
}
}

View file

@ -15,9 +15,12 @@ Export-Package: org.eclipse.cdt.build.core.scannerconfig,
org.eclipse.cdt.managedbuilder.envvar,
org.eclipse.cdt.managedbuilder.internal.buildmodel;x-friends:="org.eclipse.cdt.managedbuilder.ui",
org.eclipse.cdt.managedbuilder.internal.core;x-friends:="org.eclipse.cdt.managedbuilder.ui",
org.eclipse.cdt.managedbuilder.internal.dataprovider;x-internal:=true,
org.eclipse.cdt.managedbuilder.internal.envvar;x-internal:=true,
org.eclipse.cdt.managedbuilder.internal.language.settings.providers;x-internal:=true,
org.eclipse.cdt.managedbuilder.internal.macros;x-friends:="org.eclipse.cdt.managedbuilder.ui",
org.eclipse.cdt.managedbuilder.internal.scannerconfig;x-internal:=true,
org.eclipse.cdt.managedbuilder.language.settings.providers,
org.eclipse.cdt.managedbuilder.macros,
org.eclipse.cdt.managedbuilder.makegen,
org.eclipse.cdt.managedbuilder.makegen.gnu,

View file

@ -597,6 +597,40 @@
</run>
</application>
</extension>
<extension
point="org.eclipse.cdt.core.LanguageSettingsProvider">
<provider
class="org.eclipse.cdt.managedbuilder.internal.language.settings.providers.MBSLanguageSettingsProvider"
id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider"
name="CDT Managed Build Setting Entries">
</provider>
<provider
class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector"
id="org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetector"
name="CDT GCC Builtin Compiler Settings"
parameter="${COMMAND} -E -P -v -dD ${INPUTS}">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
<provider
class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuildCommandParser"
id="org.eclipse.cdt.managedbuilder.core.GCCBuildCommandParser"
name="CDT GCC Build Output Parser"
parameter="(gcc)|([gc]\+\+)"
prefer-non-shared="true">
</provider>
</extension>
<extension
id="scanner.discovery.problem"
name="C/C++ Scanner Discovery Problem"
point="org.eclipse.core.resources.markers">
<super
type="org.eclipse.core.resources.problemmarker">
</super>
<persistent
value="true">
</persistent>
</extension>
<extension
id="headlessSettings"
name="HeadlessBuilder Additional Settings"

View file

@ -20,6 +20,7 @@ import org.eclipse.cdt.build.internal.core.scannerconfig2.CfgScannerConfigProfil
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.envvar.IEnvironmentVariable;
import org.eclipse.cdt.core.envvar.IEnvironmentVariableManager;
import org.eclipse.cdt.core.language.settings.providers.ScannerDiscoveryLegacySupport;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.resources.ACBuilder;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
@ -179,6 +180,7 @@ public class ScannerConfigBuilder extends ACBuilder {
public static SCProfileInstance build(CfgInfoContext context, IScannerConfigBuilderInfo2 buildInfo2, int flags, Properties env, IProgressMonitor monitor) throws CoreException{
IConfiguration cfg = context.getConfiguration();
if (ScannerDiscoveryLegacySupport.isLegacyScannerDiscoveryOn(ManagedBuildManager.getDescriptionForConfiguration(cfg))) {
IProject project = cfg.getOwner().getProject();
boolean autodiscoveryEnabled2 = buildInfo2.isAutoDiscoveryEnabled();
@ -211,6 +213,7 @@ public class ScannerConfigBuilder extends ACBuilder {
return instance;
}
}
return null;
}

View file

@ -19,6 +19,7 @@ import java.util.Map.Entry;
import org.eclipse.cdt.build.core.scannerconfig.CfgInfoContext;
import org.eclipse.cdt.build.core.scannerconfig.ICfgScannerConfigBuilderInfo2Set;
import org.eclipse.cdt.build.internal.core.scannerconfig.CfgScannerConfigUtil;
import org.eclipse.cdt.core.language.settings.providers.ScannerDiscoveryLegacySupport;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.make.core.MakeCorePlugin;
@ -36,6 +37,7 @@ import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;
import org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin;
import org.eclipse.cdt.managedbuilder.internal.core.Configuration;
import org.eclipse.cdt.managedbuilder.internal.dataprovider.BuildConfigurationData;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Preferences;
import org.eclipse.core.runtime.QualifiedName;
@ -213,8 +215,13 @@ public class CfgScannerConfigInfoFactory2 {
}
}
if (id == null) {
// Language Settings Providers are meant to replace legacy scanner discovery
// so do not try to find default profile
ICConfigurationDescription cfgDescription = ManagedBuildManager.getDescriptionForConfiguration(cfg);
if (ScannerDiscoveryLegacySupport.isLegacyScannerDiscoveryOn(cfgDescription)) {
id = CfgScannerConfigUtil.getDefaultProfileId(context, true);
}
}
InfoContext baseContext = context.toInfoContext();
if(info == null){

View file

@ -30,6 +30,7 @@ import org.eclipse.cdt.core.IConsoleParser;
import org.eclipse.cdt.core.IMarkerGenerator;
import org.eclipse.cdt.core.envvar.IEnvironmentVariable;
import org.eclipse.cdt.core.envvar.IEnvironmentVariableManager;
import org.eclipse.cdt.core.language.settings.providers.ScannerDiscoveryLegacySupport;
import org.eclipse.cdt.core.resources.IConsole;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.internal.core.BuildRunnerHelper;
@ -96,6 +97,7 @@ public class ExternalBuildRunner extends AbstractBuildRunner {
String[] targets = getTargets(kind, builder);
if (targets.length != 0 && targets[targets.length - 1].equals(builder.getCleanBuildTarget()))
isClean = true;
boolean isOnlyClean = isClean && (targets.length == 1);
String[] args = getCommandArguments(builder, targets);
@ -108,7 +110,13 @@ public class ExternalBuildRunner extends AbstractBuildRunner {
ErrorParserManager epm = new ErrorParserManager(project, workingDirectoryURI, markerGenerator, errorParsers);
List<IConsoleParser> parsers = new ArrayList<IConsoleParser>();
if (!isOnlyClean) {
ICConfigurationDescription cfgDescription = ManagedBuildManager.getDescriptionForConfiguration(configuration);
ManagedBuildManager.collectLanguageSettingsConsoleParsers(cfgDescription, epm, parsers);
if (ScannerDiscoveryLegacySupport.isLegacyScannerDiscoveryOn(cfgDescription)) {
collectScannerInfoConsoleParsers(project, configuration, workingDirectoryURI, markerGenerator, parsers);
}
}
buildRunnerHelper.setLaunchParameters(launcher, buildCommand, args, workingDirectoryURI, envp);
buildRunnerHelper.prepareStreams(epm, parsers, console, new SubProgressMonitor(monitor, TICKS_STREAM_PROGRESS_MONITOR));

View file

@ -14,11 +14,15 @@ package org.eclipse.cdt.managedbuilder.core;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.cdt.core.ErrorParserManager;
import org.eclipse.cdt.core.ICommandLauncher;
import org.eclipse.cdt.core.IConsoleParser;
import org.eclipse.cdt.core.IMarkerGenerator;
import org.eclipse.cdt.core.resources.IConsole;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.internal.core.BuildRunnerHelper;
import org.eclipse.cdt.managedbuilder.buildmodel.BuildDescriptionManager;
import org.eclipse.cdt.managedbuilder.buildmodel.IBuildDescription;
@ -77,9 +81,10 @@ public class InternalBuildRunner extends AbstractBuildRunner {
flags = BuildDescriptionManager.REBUILD | BuildDescriptionManager.REMOVED | BuildDescriptionManager.DEPS;
// delta = getDelta(currentProject);
// }
boolean buildIncrementaly = delta != null;
ICConfigurationDescription cfgDescription = ManagedBuildManager.getDescriptionForConfiguration(configuration);
// Prepare launch parameters for BuildRunnerHelper
String cfgName = configuration.getName();
String toolchainName = configuration.getToolChain().getName();
@ -90,7 +95,10 @@ public class InternalBuildRunner extends AbstractBuildRunner {
String[] errorParsers = builder.getErrorParsers();
ErrorParserManager epm = new ErrorParserManager(project, workingDirectoryURI, markerGenerator, errorParsers);
buildRunnerHelper.prepareStreams(epm, null, console, new SubProgressMonitor(monitor, TICKS_STREAM_PROGRESS_MONITOR));
List<IConsoleParser> parsers = new ArrayList<IConsoleParser>();
ManagedBuildManager.collectLanguageSettingsConsoleParsers(cfgDescription, epm, parsers);
buildRunnerHelper.prepareStreams(epm, parsers, console, new SubProgressMonitor(monitor, TICKS_STREAM_PROGRESS_MONITOR));
IBuildDescription des = BuildDescriptionManager.createBuildDescription(configuration, cBS, delta, flags);
DescriptionBuilder dBuilder = null;

View file

@ -49,6 +49,12 @@ import javax.xml.transform.stream.StreamResult;
import org.eclipse.cdt.core.AbstractCExtension;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.IConsoleParser;
import org.eclipse.cdt.core.language.settings.providers.ICBuildOutputParser;
import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvider;
import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvidersKeeper;
import org.eclipse.cdt.core.language.settings.providers.IWorkingDirectoryTracker;
import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsManager;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.CoreModelUtil;
import org.eclipse.cdt.core.parser.IScannerInfo;
@ -148,7 +154,6 @@ import org.w3c.dom.ProcessingInstruction;
* @noinstantiate This class is not intended to be instantiated by clients.
*/
public class ManagedBuildManager extends AbstractCExtension {
// private static final QualifiedName buildInfoProperty = new QualifiedName(ManagedBuilderCorePlugin.PLUGIN_ID, "managedBuildInfo"); //$NON-NLS-1$
private static final String ROOT_NODE_NAME = "ManagedProjectBuildInfo"; //$NON-NLS-1$
public static final String SETTINGS_FILE_NAME = ".cdtbuild"; //$NON-NLS-1$
@ -4721,4 +4726,24 @@ public class ManagedBuildManager extends AbstractCExtension {
return true; // no target platform - nothing to check.
}
/*package*/ static void collectLanguageSettingsConsoleParsers(ICConfigurationDescription cfgDescription, IWorkingDirectoryTracker cwdTracker, List<IConsoleParser> parsers) {
if (cfgDescription instanceof ILanguageSettingsProvidersKeeper) {
List<ILanguageSettingsProvider> lsProviders = ((ILanguageSettingsProvidersKeeper) cfgDescription).getLanguageSettingProviders();
for (ILanguageSettingsProvider lsProvider : lsProviders) {
ILanguageSettingsProvider rawProvider = LanguageSettingsManager.getRawProvider(lsProvider);
if (rawProvider instanceof ICBuildOutputParser) {
ICBuildOutputParser consoleParser = (ICBuildOutputParser) rawProvider;
try {
consoleParser.startup(cfgDescription, cwdTracker);
parsers.add(consoleParser);
} catch (CoreException e) {
ManagedBuilderCorePlugin.log(new Status(IStatus.ERROR, ManagedBuilderCorePlugin.PLUGIN_ID,
"Language Settings Provider failed to start up", e)); //$NON-NLS-1$
}
}
}
}
}
}

View file

@ -283,12 +283,4 @@ public class ManagedBuilderCorePlugin extends Plugin {
ProjectConverter.convertOldStdMakeToNewStyle(project, monitor);
}
// public IDiscoveredPathManager getDiscoveryManager() {
// if ( fDiscoveryPathManager == null) {
// fDiscoveryPathManager = new DiscoveredPathManager();
// fDiscoveryPathManager.startup();
// }
// return fDiscoveryPathManager;
// }
}

View file

@ -169,3 +169,14 @@ MultiResourceInfo.MultiResourceInfo.UnhandledIHoldsOptionsType=Unhandled parent
ResourceChangeHandler2.0=project build settings update job
ToolInfo.0=conversion failure
ToolInfo.1=the tool is removed
#Language settings providers messages
AbstractBuiltinSpecsDetector.AddScannerDiscoveryMarkers=Adding Scanner Discovery markers
AbstractBuiltinSpecsDetector.ClearingMarkers=Clearing markers for {0}
AbstractBuiltinSpecsDetector.DiscoverBuiltInSettingsJobName=Discover compiler built-in language settings
AbstractBuiltinSpecsDetector.RunningScannerDiscovery=Running scanner discovery: {0}
AbstractBuiltinSpecsDetector.ScannerDiscoveryMarkerLocationPreferences=Preferences, C++/Build/Settings/Discovery, [{0}] options
AbstractBuiltinSpecsDetector.ScannerDiscoveryMarkerLocationProperties=Project Properties, C++ Preprocessor Include.../Providers, [{0}] options
AbstractBuiltinSpecsDetector.ScannerDiscoveryTaskTitle=CDT Scanner Discovery
AbstractBuiltinSpecsDetector.SerializingResults=Serializing results

View file

@ -0,0 +1,118 @@
/*******************************************************************************
* Copyright (c) 2009, 2011 Andrew Gvozdev 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:
* Andrew Gvozdev - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.managedbuilder.internal.language.settings.providers;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.cdt.core.AbstractExecutableExtensionBase;
import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsBroadcastingProvider;
import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsStorage;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICFileDescription;
import org.eclipse.cdt.core.settings.model.ICFolderDescription;
import org.eclipse.cdt.core.settings.model.ICLanguageSetting;
import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry;
import org.eclipse.cdt.core.settings.model.ICResourceDescription;
import org.eclipse.cdt.core.settings.model.ICSettingBase;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IPath;
/**
* Implementation of language settings provider for CDT Managed Build System.
*/
public class MBSLanguageSettingsProvider extends AbstractExecutableExtensionBase implements ILanguageSettingsBroadcastingProvider {
@Override
public List<ICLanguageSettingEntry> getSettingEntries(ICConfigurationDescription cfgDescription, IResource rc, String languageId) {
IPath projectPath = rc.getProjectRelativePath();
ICLanguageSetting[] languageSettings = null;
if (rc instanceof IFile) {
ICLanguageSetting ls = cfgDescription.getLanguageSettingForFile(projectPath, true);
if (ls != null) {
languageSettings = new ICLanguageSetting[] { ls };
} else {
return getSettingEntries(cfgDescription, rc.getParent(), languageId);
}
} else {
ICResourceDescription rcDescription = cfgDescription.getResourceDescription(projectPath, false);
languageSettings = getLanguageSettings(rcDescription);
}
List<ICLanguageSettingEntry> list = new ArrayList<ICLanguageSettingEntry>();
if (languageSettings != null) {
for (ICLanguageSetting langSetting : languageSettings) {
if (langSetting != null) {
String id = langSetting.getLanguageId();
if (id != null && id.equals(languageId)) {
int kindsBits = langSetting.getSupportedEntryKinds();
for (int kind=1; kind <= kindsBits; kind <<= 1) {
if ((kindsBits & kind) != 0) {
list.addAll(langSetting.getSettingEntriesList(kind));
}
}
}
}
}
}
return LanguageSettingsStorage.getPooledList(list);
}
/**
* Get language settings for resource description.
*/
private ICLanguageSetting[] getLanguageSettings(ICResourceDescription rcDescription) {
ICLanguageSetting[] array = null;
switch (rcDescription.getType()) {
case ICSettingBase.SETTING_PROJECT:
case ICSettingBase.SETTING_CONFIGURATION:
case ICSettingBase.SETTING_FOLDER:
ICFolderDescription foDes = (ICFolderDescription)rcDescription;
array = foDes.getLanguageSettings();
break;
case ICSettingBase.SETTING_FILE:
ICFileDescription fiDes = (ICFileDescription)rcDescription;
ICLanguageSetting ls = fiDes.getLanguageSetting();
if (ls != null) {
array = new ICLanguageSetting[] { ls };
}
}
if (array == null) {
array = new ICLanguageSetting[0];
}
return array;
}
@Override
public LanguageSettingsStorage copyStorage() {
class PretendStorage extends LanguageSettingsStorage {
@Override
public boolean isEmpty() {
return false;
}
@Override
public LanguageSettingsStorage clone() throws CloneNotSupportedException {
return this;
}
@Override
public boolean equals(Object obj) {
// Note that this always triggers change event even if nothing changed in MBS
return false;
}
}
return new PretendStorage();
}
}

View file

@ -0,0 +1,280 @@
/*******************************************************************************
* Copyright (c) 2009, 2011 Andrew Gvozdev 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:
* Andrew Gvozdev - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.managedbuilder.language.settings.providers;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.cdt.core.IErrorParser2;
import org.eclipse.cdt.core.IMarkerGenerator;
import org.eclipse.cdt.core.errorparsers.RegexErrorParser;
import org.eclipse.cdt.core.errorparsers.RegexErrorPattern;
import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvider;
import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsManager;
import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
/**
* Abstract class for providers parsing compiler option from build command when present in build output.
*
* @since 8.1
*/
public abstract class AbstractBuildCommandParser extends AbstractLanguageSettingsOutputScanner {
public static final Object JOB_FAMILY_BUILD_COMMAND_PARSER = "org.eclipse.cdt.managedbuilder.AbstractBuildCommandParser"; //$NON-NLS-1$
private static final String ATTR_PARAMETER = "parameter"; //$NON-NLS-1$
private static final String ATTR_RESOURCE_SCOPE = "resource-scope"; //$NON-NLS-1$
private static final String VALUE_FILE_SCOPE = "per-file"; //$NON-NLS-1$
private static final String VALUE_FOLDER_SCOPE = "per-folder"; //$NON-NLS-1$
private static final String VALUE_PROJECT_SCOPE = "per-project"; //$NON-NLS-1$
private static final String LEADING_PATH_PATTERN = "\\S+[/\\\\]"; //$NON-NLS-1$
private static final Pattern OPTIONS_PATTERN = Pattern.compile("-[^\\s\"']*(\\s*((\".*?\")|('.*?')|([^-\\s][^\\s]+)))?"); //$NON-NLS-1$
private static final int OPTION_GROUP = 0;
public enum ResourceScope {
FILE,
FOLDER,
PROJECT,
}
/**
* Note: design patterns to keep file group the same and matching {@link #FILE_GROUP}
*/
@SuppressWarnings("nls")
private static final String[] COMPILER_COMMAND_PATTERN_TEMPLATES = {
"${COMPILER_PATTERN}.*\\s" + "()([^'\"\\s]*\\.${EXTENSIONS_PATTERN})(\\s.*)?[\r\n]*", // compiling unquoted file
"${COMPILER_PATTERN}.*\\s" + "(['\"])(.*\\.${EXTENSIONS_PATTERN})\\${COMPILER_GROUPS+1}(\\s.*)?[\r\n]*" // compiling quoted file
};
private static final int FILE_GROUP = 2;
// cached value from properties, do not need to use in equals() and hashCode()
private ResourceScope resourceScope = null;
/**
* The compiler command pattern without specifying compiler options.
* The options are intended to be handled with option parsers,
* see {@link #getOptionParsers()}.
* This is regular expression pattern.
*
* @return the compiler command pattern.
*/
public String getCompilerPattern() {
return getProperty(ATTR_PARAMETER);
}
/**
* Set compiler command pattern for the provider. See {@link #getCompilerPattern()}.
* @param commandPattern - value of the command pattern to set.
* This is regular expression pattern.
*/
public void setCompilerPattern(String commandPattern) {
setProperty(ATTR_PARAMETER, commandPattern);
}
/**
* Sub-expression for compiler command pattern accounting for spaces, quotes etc.
*/
@SuppressWarnings("nls")
private String getCompilerPatternExtended() {
String compilerPattern = getCompilerPattern();
return "\\s*\"?("+LEADING_PATH_PATTERN+")?(" + compilerPattern + ")\"?";
}
/**
* @return resource scope of the entries, i.e. level in resource hierarchy where language settings entries
* will be applied by the provider. Resource scope can be one of the following:
* <br>- {@code AbstractBuildCommandParser.ResourceScope.FILE} - apply entries to the file being parsed.
* <br>- {@code AbstractBuildCommandParser.ResourceScope.FOLDER} - apply entries to the enclosing folder.
* <br>- {@code AbstractBuildCommandParser.ResourceScope.PROJECT} - apply entries to the project level.
*/
public ResourceScope getResourceScope() {
if (resourceScope == null) {
String scopeStr = getProperty(ATTR_RESOURCE_SCOPE);
if (scopeStr.equals(VALUE_FILE_SCOPE)) {
resourceScope = ResourceScope.FILE;
} else if (scopeStr.equals(VALUE_FOLDER_SCOPE)) {
resourceScope = ResourceScope.FOLDER;
} else if (scopeStr.equals(VALUE_PROJECT_SCOPE)) {
resourceScope = ResourceScope.PROJECT;
} else {
resourceScope = ResourceScope.FILE;
}
}
return resourceScope;
}
/**
* Set resource scope of the entries, i.e. level in resource hierarchy where language settings entries
* will be applied by the provider.
*
* @param rcScope - resource scope can be one of the following:
* <br>- {@code AbstractBuildCommandParser.ResourceScope.FILE} - apply entries to the file being parsed.
* <br>- {@code AbstractBuildCommandParser.ResourceScope.FOLDER} - apply entries to the enclosing folder.
* <br>- {@code AbstractBuildCommandParser.ResourceScope.PROJECT} - apply entries to the project level.
*/
public void setResourceScope(ResourceScope rcScope) {
resourceScope = rcScope;
switch (rcScope) {
case FILE:
setProperty(ATTR_RESOURCE_SCOPE, VALUE_FILE_SCOPE);
break;
case FOLDER:
setProperty(ATTR_RESOURCE_SCOPE, VALUE_FOLDER_SCOPE);
break;
case PROJECT:
setProperty(ATTR_RESOURCE_SCOPE, VALUE_PROJECT_SCOPE);
break;
default:
setProperty(ATTR_RESOURCE_SCOPE, VALUE_FILE_SCOPE);
break;
}
}
@Override
protected void setSettingEntries(List<ICLanguageSettingEntry> entries) {
IResource rc = null;
switch (getResourceScope()) {
case FILE:
rc = currentResource;
break;
case FOLDER:
if (currentResource instanceof IFile) {
rc = currentResource.getParent();
}
break;
case PROJECT:
if (currentResource != null) {
rc = currentResource.getProject();
}
break;
default:
break;
}
setSettingEntries(currentCfgDescription, rc, currentLanguageId, entries);
}
/**
* Adjust count for file group taking into consideration extra groups added by {@link #getCompilerPatternExtended()}.
*/
private int adjustFileGroup() {
return countGroups(getCompilerPatternExtended()) + FILE_GROUP;
}
/**
* Make search pattern for compiler command based on template.
*/
private String makePattern(String template) {
@SuppressWarnings("nls")
String pattern = template
.replace("${COMPILER_PATTERN}", getCompilerPatternExtended())
.replace("${EXTENSIONS_PATTERN}", getPatternFileExtensions())
.replace("${COMPILER_GROUPS+1}", new Integer(countGroups(getCompilerPatternExtended()) + 1).toString());
return pattern;
}
@Override
protected String parseResourceName(String line) {
if (line == null) {
return null;
}
for (String template : COMPILER_COMMAND_PATTERN_TEMPLATES) {
String pattern = makePattern(template);
Matcher fileMatcher = Pattern.compile(pattern).matcher(line);
if (fileMatcher.matches()) {
int fileGroup = adjustFileGroup();
String sourceFileName = fileMatcher.group(fileGroup);
return sourceFileName;
}
}
return null;
}
@Override
protected List<String> parseOptions(String line) {
if (line == null || currentResource == null) {
return null;
}
List<String> options = new ArrayList<String>();
Matcher optionMatcher = OPTIONS_PATTERN.matcher(line);
while (optionMatcher.find()) {
String option = optionMatcher.group(OPTION_GROUP);
if (option!=null) {
options.add(option);
}
}
return options;
}
private void serializeLanguageSettingsInBackground() {
ILanguageSettingsProvider wspProvider = LanguageSettingsManager.getWorkspaceProvider(getId());
ILanguageSettingsProvider rawProvider = LanguageSettingsManager.getRawProvider(wspProvider);
if (rawProvider == this) {
// this is workspace provider
serializeLanguageSettingsInBackground(null);
} else {
serializeLanguageSettingsInBackground(currentCfgDescription);
}
}
@Override
public void shutdown() {
serializeLanguageSettingsInBackground();
super.shutdown();
}
/**
* Trivial Error Parser which allows highlighting of output lines matching the patterns
* of this parser. Intended for better troubleshooting experience.
* Implementers are supposed to add the error parser via extension point {@code org.eclipse.cdt.core.ErrorParser}.
*/
protected static abstract class AbstractBuildCommandPatternHighlighter extends RegexErrorParser implements IErrorParser2 {
/**
* Constructor.
* @param parserId - build command parser ID specified in the extension {@code org.eclipse.cdt.core.LanguageSettingsProvider}.
*/
public AbstractBuildCommandPatternHighlighter(String parserId) {
init(parserId);
}
/**
* Initialize the error parser.
* @param parserId - language settings provider (the build command parser) ID.
*/
protected void init(String parserId) {
AbstractBuildCommandParser buildCommandParser = (AbstractBuildCommandParser) LanguageSettingsManager.getExtensionProviderCopy(parserId, false);
if (buildCommandParser != null) {
for (String template : COMPILER_COMMAND_PATTERN_TEMPLATES) {
String pattern = buildCommandParser.makePattern(template);
String fileExpr = "$"+buildCommandParser.adjustFileGroup(); //$NON-NLS-1$
String descExpr = "$0"; //$NON-NLS-1$
addPattern(new RegexErrorPattern(pattern, fileExpr, null, descExpr, null, IMarkerGenerator.SEVERITY_WARNING, true));
}
}
}
@Override
public int getProcessLineBehaviour() {
return KEEP_LONGLINES;
}
}
}

View file

@ -0,0 +1,745 @@
/*******************************************************************************
* Copyright (c) 2009, 2011 Andrew Gvozdev 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:
* Andrew Gvozdev - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.managedbuilder.language.settings.providers;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.CommandLauncher;
import org.eclipse.cdt.core.ErrorParserManager;
import org.eclipse.cdt.core.ICommandLauncher;
import org.eclipse.cdt.core.IConsoleParser;
import org.eclipse.cdt.core.IMarkerGenerator;
import org.eclipse.cdt.core.ProblemMarkerInfo;
import org.eclipse.cdt.core.language.settings.providers.ICBuildOutputParser;
import org.eclipse.cdt.core.language.settings.providers.ICListenerAgent;
import org.eclipse.cdt.core.language.settings.providers.IWorkingDirectoryTracker;
import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.core.model.ILanguageDescriptor;
import org.eclipse.cdt.core.model.LanguageManager;
import org.eclipse.cdt.core.resources.IConsole;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.internal.core.BuildRunnerHelper;
import org.eclipse.cdt.internal.core.XmlUtil;
import org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin;
import org.eclipse.cdt.managedbuilder.internal.core.ManagedMakeMessages;
import org.eclipse.cdt.utils.CommandLineUtil;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.core.runtime.jobs.Job;
import org.w3c.dom.Element;
/**
* Abstract parser capable to execute compiler command printing built-in compiler
* specs and parse built-in language settings out of it.
*
* @since 8.1
*/
public abstract class AbstractBuiltinSpecsDetector extends AbstractLanguageSettingsOutputScanner implements ICListenerAgent {
public static final String JOB_FAMILY_BUILTIN_SPECS_DETECTOR = "org.eclipse.cdt.managedbuilder.AbstractBuiltinSpecsDetector"; //$NON-NLS-1$
protected static final String COMPILER_MACRO = "${COMMAND}"; //$NON-NLS-1$
protected static final String SPEC_FILE_MACRO = "${INPUTS}"; //$NON-NLS-1$
protected static final String SPEC_EXT_MACRO = "${EXT}"; //$NON-NLS-1$
protected static final String SPEC_FILE_BASE = "spec"; //$NON-NLS-1$
private static final String CDT_MANAGEDBUILDER_UI_PLUGIN_ID = "org.eclipse.cdt.managedbuilder.ui"; //$NON-NLS-1$
private static final String SCANNER_DISCOVERY_CONSOLE = "org.eclipse.cdt.managedbuilder.ScannerDiscoveryConsole"; //$NON-NLS-1$
private static final String SCANNER_DISCOVERY_GLOBAL_CONSOLE = "org.eclipse.cdt.managedbuilder.ScannerDiscoveryGlobalConsole"; //$NON-NLS-1$
private static final String DEFAULT_CONSOLE_ICON = "icons/obj16/inspect_system.gif"; //$NON-NLS-1$
private static final String GMAKE_ERROR_PARSER_ID = "org.eclipse.cdt.core.GmakeErrorParser"; //$NON-NLS-1$
private static final String ATTR_PARAMETER = "parameter"; //$NON-NLS-1$
private static final String ATTR_CONSOLE = "console"; //$NON-NLS-1$
private static final int MONITOR_SCALE = 100;
private static final int TICKS_REMOVE_MARKERS = 1 * MONITOR_SCALE;
private static final int TICKS_RUN_FOR_ONE_LANGUAGE = 10 * MONITOR_SCALE;
private static final int TICKS_SERIALIZATION = 1 * MONITOR_SCALE;
private static final int TICKS_OUTPUT_PARSING = 1 * MONITOR_SCALE;
private static final int TICKS_EXECUTE_COMMAND = 1 * MONITOR_SCALE;
protected URI mappedRootURI = null;
protected URI buildDirURI = null;
protected java.io.File specFile = null;
protected boolean preserveSpecFile = false;
protected List<ICLanguageSettingEntry> detectedSettingEntries = null;
protected int collected = 0;
protected boolean isExecuted = false;
private BuildRunnerHelper buildRunnerHelper;
private SDMarkerGenerator markerGenerator = new SDMarkerGenerator();
private boolean isConsoleEnabled = false;
private String currentCommandResolved = null;
private class SDMarkerGenerator implements IMarkerGenerator {
// Reuse scanner discovery markers defined in org.eclipse.cdt.managedbuilder.core plugin.xml
protected static final String SCANNER_DISCOVERY_PROBLEM_MARKER = "org.eclipse.cdt.managedbuilder.core.scanner.discovery.problem"; //$NON-NLS-1$
protected static final String ATTR_PROVIDER = "provider"; //$NON-NLS-1$
@Override
public void addMarker(IResource rc, int lineNumber, String errorDesc, int severity, String errorVar) {
ProblemMarkerInfo info = new ProblemMarkerInfo(rc, lineNumber, errorDesc, severity, errorVar);
addMarker(info);
}
@Override
public void addMarker(final ProblemMarkerInfo problemMarkerInfo) {
final String providerName = getName();
final String providerId = getId();
// Add markers in a job to avoid deadlocks
Job markerJob = new Job(ManagedMakeMessages.getResourceString("AbstractBuiltinSpecsDetector.AddScannerDiscoveryMarkers")) { //$NON-NLS-1$
@Override
protected IStatus run(IProgressMonitor monitor) {
// Avoid duplicates as different languages can generate identical errors
try {
IMarker[] markers = problemMarkerInfo.file.findMarkers(SDMarkerGenerator.SCANNER_DISCOVERY_PROBLEM_MARKER, false, IResource.DEPTH_ZERO);
for (IMarker marker : markers) {
int sev = ((Integer) marker.getAttribute(IMarker.SEVERITY)).intValue();
if (sev == problemMarkerInfo.severity) {
String msg = (String) marker.getAttribute(IMarker.MESSAGE);
if (msg != null && msg.equals(problemMarkerInfo.description)) {
return Status.OK_STATUS;
}
}
}
} catch (CoreException e) {
return new Status(Status.ERROR, ManagedBuilderCorePlugin.PLUGIN_ID, "Error checking markers.", e); //$NON-NLS-1$
}
try {
IMarker marker = problemMarkerInfo.file.createMarker(SDMarkerGenerator.SCANNER_DISCOVERY_PROBLEM_MARKER);
marker.setAttribute(IMarker.MESSAGE, problemMarkerInfo.description);
marker.setAttribute(IMarker.SEVERITY, problemMarkerInfo.severity);
marker.setAttribute(SDMarkerGenerator.ATTR_PROVIDER, providerId);
if (problemMarkerInfo.file instanceof IWorkspaceRoot) {
String msgPreferences = ManagedMakeMessages.getFormattedString("AbstractBuiltinSpecsDetector.ScannerDiscoveryMarkerLocationPreferences", providerName); //$NON-NLS-1$
marker.setAttribute(IMarker.LOCATION, msgPreferences);
} else {
String msgProperties = ManagedMakeMessages.getFormattedString("AbstractBuiltinSpecsDetector.ScannerDiscoveryMarkerLocationProperties", providerName); //$NON-NLS-1$
marker.setAttribute(IMarker.LOCATION, msgProperties);
}
} catch (CoreException e) {
return new Status(Status.ERROR, ManagedBuilderCorePlugin.PLUGIN_ID, "Error adding markers.", e); //$NON-NLS-1$
}
return Status.OK_STATUS;
}
};
markerJob.setRule(problemMarkerInfo.file);
markerJob.schedule();
}
/**
* Delete markers previously set by this provider for the resource.
*
* @param rc - resource to check markers.
*/
public void deleteMarkers(IResource rc) {
String providerId = getId();
try {
IMarker[] markers = rc.findMarkers(SCANNER_DISCOVERY_PROBLEM_MARKER, false, IResource.DEPTH_ZERO);
for (IMarker marker : markers) {
if (providerId.equals(marker.getAttribute(ATTR_PROVIDER))) {
marker.delete();
}
}
} catch (CoreException e) {
ManagedBuilderCorePlugin.log(new Status(Status.ERROR, ManagedBuilderCorePlugin.PLUGIN_ID, "Error deleting markers.", e)); //$NON-NLS-1$
}
}
}
/**
* Internal ICConsoleParser to handle individual run for one language.
*/
private class ConsoleParserAdapter implements ICBuildOutputParser {
@Override
public void startup(ICConfigurationDescription cfgDescription, IWorkingDirectoryTracker cwdTracker) throws CoreException {
AbstractBuiltinSpecsDetector.this.cwdTracker = cwdTracker;
}
@Override
public boolean processLine(String line) {
return AbstractBuiltinSpecsDetector.this.processLine(line);
}
@Override
public void shutdown() {
AbstractBuiltinSpecsDetector.this.cwdTracker = null;
}
}
/**
* Compiler command without arguments. This value is used to replace macro ${COMMAND}.
* In particular, this method is implemented in {@link ToolchainBuiltinSpecsDetector}
* which retrieves the command from tool-chain.
*
* @param languageId - language ID.
* @return compiler command without arguments, i.e. compiler program.
*/
protected abstract String getCompilerCommand(String languageId);
/**
* The command to run. Some macros could be specified in there:
* <ul>
* <b>${COMMAND}</b> - compiler command without arguments (compiler program).
* Normally would come from the tool-chain.<br>
* <b>${INPUTS}</b> - path to spec file which will be placed in workspace area.<br>
* <b>${EXT}</b> - file extension calculated from language ID.
* </ul>
* The parameter could be taken from the extension
* in {@code plugin.xml} or from property file.
*
* @return the command to run or empty string if command is not defined.
*/
public String getCommand() {
return getProperty(ATTR_PARAMETER);
}
/**
* Set custom command for the provider. See {@link #getCommand()}.
* @param command - value of custom command to set.
*/
public void setCommand(String command) {
setProperty(ATTR_PARAMETER, command);
}
/**
* @return {@code true} if console output is enabled for this provider, {@code false} otherwise.
*/
public boolean isConsoleEnabled() {
return isConsoleEnabled;
}
/**
* Enable or disable console output for this provider.
*
* @param enable - {@code true} to enable console output or {@code false} to disable.
*/
public void setConsoleEnabled(boolean enable) {
isConsoleEnabled = enable;
}
/**
* Expand macros specified in the compiler command. See {@link #getCommand()} for
* the recognized list of macros.
*
* @param languageId - language ID.
* @return - resolved command to run.
* @throws CoreException if something goes wrong.
*/
protected String resolveCommand(String languageId) throws CoreException {
String cmd = getCommand();
if (cmd != null) {
if (cmd.contains(COMPILER_MACRO)) {
String compiler = getCompilerCommand(languageId);
if (compiler != null)
cmd = cmd.replace(COMPILER_MACRO, compiler);
}
if (cmd.contains(SPEC_FILE_MACRO)) {
String specFileName = getSpecFile(languageId);
if (specFileName != null)
cmd = cmd.replace(SPEC_FILE_MACRO, specFileName);
}
if (cmd.contains(SPEC_EXT_MACRO)) {
String specFileExt = getSpecFileExtension(languageId);
if (specFileExt != null)
cmd = cmd.replace(SPEC_EXT_MACRO, specFileExt);
}
}
return cmd;
}
@Override
protected String parseResourceName(String line) {
// Normally built-in specs detectors are per-language and the result applies for the whole workspace.
// Returning null works workspace-wide here.
return null;
}
@Override
protected String determineLanguage() {
// language id is supposed to be set by run(), just return it
return currentLanguageId;
}
@Override
protected URI getMappedRootURI(IResource sourceFile, String parsedResourceName) {
// Do not calculate mappedRootURI for each line
if (mappedRootURI == null) {
mappedRootURI = super.getMappedRootURI(sourceFile, parsedResourceName);
}
return mappedRootURI;
}
@Override
protected URI getBuildDirURI(URI mappedRootURI) {
// Do not calculate buildDirURI for each line
if (buildDirURI == null) {
buildDirURI = super.getBuildDirURI(mappedRootURI);
}
return buildDirURI;
}
@Override
public void registerListener(ICConfigurationDescription cfgDescription) {
currentCfgDescription = cfgDescription;
execute();
}
@Override
public void unregisterListener() {
}
@Override
public void startup(ICConfigurationDescription cfgDescription, IWorkingDirectoryTracker cwdTracker) throws CoreException {
super.startup(cfgDescription, cwdTracker);
mappedRootURI = null;
buildDirURI = super.getBuildDirURI(mappedRootURI);
}
@Override
public void shutdown() {
mappedRootURI = null;
buildDirURI = null;
super.shutdown();
}
/**
* Execute provider's command which is expected to print built-in compiler options (specs) to build output.
* The parser will parse output and generate language settings for corresponding resources.
*/
protected void execute() {
if (isExecuted) {
return;
}
isExecuted = true;
Job job = new Job(ManagedMakeMessages.getResourceString("AbstractBuiltinSpecsDetector.DiscoverBuiltInSettingsJobNam")) { //$NON-NLS-1$
@Override
protected IStatus run(IProgressMonitor monitor) {
IStatus status;
try {
startup(currentCfgDescription, null);
status = runForEachLanguage(monitor);
} catch (CoreException e) {
ManagedBuilderCorePlugin.log(e);
status = new Status(IStatus.ERROR, ManagedBuilderCorePlugin.PLUGIN_ID, IStatus.ERROR, "Error running Builtin Specs Detector", e); //$NON-NLS-1$
} finally {
shutdown();
}
return status;
}
@Override
public boolean belongsTo(Object family) {
return family == JOB_FAMILY_BUILTIN_SPECS_DETECTOR;
}
};
IProject project = null;
if (currentCfgDescription != null) {
ICProjectDescription prjDescription = currentCfgDescription.getProjectDescription();
if (prjDescription != null) {
project = prjDescription.getProject();
}
}
job.setRule(project);
job.schedule();
}
/**
* Run built-in specs command for each language.
*
* @param monitor - progress monitor in the initial state where {@link IProgressMonitor#beginTask(String, int)}
* has not been called yet.
* @return status of operation.
*/
protected IStatus runForEachLanguage(IProgressMonitor monitor) {
MultiStatus status = new MultiStatus(ManagedBuilderCorePlugin.PLUGIN_ID, IStatus.OK, "Problem running CDT Scanner Discovery provider " + getId(), null); //$NON-NLS-1$
if (monitor == null) {
monitor = new NullProgressMonitor();
}
try {
boolean isChanged = false;
List<String> languageIds = getLanguageScope();
if (languageIds != null) {
monitor.beginTask(ManagedMakeMessages.getResourceString("AbstractBuiltinSpecsDetector.ScannerDiscoveryTaskTitle"), //$NON-NLS-1$
TICKS_REMOVE_MARKERS + languageIds.size()*TICKS_RUN_FOR_ONE_LANGUAGE + TICKS_SERIALIZATION);
IResource markersResource = currentProject != null ? currentProject : ResourcesPlugin.getWorkspace().getRoot();
monitor.subTask(ManagedMakeMessages.getFormattedString("AbstractBuiltinSpecsDetector.ClearingMarkers", markersResource.getFullPath().toString())); //$NON-NLS-1$
markerGenerator.deleteMarkers(markersResource);
if (monitor.isCanceled())
throw new OperationCanceledException();
monitor.worked(TICKS_REMOVE_MARKERS);
for (String languageId : languageIds) {
List<ICLanguageSettingEntry> oldEntries = getSettingEntries(currentCfgDescription, null, languageId);
try {
startupForLanguage(languageId);
runForLanguage(new SubProgressMonitor(monitor, TICKS_RUN_FOR_ONE_LANGUAGE));
} catch (Exception e) {
IStatus s = new Status(IStatus.ERROR, ManagedBuilderCorePlugin.PLUGIN_ID, IStatus.ERROR, "Error running Builtin Specs Detector", e); //$NON-NLS-1$
ManagedBuilderCorePlugin.log(s);
status.merge(s);
} finally {
shutdownForLanguage();
}
if (!isChanged) {
List<ICLanguageSettingEntry> newEntries = getSettingEntries(currentCfgDescription, null, languageId);
isChanged = newEntries != oldEntries;
}
if (monitor.isCanceled())
throw new OperationCanceledException();
}
}
monitor.subTask(ManagedMakeMessages.getResourceString("AbstractBuiltinSpecsDetector.SerializingResults")); //$NON-NLS-1$
if (isChanged) { // avoids resource and settings change notifications
IStatus s = serializeLanguageSettings(currentCfgDescription);
status.merge(s);
}
monitor.worked(TICKS_SERIALIZATION);
} catch (OperationCanceledException e) {
// user chose to cancel operation, do not threaten them with red error signs
} catch (Exception e) {
status.merge(new Status(IStatus.ERROR, ManagedBuilderCorePlugin.PLUGIN_ID, IStatus.ERROR, "Error running Builtin Specs Detector", e)); //$NON-NLS-1$
ManagedBuilderCorePlugin.log(status);
} finally {
monitor.done();
}
return status;
}
/**
* Initialize provider before running for a language.
*
* @param languageId - language ID.
* @throws CoreException if something goes wrong.
*/
protected void startupForLanguage(String languageId) throws CoreException {
currentLanguageId = languageId;
specFile = null; // init specFile *before* calling resolveCommand(), can be changed in there
currentCommandResolved = resolveCommand(currentLanguageId);
detectedSettingEntries = new ArrayList<ICLanguageSettingEntry>();
collected = 0;
}
/**
* Save collected entries and dispose temporary data used during run for the language.
*/
protected void shutdownForLanguage() {
if (detectedSettingEntries != null && detectedSettingEntries.size() > 0) {
collected = detectedSettingEntries.size();
setSettingEntries(currentCfgDescription, currentResource, currentLanguageId, detectedSettingEntries);
}
detectedSettingEntries = null;
currentCommandResolved = null;
if (specFile!=null && !preserveSpecFile) {
specFile.delete();
specFile = null;
}
currentLanguageId = null;
}
/**
* Run built-in specs command for one language.
*
* @param monitor - progress monitor in the initial state where {@link IProgressMonitor#beginTask(String, int)}
* has not been called yet.
*/
private void runForLanguage(IProgressMonitor monitor) throws CoreException {
buildRunnerHelper = new BuildRunnerHelper(currentProject);
if (monitor == null) {
monitor = new NullProgressMonitor();
}
try {
monitor.beginTask(ManagedMakeMessages.getFormattedString("AbstractBuiltinSpecsDetector.RunningScannerDiscovery", getName()), //$NON-NLS-1$
TICKS_EXECUTE_COMMAND + TICKS_OUTPUT_PARSING);
IConsole console;
if (isConsoleEnabled) {
console = startProviderConsole();
} else {
// that looks in extension points registry and won't find the id, this console is not shown
console = CCorePlugin.getDefault().getConsole(ManagedBuilderCorePlugin.PLUGIN_ID + ".console.hidden"); //$NON-NLS-1$
}
console.start(currentProject);
ICommandLauncher launcher = new CommandLauncher();
launcher.setProject(currentProject);
IPath program = new Path(""); //$NON-NLS-1$
String[] args = new String[0];
String[] cmdArray = CommandLineUtil.argumentsToArray(currentCommandResolved);
if (cmdArray != null && cmdArray.length > 0) {
program = new Path(cmdArray[0]);
if (cmdArray.length > 1) {
args = new String[cmdArray.length-1];
System.arraycopy(cmdArray, 1, args, 0, args.length);
}
}
String[] envp = BuildRunnerHelper.getEnvp(currentCfgDescription);
// Using GMAKE_ERROR_PARSER_ID as it can handle generated error messages
ErrorParserManager epm = new ErrorParserManager(currentProject, buildDirURI, markerGenerator, new String[] {GMAKE_ERROR_PARSER_ID});
ConsoleParserAdapter consoleParser = new ConsoleParserAdapter();
consoleParser.startup(currentCfgDescription, epm);
List<IConsoleParser> parsers = new ArrayList<IConsoleParser>();
parsers.add(consoleParser);
buildRunnerHelper.setLaunchParameters(launcher, program, args, buildDirURI, envp);
buildRunnerHelper.prepareStreams(epm, parsers, console, new SubProgressMonitor(monitor, TICKS_OUTPUT_PARSING));
buildRunnerHelper.greeting(ManagedMakeMessages.getFormattedString("AbstractBuiltinSpecsDetector.RunningScannerDiscovery", getName())); //$NON-NLS-1$
OutputStream outStream = buildRunnerHelper.getOutputStream();
OutputStream errStream = buildRunnerHelper.getErrorStream();
runProgramForLanguage(currentLanguageId, currentCommandResolved, envp, buildDirURI, outStream, errStream,
new SubProgressMonitor(monitor, TICKS_EXECUTE_COMMAND, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK));
buildRunnerHelper.close();
buildRunnerHelper.goodbye();
} catch (Exception e) {
ManagedBuilderCorePlugin.log(new CoreException(new Status(IStatus.ERROR, ManagedBuilderCorePlugin.PLUGIN_ID, "Error running Builtin Specs Detector" , e))); //$NON-NLS-1$
} finally {
try {
buildRunnerHelper.close();
} catch (IOException e) {
ManagedBuilderCorePlugin.log(e);
}
monitor.done();
}
}
protected int runProgramForLanguage(String languageId, String command, String[] envp, URI workingDirectoryURI, OutputStream consoleOut, OutputStream consoleErr, IProgressMonitor monitor) throws CoreException, IOException {
return buildRunnerHelper.build(monitor);
}
@Override
protected void setSettingEntries(List<ICLanguageSettingEntry> entries) {
// Built-in specs detectors collect entries not per line but for the whole output
// so collect them to save later when output finishes
if (entries != null) {
detectedSettingEntries.addAll(entries);
}
}
/**
* Create and start the provider console.
* @return CDT console.
*/
private IConsole startProviderConsole() {
IConsole console = null;
if (isConsoleEnabled && currentLanguageId != null) {
String extConsoleId;
if (currentProject != null) {
extConsoleId = SCANNER_DISCOVERY_CONSOLE;
} else {
extConsoleId = SCANNER_DISCOVERY_GLOBAL_CONSOLE;
}
ILanguage ld = LanguageManager.getInstance().getLanguage(currentLanguageId);
if (ld != null) {
String consoleId = ManagedBuilderCorePlugin.PLUGIN_ID + '.' + getId() + '.' + currentLanguageId;
String consoleName = getName() + ", " + ld.getName(); //$NON-NLS-1$
URL defaultIcon = Platform.getBundle(CDT_MANAGEDBUILDER_UI_PLUGIN_ID).getEntry(DEFAULT_CONSOLE_ICON);
if (defaultIcon == null) {
@SuppressWarnings("nls")
String msg = "Unable to find icon " + DEFAULT_CONSOLE_ICON + " in plugin " + CDT_MANAGEDBUILDER_UI_PLUGIN_ID;
ManagedBuilderCorePlugin.log(new Status(IStatus.ERROR, ManagedBuilderCorePlugin.PLUGIN_ID, msg));
}
console = CCorePlugin.getDefault().getConsole(extConsoleId, consoleId, consoleName, defaultIcon);
}
}
if (console == null) {
// that looks in extension points registry and won't find the id, this console is not shown
console = CCorePlugin.getDefault().getConsole(ManagedBuilderCorePlugin.PLUGIN_ID + ".console.hidden"); //$NON-NLS-1$
}
return console;
}
/**
* Get path to spec file which normally would be placed in workspace area.
* This value is used to replace macro ${INPUTS}.
*
* @param languageId - language ID.
* @return full path to the specs file.
*/
protected String getSpecFile(String languageId) {
String specExt = getSpecFileExtension(languageId);
String ext = ""; //$NON-NLS-1$
if (specExt != null) {
ext = '.' + specExt;
}
String specFileName = SPEC_FILE_BASE + ext;
IPath workingLocation = ManagedBuilderCorePlugin.getDefault().getStateLocation();
IPath fileLocation = workingLocation.append(specFileName);
specFile = new java.io.File(fileLocation.toOSString());
// will preserve spec file if it was already there otherwise will delete upon finishing
preserveSpecFile = specFile.exists();
if (!preserveSpecFile) {
try {
// In the typical case it is sufficient to have an empty file.
specFile.createNewFile();
} catch (IOException e) {
ManagedBuilderCorePlugin.log(e);
}
}
return fileLocation.toString();
}
/**
* Determine file extension by language id. This implementation retrieves first extension
* from the list as there could be multiple extensions associated with the given language.
* This value is used to replace macro ${EXT}.
*
* @param languageId - given language ID.
* @return file extension associated with the language or {@code null} if not found.
*/
protected String getSpecFileExtension(String languageId) {
String ext = null;
ILanguageDescriptor langDescriptor = LanguageManager.getInstance().getLanguageDescriptor(languageId);
if (langDescriptor != null) {
IContentType[] contentTypes = langDescriptor.getContentTypes();
if (contentTypes != null && contentTypes.length > 0) {
String[] fileExtensions = contentTypes[0].getFileSpecs(IContentType.FILE_EXTENSION_SPEC);
if (fileExtensions != null && fileExtensions.length > 0) {
ext = fileExtensions[0];
}
}
}
if (ext == null) {
ManagedBuilderCorePlugin.log(new Status(IStatus.ERROR, ManagedBuilderCorePlugin.PLUGIN_ID, "Unable to find file extension for language " + languageId)); //$NON-NLS-1$
}
return ext;
}
@Override
public Element serializeAttributes(Element parentElement) {
Element elementProvider = super.serializeAttributes(parentElement);
elementProvider.setAttribute(ATTR_CONSOLE, Boolean.toString(isConsoleEnabled));
return elementProvider;
}
@Override
public void loadAttributes(Element providerNode) {
super.loadAttributes(providerNode);
String consoleValue = XmlUtil.determineAttributeValue(providerNode, ATTR_CONSOLE);
if (consoleValue != null) {
isConsoleEnabled = Boolean.parseBoolean(consoleValue);
}
}
@Override
public void loadEntries(Element providerNode) {
super.loadEntries(providerNode);
if (!isEmpty()) {
isExecuted = true;
}
}
@Override
public boolean isEmpty() {
// treat provider that has been executed as not empty
// to let "Clear" button to restart the provider
return !isExecuted && super.isEmpty();
}
@Override
public void clear() {
super.clear();
isExecuted = false;
}
@Override
protected AbstractBuiltinSpecsDetector cloneShallow() throws CloneNotSupportedException {
AbstractBuiltinSpecsDetector clone = (AbstractBuiltinSpecsDetector) super.cloneShallow();
clone.isExecuted = false;
return clone;
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + (isConsoleEnabled ? 1231 : 1237);
result = prime * result + (isExecuted ? 1231 : 1237);
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (!(obj instanceof AbstractBuiltinSpecsDetector))
return false;
AbstractBuiltinSpecsDetector other = (AbstractBuiltinSpecsDetector) obj;
if (isConsoleEnabled != other.isConsoleEnabled)
return false;
if (isExecuted != other.isExecuted)
return false;
return true;
}
}

View file

@ -0,0 +1,84 @@
/*******************************************************************************
* Copyright (c) 2009, 2012 Andrew Gvozdev 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:
* Andrew Gvozdev - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.managedbuilder.language.settings.providers;
import org.eclipse.cdt.core.errorparsers.RegexErrorPattern;
import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsEditableProvider;
import org.eclipse.cdt.core.settings.model.ICSettingEntry;
/**
* Build command parser capable to parse gcc command in build output and generate
* language settings per file being compiled.
*
* @since 8.1
*/
public class GCCBuildCommandParser extends AbstractBuildCommandParser implements ILanguageSettingsEditableProvider {
@SuppressWarnings("nls")
static final AbstractOptionParser[] optionParsers = {
new IncludePathOptionParser("-I\\s*([\"'])(.*)\\1", "$2"),
new IncludePathOptionParser("-I\\s*([^\\s\"']*)", "$1"),
new IncludeFileOptionParser("-include\\s*([\"'])(.*)\\1", "$2"),
new IncludeFileOptionParser("-include\\s*([^\\s\"']*)", "$1"),
new MacroOptionParser("-D\\s*([\"'])([^=]*)(=(.*))?\\1", "$2", "$4"),
new MacroOptionParser("-D\\s*([^\\s=\"']*)=(\\\\([\"']))(.*?)\\2", "$1", "$3$4$3"),
new MacroOptionParser("-D\\s*([^\\s=\"']*)=([\"'])(.*?)\\2", "$1", "$3"),
new MacroOptionParser("-D\\s*([^\\s=\"']*)(=([^\\s\"']*))?", "$1", "$3"),
new MacroOptionParser("-U\\s*([^\\s=\"']*)", "$1", ICSettingEntry.UNDEFINED),
new MacroFileOptionParser("-macros\\s*([\"'])(.*)\\1", "$2"),
new MacroFileOptionParser("-macros\\s*([^\\s\"']*)", "$1"),
new LibraryPathOptionParser("-L\\s*([\"'])(.*)\\1", "$2"),
new LibraryPathOptionParser("-L\\s*([^\\s\"']*)", "$1"),
new LibraryFileOptionParser("-l\\s*([^\\s\"']*)", "lib$1.a"), };
@Override
protected AbstractOptionParser[] getOptionParsers() {
return optionParsers;
}
@Override
public GCCBuildCommandParser cloneShallow() throws CloneNotSupportedException {
return (GCCBuildCommandParser) super.cloneShallow();
}
@Override
public GCCBuildCommandParser clone() throws CloneNotSupportedException {
return (GCCBuildCommandParser) super.clone();
}
/**
* Error Parser which allows highlighting of output lines matching the patterns of this parser.
* Intended for better troubleshooting experience.
*/
public static class GCCBuildCommandPatternHighlighter extends AbstractBuildCommandParser.AbstractBuildCommandPatternHighlighter {
// ID of the parser taken from the existing extension point
private static final String GCC_BUILD_COMMAND_PARSER_EXT = "org.eclipse.cdt.managedbuilder.core.GCCBuildCommandParser"; //$NON-NLS-1$
/**
* Default constructor.
*/
public GCCBuildCommandPatternHighlighter() {
super(GCC_BUILD_COMMAND_PARSER_EXT);
}
@Override
public Object clone() throws CloneNotSupportedException {
GCCBuildCommandPatternHighlighter that = new GCCBuildCommandPatternHighlighter();
that.setId(getId());
that.setName(getName());
for (RegexErrorPattern pattern : getPatterns()) {
that.addPattern((RegexErrorPattern)pattern.clone());
}
return that;
}
}
}

View file

@ -0,0 +1,133 @@
/*******************************************************************************
* Copyright (c) 2009, 2012 Andrew Gvozdev 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:
* Andrew Gvozdev - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.managedbuilder.language.settings.providers;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsEditableProvider;
import org.eclipse.cdt.core.language.settings.providers.IWorkingDirectoryTracker;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICSettingEntry;
import org.eclipse.core.runtime.CoreException;
/**
* Language settings provider to detect built-in compiler settings for GCC compiler.
*
* @since 8.1
*/
public class GCCBuiltinSpecsDetector extends ToolchainBuiltinSpecsDetector implements ILanguageSettingsEditableProvider {
// ID must match the tool-chain definition in org.eclipse.cdt.managedbuilder.core.buildDefinitions extension point
private static final String GCC_TOOLCHAIN_ID = "cdt.managedbuild.toolchain.gnu.base"; //$NON-NLS-1$
private enum State {NONE, EXPECTING_LOCAL_INCLUDE, EXPECTING_SYSTEM_INCLUDE, EXPECTING_FRAMEWORKS}
private State state = State.NONE;
@SuppressWarnings("nls")
private static final AbstractOptionParser[] optionParsers = {
new IncludePathOptionParser("#include \"(\\S.*)\"", "$1", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY | ICSettingEntry.LOCAL),
new IncludePathOptionParser("#include <(\\S.*)>", "$1", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY),
new IncludePathOptionParser("#framework <(\\S.*)>", "$1", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY | ICSettingEntry.FRAMEWORKS_MAC),
new MacroOptionParser("#define\\s+(\\S*\\(.*?\\))\\s*(.*)", "$1", "$2", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY),
new MacroOptionParser("#define\\s+(\\S*)\\s*(\\S*)", "$1", "$2", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY),
};
@Override
protected String getToolchainId() {
return GCC_TOOLCHAIN_ID;
}
@Override
protected AbstractOptionParser[] getOptionParsers() {
return optionParsers;
}
/**
* Create a list from one item.
*/
private List<String> makeList(String line) {
List<String> list = new ArrayList<String>();
list.add(line);
return list;
}
@SuppressWarnings("nls")
@Override
protected List<String> parseOptions(String line) {
line = line.trim();
// contribution of -dD option
if (line.startsWith("#define")) {
return makeList(line);
}
// contribution of includes
if (line.equals("#include \"...\" search starts here:")) {
state = State.EXPECTING_LOCAL_INCLUDE;
} else if (line.equals("#include <...> search starts here:")) {
state = State.EXPECTING_SYSTEM_INCLUDE;
} else if (line.startsWith("End of search list.")) {
state = State.NONE;
} else if (line.equals("Framework search starts here:")) {
state = State.EXPECTING_FRAMEWORKS;
} else if (line.startsWith("End of framework search list.")) {
state = State.NONE;
} else if (state==State.EXPECTING_LOCAL_INCLUDE) {
// making that up for the parser to figure out
line = "#include \""+line+"\"";
return makeList(line);
} else {
String frameworkIndicator = "(framework directory)";
if (state==State.EXPECTING_SYSTEM_INCLUDE) {
// making that up for the parser to figure out
if (line.contains(frameworkIndicator)) {
line = "#framework <"+line.replace(frameworkIndicator, "").trim()+">";
} else {
line = "#include <"+line+">";
}
return makeList(line);
} else if (state==State.EXPECTING_FRAMEWORKS) {
// making that up for the parser to figure out
line = "#framework <"+line.replace(frameworkIndicator, "").trim()+">";
return makeList(line);
}
}
return null;
}
@Override
public void startup(ICConfigurationDescription cfgDescription, IWorkingDirectoryTracker cwdTracker) throws CoreException {
super.startup(cfgDescription, cwdTracker);
state = State.NONE;
}
@Override
public void shutdown() {
state = State.NONE;
super.shutdown();
}
@Override
public GCCBuiltinSpecsDetector cloneShallow() throws CloneNotSupportedException {
return (GCCBuiltinSpecsDetector) super.cloneShallow();
}
@Override
public GCCBuiltinSpecsDetector clone() throws CloneNotSupportedException {
return (GCCBuiltinSpecsDetector) super.clone();
}
}

View file

@ -0,0 +1,105 @@
/*******************************************************************************
* Copyright (c) 2009, 2012 Andrew Gvozdev 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:
* Andrew Gvozdev - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.managedbuilder.language.settings.providers;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.cdt.managedbuilder.core.IInputType;
import org.eclipse.cdt.managedbuilder.core.ITool;
import org.eclipse.cdt.managedbuilder.core.IToolChain;
import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;
import org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin;
/**
* Abstract parser capable to execute compiler command printing built-in compiler
* specs and parse built-in language settings out of it. The compiler to be used
* is taken from MBS tool-chain definition.
*
* @since 8.1
*/
public abstract class ToolchainBuiltinSpecsDetector extends AbstractBuiltinSpecsDetector {
private Map<String, ITool> toolMap = new HashMap<String, ITool>();
/**
* Concrete compiler specs detectors need to supply tool-chain ID.
*
* Tool-chain id must be supplied for global providers where we don't
* have configuration description to figure that out programmatically.
*/
protected abstract String getToolchainId();
/**
* Finds a tool handling given language in the tool-chain of the provider.
* This returns the first tool found.
*/
private ITool getTool(String languageId) {
ITool langTool = toolMap.get(languageId);
if (langTool != null) {
return langTool;
}
String toolchainId = getToolchainId();
for (IToolChain toolchain = ManagedBuildManager.getExtensionToolChain(toolchainId);toolchain != null;toolchain = toolchain.getSuperClass()) {
ITool tool = getTool(languageId, toolchain);
if (tool != null) {
return tool;
}
}
ManagedBuilderCorePlugin.error("Unable to find tool in toolchain=" + toolchainId + " for language=" + languageId); //$NON-NLS-1$ //$NON-NLS-2$
return null;
}
/**
* Finds a tool handling given language in the tool-chain.
* This returns the first tool found.
*/
private ITool getTool(String languageId, IToolChain toolchain) {
ITool[] tools = toolchain.getTools();
for (ITool tool : tools) {
IInputType[] inputTypes = tool.getInputTypes();
for (IInputType inType : inputTypes) {
String lang = inType.getLanguageId(tool);
if (languageId.equals(lang)) {
toolMap.put(languageId, tool);
return tool;
}
}
}
return null;
}
@Override
protected String getCompilerCommand(String languageId) {
ITool tool = getTool(languageId);
String compilerCommand = tool.getToolCommand();
if (compilerCommand.isEmpty()) {
ManagedBuilderCorePlugin.error("Unable to find compiler command in toolchain=" + getToolchainId()); //$NON-NLS-1$
}
return compilerCommand;
}
@Override
protected String getSpecFileExtension(String languageId) {
String ext = null;
ITool tool = getTool(languageId);
String[] srcFileExtensions = tool.getAllInputExtensions();
if (srcFileExtensions != null && srcFileExtensions.length > 0) {
ext = srcFileExtensions[0];
}
if (ext == null || ext.isEmpty()) {
ManagedBuilderCorePlugin.error("Unable to find file extension for language " + languageId); //$NON-NLS-1$
}
return ext;
}
}

View file

@ -0,0 +1,33 @@
/*******************************************************************************
* Copyright (c) 2010, 2011 Andrew Gvozdev 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:
* Andrew Gvozdev - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.internal.tests.filesystem.ram;
import java.net.URI;
import org.eclipse.cdt.core.EFSExtensionProvider;
/**
* Test stub to test EFSExtensionProvider mappings.
*
*/
public class MemoryEFSExtensionProvider extends EFSExtensionProvider {
public String getMappedPath(URI locationURI) {
String path = locationURI.getPath();
if (path.contains("/BeingMappedFrom/Folder")) {
return path.replaceFirst("/BeingMappedFrom/Folder", "/LocallyMappedTo/Folder");
}
return super.getMappedPath(locationURI);
}
}

View file

@ -240,6 +240,13 @@
</run>
</filesystem>
</extension>
<extension
point="org.eclipse.cdt.core.EFSExtensionProvider">
<EFSExtensionProvider
class="org.eclipse.cdt.core.internal.tests.filesystem.ram.MemoryEFSExtensionProvider"
scheme="mem">
</EFSExtensionProvider>
</extension>
<extension
id="RegexErrorParserId"
name="Test Plugin RegexErrorParser"

View file

@ -0,0 +1,38 @@
/*******************************************************************************
* Copyright (c) 2012, 2012 Andrew Gvozdev 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:
* Andrew Gvozdev - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.language.settings.providers;
import org.eclipse.cdt.core.IConsoleParser;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.core.runtime.CoreException;
/**
* Console parser interface extended to support language settings providers.
*
* @since 5.4
*/
public interface ICBuildOutputParser extends IConsoleParser {
/**
* Initialize console parser.
*
* @param cfgDescription - configuration description for the parser.
* @param cwdTracker - tracker to keep track of current working directory.
* @throws CoreException if anything goes wrong.
*/
public void startup(ICConfigurationDescription cfgDescription, IWorkingDirectoryTracker cwdTracker) throws CoreException;
@Override
public boolean processLine(String line);
@Override
public void shutdown();
}

View file

@ -0,0 +1,28 @@
/*******************************************************************************
* Copyright (c) 2012, 2012 Andrew Gvozdev 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:
* Andrew Gvozdev - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.language.settings.providers;
import java.net.URI;
/**
* Interface for console parsers able to track current working directory for build.
*
* @since 5.4
*/
public interface IWorkingDirectoryTracker {
/**
* Returns current working directory for the current build command as determined from
* build output.
*
* @return URI of current working directory or {@code null}.
*/
public URI getWorkingDirectoryURI();
}

View file

@ -330,9 +330,26 @@ public class LanguageSettingsManager {
/**
* Save language settings providers of the workspace (global providers) to persistent storage.
*
* @throws CoreException
* @throws CoreException if something goes wrong.
*/
public static void serializeLanguageSettingsWorkspace() throws CoreException {
LanguageSettingsProvidersSerializer.serializeLanguageSettingsWorkspace();
}
/**
* Save language settings providers of a project to persistent storage in a background job.
*
* @param prjDescription - project description of the project.
*/
public static void serializeLanguageSettingsInBackground(ICProjectDescription prjDescription) {
LanguageSettingsProvidersSerializer.serializeLanguageSettingsInBackground(prjDescription);
}
/**
* Save language settings providers of the workspace (global providers) to persistent storage
* in a background job.
*/
public static void serializeLanguageSettingsWorkspaceInBackground() {
LanguageSettingsProvidersSerializer.serializeLanguageSettingsWorkspaceInBackground();
}
}

View file

@ -258,6 +258,24 @@ public class LanguageSettingsSerializableProvider extends LanguageSettingsBasePr
return status;
}
/**
* Convenience method to persist language settings entries in background for the project or
* workspace as often-used operation.
* Note that configuration description is passed as an argument but the
* current implementation saves all configurations.
*
* @param cfgDescription - configuration description.
* If not {@code null}, all providers of the project are serialized.
* If {@code null}, global workspace providers are serialized.
*/
public void serializeLanguageSettingsInBackground(ICConfigurationDescription cfgDescription) {
if (cfgDescription != null) {
LanguageSettingsManager.serializeLanguageSettingsInBackground(cfgDescription.getProjectDescription());
} else {
LanguageSettingsManager.serializeLanguageSettingsWorkspaceInBackground();
}
}
/**
* Load provider from XML provider element.
* This is convenience method not intended to be overridden on purpose.

View file

@ -15,6 +15,9 @@ import java.util.ArrayList;
import java.util.List;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.internal.core.LocalProjectScope;
import org.eclipse.cdt.internal.core.language.settings.providers.LanguageSettingsExtensionManager;
import org.eclipse.cdt.internal.core.language.settings.providers.LanguageSettingsProvidersSerializer;
@ -82,6 +85,49 @@ public class ScannerDiscoveryLegacySupport {
}
}
/**
* Check if legacy Scanner Discovery in MBS should be active.
*/
private static boolean isMbsLanguageSettingsProviderOn(ICConfigurationDescription cfgDescription) {
if (cfgDescription instanceof ILanguageSettingsProvidersKeeper) {
List<ILanguageSettingsProvider> lsProviders = ((ILanguageSettingsProvidersKeeper) cfgDescription).getLanguageSettingProviders();
for (ILanguageSettingsProvider lsp : lsProviders) {
if (MBS_LANGUAGE_SETTINGS_PROVIDER_ID.equals(lsp.getId())) {
return true;
}
}
}
return false;
}
/**
* @noreference This is internal helper method to support compatibility with previous versions
* which is not intended to be referenced by clients.
*/
public static boolean isLegacyScannerDiscoveryOn(ICConfigurationDescription cfgDescription) {
IProject project = null;
if (cfgDescription != null) {
ICProjectDescription prjDescription = cfgDescription.getProjectDescription();
if (prjDescription != null) {
project = prjDescription.getProject();
}
}
return isLanguageSettingsProvidersFunctionalityEnabled(project) || isMbsLanguageSettingsProviderOn(cfgDescription);
}
/**
* @noreference This is internal helper method to support compatibility with previous versions
* which is not intended to be referenced by clients.
*/
public static boolean isLegacyScannerDiscoveryOn(IProject project) {
ICConfigurationDescription cfgDescription = null;
ICProjectDescription prjDescription = CoreModel.getDefault().getProjectDescription(project);
if (prjDescription != null) {
cfgDescription = prjDescription.getActiveConfiguration();
}
return isLanguageSettingsProvidersFunctionalityEnabled(project) || isMbsLanguageSettingsProviderOn(cfgDescription);
}
/**
* Return list containing MBS and User provider. Used to initialize for unaware tool-chains (backward compatibility).
*/

View file

@ -334,10 +334,8 @@ public class CDataUtil {
}
/**
* Convenience method to create {@link ICLanguageSettingEntry} depending on kind.
* Convenience method to create {@link ICSettingEntry} depending on kind.
* Note that this method keeps the entries in the pool to avoid proliferation of duplicates.
*
* Note that the method always returns {@link ICLanguageSettingEntry}.
*/
public static ICSettingEntry createEntry(int kind, String name, String value, IPath[] exclusionPatterns, int flags) {
return createEntry(kind, name, value, exclusionPatterns, flags, null, null, null);

View file

@ -36,6 +36,7 @@ import org.eclipse.cdt.core.settings.model.ICStorageElement;
import org.eclipse.cdt.internal.core.XmlUtil;
import org.eclipse.cdt.internal.core.settings.model.CConfigurationSpecSettings;
import org.eclipse.cdt.internal.core.settings.model.IInternalCCfgInfo;
import org.eclipse.cdt.internal.core.settings.model.SettingsModelMessages;
import org.eclipse.core.filesystem.URIUtil;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
@ -47,13 +48,16 @@ import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.ILock;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.osgi.util.NLS;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
@ -70,11 +74,16 @@ public class LanguageSettingsProvidersSerializer {
public static final String ELEM_PROVIDER = LanguageSettingsExtensionManager.ELEM_PROVIDER;
public static final String ELEM_LANGUAGE_SCOPE = LanguageSettingsExtensionManager.ELEM_LANGUAGE_SCOPE;
private static final String JOB_FAMILY_SERIALIZE_LANGUAGE_SETTINGS_PROJECT = "CDT_JOB_FAMILY_SERIALIZE_LANGUAGE_SETTINGS_PROJECT"; //$NON-NLS-1$
private static final String JOB_FAMILY_SERIALIZE_LANGUAGE_SETTINGS_WORKSPACE = "CDT_JOB_FAMILY_SERIALIZE_LANGUAGE_SETTINGS_WORKSPACE"; //$NON-NLS-1$
private static final String PREFERENCE_WORSPACE_PROVIDERS_SET = "language.settings.providers.workspace.prefs.toggle"; //$NON-NLS-1$
private static final String CPROJECT_STORAGE_MODULE = "org.eclipse.cdt.core.LanguageSettingsProviders"; //$NON-NLS-1$
private static final String STORAGE_WORKSPACE_LANGUAGE_SETTINGS = "language.settings.xml"; //$NON-NLS-1$
private static final String STORAGE_PROJECT_PATH = ".settings/language.settings.xml"; //$NON-NLS-1$
private static final int PROGRESS_MONITOR_SCALE = 100;
private static final int TICKS_SERIALIZING = 1 * PROGRESS_MONITOR_SCALE;
private static final String ELEM_PLUGIN = "plugin"; //$NON-NLS-1$
private static final String ELEM_EXTENSION = "extension"; //$NON-NLS-1$
private static final String ATTR_EXTENSION_POINT = "point"; //$NON-NLS-1$
@ -537,6 +546,46 @@ public class LanguageSettingsProvidersSerializer {
}
}
/**
* Save language settings providers of the workspace (global providers) to persistent storage
* in background.
*/
public static void serializeLanguageSettingsWorkspaceInBackground() {
Job[] jobs = Job.getJobManager().find(JOB_FAMILY_SERIALIZE_LANGUAGE_SETTINGS_WORKSPACE);
for (Job job : jobs) {
if (job.getState() == Job.WAITING) {
// do not schedule if there is serializing job in queue already
return;
}
}
Job job = new Job(SettingsModelMessages.getString("LanguageSettingsProvidersSerializer.SerializeJobName")) { //$NON-NLS-1$
@Override
protected IStatus run(IProgressMonitor monitor) {
try {
monitor.beginTask(SettingsModelMessages.getString("LanguageSettingsProvidersSerializer.SerializingForWorkspace"), //$NON-NLS-1$
TICKS_SERIALIZING);
serializeLanguageSettingsWorkspace();
monitor.worked(TICKS_SERIALIZING);
return Status.OK_STATUS;
} catch (Throwable e) {
String msg = "Internal error running job of serializing language settings in workspace"; //$NON-NLS-1$
return new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, msg, e);
} finally {
monitor.done();
}
}
@Override
public boolean belongsTo(Object family) {
return family == JOB_FAMILY_SERIALIZE_LANGUAGE_SETTINGS_WORKSPACE;
}
};
job.setRule(null);
job.schedule();
}
/**
* Load language settings for workspace.
*/
@ -811,6 +860,57 @@ public class LanguageSettingsProvidersSerializer {
}
}
/**
* Save language settings providers of a project to persistent storage in background.
*
* @param prjDescription - project description of the project.
*/
public static void serializeLanguageSettingsInBackground(final ICProjectDescription prjDescription) {
Job job = new Job(SettingsModelMessages.getString("LanguageSettingsProvidersSerializer.SerializeJobName")) { //$NON-NLS-1$
@Override
protected IStatus run(IProgressMonitor monitor) {
try {
monitor.beginTask(NLS.bind(SettingsModelMessages.getString("LanguageSettingsProvidersSerializer.SerializingForProject"), //$NON-NLS-1$
prjDescription.getName()), TICKS_SERIALIZING);
serializeLanguageSettings(prjDescription);
monitor.worked(TICKS_SERIALIZING);
return Status.OK_STATUS;
} catch (Throwable e) {
String msg = "Internal error running job of serializing language settings for project " + prjDescription.getName(); //$NON-NLS-1$
return new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, msg, e);
} finally {
monitor.done();
}
}
@Override
public boolean belongsTo(Object family) {
return family == JOB_FAMILY_SERIALIZE_LANGUAGE_SETTINGS_PROJECT;
}
};
ISchedulingRule rule = null;
IProject project = prjDescription.getProject();
if (project != null) {
IFile fileStorePrj = getStoreInProjectArea(project);
IContainer folder = fileStorePrj.getParent();
if (folder instanceof IFolder && !folder.exists()) {
try {
((IFolder) folder).create(true, true, null);
} catch (CoreException e) {
CCorePlugin.log(e);
}
}
if (folder.isAccessible()) {
rule = fileStorePrj;
}
}
if (rule == null) {
rule = ResourcesPlugin.getWorkspace().getRoot();
}
job.setRule(rule);
job.schedule();
}
/**
* Load language settings to the project description from XML.
*

View file

@ -51,6 +51,9 @@ ExtensionContainerFactory.4=invalid setting provider class specified
ExtensionContainerFactory.5=provider element not specified
LanguageSettingsBaseProvider.CanBeConfiguredOnlyOnce=LanguageSettingsBaseProvider can be configured only once
LanguageSettingsScannerInfoProvider.UnableToDetermineLanguage=Error getting ScannerInfo: Unable to determine language for resource {0}
LanguageSettingsProvidersSerializer.SerializeJobName=Serialize CDT language settings entries
LanguageSettingsProvidersSerializer.SerializingForProject="Serializing language settings for project {0}
LanguageSettingsProvidersSerializer.SerializingForWorkspace="Serializing language settings for global providers
SettingsContext.0=no project associated with the context
SettingsContext.1=can not accept the not-context project description

View file

@ -531,8 +531,10 @@ public class CCorePlugin extends Plugin {
* </code>
*
* @return CDT console adapter.
*
* @since 5.4
*/
private IConsole getConsole(String extConsoleId, String contextId, String name, URL iconUrl) {
public IConsole getConsole(String extConsoleId, String contextId, String name, URL iconUrl) {
try {
IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(CCorePlugin.PLUGIN_ID, "CBuildConsole"); //$NON-NLS-1$
if (extensionPoint != null) {

View file

@ -24,6 +24,7 @@ import java.util.Map;
import java.util.Vector;
import org.eclipse.cdt.core.errorparsers.ErrorParserNamedWrapper;
import org.eclipse.cdt.core.language.settings.providers.IWorkingDirectoryTracker;
import org.eclipse.cdt.core.resources.ACBuilder;
import org.eclipse.cdt.internal.core.Cygwin;
import org.eclipse.cdt.internal.core.IErrorMarkeredOutputStream;
@ -50,7 +51,7 @@ import org.osgi.service.prefs.BackingStoreException;
*
* @noextend This class is not intended to be subclassed by clients.
*/
public class ErrorParserManager extends OutputStream implements IConsoleParser {
public class ErrorParserManager extends OutputStream implements IConsoleParser, IWorkingDirectoryTracker {
/**
* The list of error parsers stored in .project for 3.X projects
* as key/value pair with key="org.eclipse.cdt.core.errorOutputParser"
@ -193,6 +194,7 @@ public class ErrorParserManager extends OutputStream implements IConsoleParser {
* @return the current URI location where the build is being performed
* @since 5.1
*/
@Override
public URI getWorkingDirectoryURI() {
if (!fDirectoryStack.isEmpty())
return fDirectoryStack.lastElement();

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2004, 2009 IBM Corporation and others.
* Copyright (c) 2004, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -12,10 +12,6 @@ package org.eclipse.cdt.core;
/**
* A basic interface for console parsers
*
* @author vhirsl
* @noextend This interface is not intended to be extended by clients.
* @noimplement This interface is not intended to be implemented by clients.
*/
public interface IConsoleParser {
/**

View file

@ -31,13 +31,23 @@ public class Cygwin {
* Check if cygwin path conversion utilities are available in the path.
*
* @param envPath - list of directories to search for cygwin utilities separated
* by path separator (format of environment variable $PATH).
* by path separator (format of environment variable $PATH)
* or {@code null} to use current $PATH.
* @return {@code true} if cygwin is available, {@code false} otherwise.
*/
public static boolean isAvailable(String envPath) {
return Platform.getOS().equals(Platform.OS_WIN32) && findCygpathLocation(envPath) != null;
}
/**
* Check if cygwin path conversion utilities are available in $PATH.
*
* @return {@code true} if cygwin is available, {@code false} otherwise.
*/
public static boolean isAvailable() {
return Platform.getOS().equals(Platform.OS_WIN32) && findCygpathLocation(null) != null;
}
/**
* Conversion from Cygwin path to Windows path.
*

View file

@ -17,3 +17,6 @@ objectFileName=Object File
profileName=XL C managed make per project scanner discovery profile
profileNameCPP=XL C++ managed make per project scanner discovery profile
XlcBuiltinSpecsDetectorName=CDT XLC Builtin Compiler Settings
XlcBuildCommandParserName=CDT XLC Build Output Parser

View file

@ -74,6 +74,25 @@
class="org.eclipse.cdt.make.xlc.core.scannerconfig.XlCSpecsConsoleParser">
</scannerInfoConsoleParser>
</scannerInfoProvider>
</extension>
<extension
point="org.eclipse.cdt.core.LanguageSettingsProvider">
<provider
class="org.eclipse.cdt.managedbuilder.xlc.core.XlcBuiltinSpecsDetector"
id="org.eclipse.cdt.managedbuilder.xlc.core.XlcBuiltinSpecsDetector"
name="%XlcBuiltinSpecsDetectorName"
parameter="${COMMAND} -E -V -P -w ${INPUTS}">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
<provider
class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuildCommandParser"
id="org.eclipse.cdt.managedbuilder.xlc.core.XlcBuildCommandParser"
name="%XlcBuildCommandParserName"
parameter="xl[cC]"
prefer-non-shared="true">
</provider>
</extension>
</plugin>

View file

@ -0,0 +1,86 @@
/*******************************************************************************
* Copyright (c) 2009, 2011 Andrew Gvozdev 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:
* Andrew Gvozdev - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.managedbuilder.xlc.core;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsEditableProvider;
import org.eclipse.cdt.core.settings.model.ICSettingEntry;
import org.eclipse.cdt.managedbuilder.language.settings.providers.ToolchainBuiltinSpecsDetector;
/**
* Language settings provider to detect built-in compiler settings for IBM XLC compiler.
*/
public class XlcBuiltinSpecsDetector extends ToolchainBuiltinSpecsDetector implements ILanguageSettingsEditableProvider {
// must match the toolchain definition in org.eclipse.cdt.managedbuilder.core.buildDefinitions extension point
private static final String XLC_TOOLCHAIN_ID = "cdt.managedbuild.toolchain.xlc.exe.debug"; //$NON-NLS-1$
private static final Pattern OPTIONS_PATTERN = Pattern.compile("-[^\\s\"']*(\\s*((\".*?\")|('.*?')|([^-\\s][^\\s]+)))?"); //$NON-NLS-1$
private static final int OPTION_GROUP = 0;
/* Sample output:
> xlC -E -V -P -w ~/tmp/spec.C
export XL_CONFIG=/etc/vac.cfg:xlC
/usr/vac/exe/xlCcpp /home/me/tmp/spec.C - -qc++=/usr/vacpp/include -D_AIX -D_AIX32 -D_AIX41 -D_AIX43 -D_AIX50 -D_AIX51 -D_AIX52 -D_IBMR2 -D_POWER -E -P -w -qlanglvl=ansi -qansialias
rm /tmp/xlcW0lt4Jia
rm /tmp/xlcW1lt4Jib
rm /tmp/xlcW2lt4Jic
*/
@SuppressWarnings("nls")
private static final AbstractOptionParser[] optionParsers = {
new IncludePathOptionParser("-I\\s*([\"'])(.*)\\1", "$2", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY | ICSettingEntry.LOCAL),
new IncludePathOptionParser("-I\\s*([^\\s\"']*)", "$1", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY),
new IncludePathOptionParser("-qc\\+\\+=\\s*([^\\s\"']*)", "$1", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY),
new MacroOptionParser("-D\\s*([\"'])([^=]*)(=(.*))?\\1", "$2", "$4", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY),
new MacroOptionParser("-D\\s*([^\\s=\"']*)=(\\\\([\"']))(.*?)\\2", "$1", "$3$4$3", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY),
new MacroOptionParser("-D\\s*([^\\s=\"']*)=([\"'])(.*?)\\2", "$1", "$3", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY),
new MacroOptionParser("-D\\s*([^\\s=\"']*)(=([^\\s\"']*))?", "$1", "$3", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY),
};
@Override
protected String getToolchainId() {
return XLC_TOOLCHAIN_ID;
}
@Override
protected AbstractOptionParser[] getOptionParsers() {
return optionParsers;
}
@Override
protected List<String> parseOptions(String line) {
List<String> options = new ArrayList<String>();
Matcher optionMatcher = OPTIONS_PATTERN.matcher(line);
while (optionMatcher.find()) {
String option = optionMatcher.group(OPTION_GROUP);
if (option!=null) {
options.add(option);
}
}
return options;
}
@Override
public XlcBuiltinSpecsDetector cloneShallow() throws CloneNotSupportedException {
return (XlcBuiltinSpecsDetector) super.cloneShallow();
}
@Override
public XlcBuiltinSpecsDetector clone() throws CloneNotSupportedException {
return (XlcBuiltinSpecsDetector) super.clone();
}
}