Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core.tests/META-INF/MANIFEST.MF2
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/language/settings/providers/tests/AllLanguageSettingsProvidersMBSTests.java1
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/language/settings/providers/tests/CompilationDatabaseParserTest.java924
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/META-INF/MANIFEST.MF5
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/plugin.properties1
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/plugin.xml6
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/language/settings/providers/CompilationDatabaseParser.java460
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/language/settings/providers/CompileCommand.java34
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/language/settings/providers/Messages.java37
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/language/settings/providers/messages.properties21
-rw-r--r--build/org.eclipse.cdt.managedbuilder.ui/META-INF/MANIFEST.MF2
-rw-r--r--build/org.eclipse.cdt.managedbuilder.ui/plugin.xml7
-rw-r--r--build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/language/settings/providers/CompilationDatabaseParserOptionPage.java295
-rw-r--r--build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/language/settings/providers/Messages.java32
-rw-r--r--build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/language/settings/providers/messages.properties19
-rw-r--r--releng/CDT.setup4
-rw-r--r--releng/org.eclipse.cdt.target/cdt.target4
17 files changed, 1850 insertions, 4 deletions
diff --git a/build/org.eclipse.cdt.managedbuilder.core.tests/META-INF/MANIFEST.MF b/build/org.eclipse.cdt.managedbuilder.core.tests/META-INF/MANIFEST.MF
index af5e610101c..1ba05c98949 100644
--- a/build/org.eclipse.cdt.managedbuilder.core.tests/META-INF/MANIFEST.MF
+++ b/build/org.eclipse.cdt.managedbuilder.core.tests/META-INF/MANIFEST.MF
@@ -14,6 +14,7 @@ Export-Package: org.eclipse.cdt.managedbuilder.core.tests,
org.eclipse.cdt.projectmodel.tests
Require-Bundle: org.eclipse.core.runtime,
org.junit,
+ org.junit.jupiter.api,
org.eclipse.core.resources,
org.eclipse.ui,
org.eclipse.ui.ide,
@@ -25,3 +26,4 @@ Require-Bundle: org.eclipse.core.runtime,
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Automatic-Module-Name: org.eclipse.cdt.managedbuilder.core.tests
+Import-Package: com.google.gson
diff --git a/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/language/settings/providers/tests/AllLanguageSettingsProvidersMBSTests.java b/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/language/settings/providers/tests/AllLanguageSettingsProvidersMBSTests.java
index 2a13429717c..e638ee210a1 100644
--- a/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/language/settings/providers/tests/AllLanguageSettingsProvidersMBSTests.java
+++ b/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/language/settings/providers/tests/AllLanguageSettingsProvidersMBSTests.java
@@ -32,5 +32,6 @@ public class AllLanguageSettingsProvidersMBSTests extends TestSuite {
addTestSuite(GCCBuildCommandParserTest.class);
addTestSuite(BuiltinSpecsDetectorTest.class);
addTestSuite(GCCBuiltinSpecsDetectorTest.class);
+ addTestSuite(CompilationDatabaseParserTest.class);
}
}
diff --git a/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/language/settings/providers/tests/CompilationDatabaseParserTest.java b/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/language/settings/providers/tests/CompilationDatabaseParserTest.java
new file mode 100644
index 00000000000..4a0490c26f9
--- /dev/null
+++ b/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/language/settings/providers/tests/CompilationDatabaseParserTest.java
@@ -0,0 +1,924 @@
+/*******************************************************************************
+ * Copyright (c) 2019 Marc-Andre Laperle.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.cdt.managedbuilder.language.settings.providers.tests;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.io.ByteArrayInputStream;
+import java.io.FileReader;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.dom.ast.gnu.cpp.GPPLanguage;
+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.LanguageSettingsManager;
+import org.eclipse.cdt.core.model.CoreModel;
+import org.eclipse.cdt.core.model.ICElement;
+import org.eclipse.cdt.core.model.ICProject;
+import org.eclipse.cdt.core.model.ITranslationUnit;
+import org.eclipse.cdt.core.settings.model.CIncludePathEntry;
+import org.eclipse.cdt.core.settings.model.CMacroEntry;
+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.util.CDataUtil;
+import org.eclipse.cdt.core.testplugin.ResourceHelper;
+import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
+import org.eclipse.cdt.internal.core.language.settings.providers.LanguageSettingsProvidersSerializer;
+import org.eclipse.cdt.managedbuilder.internal.language.settings.providers.CompilationDatabaseParser;
+import org.eclipse.cdt.managedbuilder.internal.language.settings.providers.CompileCommand;
+import org.eclipse.cdt.managedbuilder.language.settings.providers.AbstractBuildCommandParser;
+import org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuildCommandParser;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.jobs.Job;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonSyntaxException;
+
+/**
+ * Test cases to test CompilationDatabaseParser (compile_commands.json).
+ */
+public class CompilationDatabaseParserTest extends BaseTestCase {
+ private static final String COMPILATION_DATABASE_PARSER_EXT = "org.eclipse.cdt.managedbuilder.core.CompilationDatabaseParser"; //$NON-NLS-1$
+ private static final String GCC_BUILD_COMMAND_PARSER_EXT = "org.eclipse.cdt.managedbuilder.core.GCCBuildCommandParser"; //$NON-NLS-1$
+
+ private static final String ATTR_CDB_PATH = "cdb-path"; //$NON-NLS-1$
+ private static final String ATTR_BUILD_PARSER_ID = "build-parser-id"; //$NON-NLS-1$
+ private static final String ATTR_CDB_MODIFIED_TIME = "cdb-modified-time"; //$NON-NLS-1$
+ private static final String ATTR_EXCLUDE_FILES = "exclude-files"; //$NON-NLS-1$
+
+ private IFile fCdbFile;
+ private IFile fSourceFile;
+ private IFile fSourceFile2;
+ private IFile fOutsideCdbSourceFile;
+ private IProject fProject;
+ private IFolder fFolder;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ try {
+ joingLanguageSettingsJobs();
+ } catch (Exception e) {
+ // ignore
+ }
+ super.tearDown();
+ }
+
+ private void createTestProject() throws Exception {
+ createTestProject(true, true, true, true, true);
+ }
+
+ private void createTestProject(boolean useAbsoluteSourcePath, boolean haveCommandDir, boolean validCommandDir,
+ boolean haveCommandLine, boolean validCommandLine) throws Exception {
+ fProject = ResourceHelper.createCDTProjectWithConfig(getName());
+ fFolder = ResourceHelper.createFolder(fProject, "folder");
+
+ IFile sourceFile = fFolder.getFile("test.cpp");
+ if (sourceFile.exists()) {
+ sourceFile.delete(true, null);
+ }
+
+ IFile sourceFile2 = fProject.getFile("test.cpp");
+ if (sourceFile2.exists()) {
+ sourceFile2.delete(true, null);
+ }
+
+ fSourceFile = ResourceHelper.createFile(sourceFile, "//comment");
+ fSourceFile2 = ResourceHelper.createFile(sourceFile2, "//comment2");
+
+ IFile outsideSourceFile = fFolder.getFile("outside.cpp");
+ if (outsideSourceFile.exists()) {
+ outsideSourceFile.delete(true, null);
+ }
+ fOutsideCdbSourceFile = ResourceHelper.createFile(outsideSourceFile, "//comment");
+
+ IFile file = fProject.getFile("compile_commands.json");
+ if (file.exists()) {
+ file.delete(true, null);
+ }
+
+ // Command for proj/folder/test.cpp
+ CompileCommand command = new CompileCommand();
+ if (haveCommandDir) {
+ if (validCommandDir)
+ command.directory = fSourceFile.getParent().getLocation().toOSString();
+ else
+ command.directory = "foo";
+ }
+ String sourceFilePath = fSourceFile.getLocation().toOSString();
+ if (!useAbsoluteSourcePath) {
+ sourceFilePath = fSourceFile.getLocation().makeRelativeTo(fSourceFile.getParent().getLocation())
+ .toOSString();
+ }
+ command.file = sourceFilePath;
+ if (haveCommandLine) {
+ if (validCommandLine)
+ command.command = "g++ -I" + fFolder.getLocation().toOSString() + " -DFOO=2 " + sourceFilePath;
+ else
+ command.command = "foo";
+ }
+
+ // Command for proj/test.cpp
+ CompileCommand command2 = new CompileCommand();
+ if (haveCommandDir) {
+ if (validCommandDir)
+ command2.directory = fSourceFile2.getParent().getLocation().toOSString();
+ else
+ command2.directory = "foo";
+ }
+ String sourceFilePath2 = fSourceFile2.getLocation().toOSString();
+ if (!useAbsoluteSourcePath) {
+ sourceFilePath2 = fSourceFile2.getLocation().makeRelativeTo(fSourceFile2.getParent().getLocation())
+ .toOSString();
+ }
+ command2.file = sourceFilePath2;
+ if (haveCommandLine) {
+ if (validCommandLine)
+ command2.command = "g++ -I" + fFolder.getLocation().toOSString() + " -DFOO=3 " + sourceFilePath2;
+ else
+ command2.command = "foo";
+ }
+
+ CompileCommand[] commands = new CompileCommand[2];
+ commands[0] = command;
+ commands[1] = command2;
+
+ String json = new Gson().toJson(commands);
+ fCdbFile = ResourceHelper.createFile(file, json);
+
+ ICConfigurationDescription cfgDescription = getConfigurationDescription(fProject, true);
+ GCCBuildCommandParser buildCommandParser = (GCCBuildCommandParser) LanguageSettingsManager
+ .getExtensionProviderCopy(GCC_BUILD_COMMAND_PARSER_EXT, true);
+ assertTrue(cfgDescription instanceof ILanguageSettingsProvidersKeeper);
+ List<ILanguageSettingsProvider> providers = new ArrayList<>();
+ providers.add(buildCommandParser);
+ ((ILanguageSettingsProvidersKeeper) cfgDescription).setLanguageSettingProviders(providers);
+ CoreModel.getDefault().setProjectDescription(cfgDescription.getProjectDescription().getProject(),
+ cfgDescription.getProjectDescription());
+ }
+
+ private void joingLanguageSettingsJobs() throws InterruptedException {
+ Job.getJobManager().join(CompilationDatabaseParser.JOB_FAMILY_COMPILATION_DATABASE_PARSER, null);
+ Job.getJobManager().join(AbstractBuildCommandParser.JOB_FAMILY_BUILD_COMMAND_PARSER, null);
+ Job.getJobManager().join(LanguageSettingsProvidersSerializer.JOB_FAMILY_SERIALIZE_LANGUAGE_SETTINGS_PROJECT,
+ null);
+ Job.getJobManager().join(LanguageSettingsProvidersSerializer.JOB_FAMILY_SERIALIZE_LANGUAGE_SETTINGS_WORKSPACE,
+ null);
+ }
+
+ /**
+ * Helper method to fetch a configuration description.
+ */
+ private ICConfigurationDescription getConfigurationDescription(IProject project, boolean writable) {
+ CoreModel coreModel = CoreModel.getDefault();
+ ICProjectDescriptionManager mngr = coreModel.getProjectDescriptionManager();
+ // project description
+ ICProjectDescription projectDescription = mngr.getProjectDescription(project, writable);
+ assertNotNull(projectDescription);
+ assertEquals(1, projectDescription.getConfigurations().length);
+ // configuration description
+ ICConfigurationDescription[] cfgDescriptions = projectDescription.getConfigurations();
+ return cfgDescriptions[0];
+ }
+
+ private void addLanguageSettingsProvider(ILanguageSettingsProvider provider) throws CoreException {
+ ICConfigurationDescription cfgDescription = getConfigurationDescription(fProject, true);
+ List<ILanguageSettingsProvider> providers = new ArrayList<>(
+ ((ILanguageSettingsProvidersKeeper) cfgDescription).getLanguageSettingProviders());
+ providers.add(provider);
+ ((ILanguageSettingsProvidersKeeper) cfgDescription).setLanguageSettingProviders(providers);
+ CoreModel.getDefault().setProjectDescription(cfgDescription.getProjectDescription().getProject(),
+ cfgDescription.getProjectDescription());
+ }
+
+ private CompilationDatabaseParser getCompilationDatabaseParser() throws CoreException {
+ ICConfigurationDescription cfgDescription = getConfigurationDescription(fProject, false);
+ List<ILanguageSettingsProvider> settingProviders = ((ILanguageSettingsProvidersKeeper) cfgDescription)
+ .getLanguageSettingProviders();
+ for (ILanguageSettingsProvider languageSettingsProvider : settingProviders) {
+ if (languageSettingsProvider instanceof CompilationDatabaseParser) {
+ return (CompilationDatabaseParser) languageSettingsProvider;
+ }
+ }
+
+ return null;
+ }
+
+ private void assertExpectedEntries(CompilationDatabaseParser parser) {
+ assertFalse(parser.isEmpty());
+ ICConfigurationDescription resCfgDescription = getConfigurationDescription(fProject, false);
+ List<ICLanguageSettingEntry> entries = parser.getSettingEntries(resCfgDescription, fSourceFile, GPPLanguage.ID);
+
+ CIncludePathEntry expected = new CIncludePathEntry("/${ProjName}/folder",
+ CIncludePathEntry.VALUE_WORKSPACE_PATH);
+ CIncludePathEntry entry = (CIncludePathEntry) entries.get(0);
+ assertEquals(expected.getName(), entry.getName());
+ assertEquals(expected.getValue(), entry.getValue());
+ assertEquals(expected.getKind(), entry.getKind());
+ assertEquals(expected.getFlags(), entry.getFlags());
+ assertEquals(expected, entry);
+
+ assertEquals(new CMacroEntry("FOO", "2", 0), entries.get(1));
+
+ entries = parser.getSettingEntries(resCfgDescription, fSourceFile2, GPPLanguage.ID);
+
+ entry = (CIncludePathEntry) entries.get(0);
+ assertEquals(expected.getName(), entry.getName());
+ assertEquals(expected.getValue(), entry.getValue());
+ assertEquals(expected.getKind(), entry.getKind());
+ assertEquals(expected.getFlags(), entry.getFlags());
+ assertEquals(expected, entry);
+
+ assertEquals(new CMacroEntry("FOO", "3", 0), entries.get(1));
+ }
+
+ public void testParseCDB_WritableConfigDesc() throws Exception {
+ createTestProject();
+
+ ICProject cProject = CCorePlugin.getDefault().getCoreModel().create(fProject);
+ ICElement ce = CCorePlugin.getDefault().getCoreModel().create(fOutsideCdbSourceFile.getFullPath());
+ ITranslationUnit tu = (ITranslationUnit) ce;
+ assertFalse(
+ CDataUtil.isExcluded(tu.getPath(), getConfigurationDescription(fProject, false).getSourceEntries()));
+
+ CompilationDatabaseParser parser = (CompilationDatabaseParser) LanguageSettingsManager
+ .getExtensionProviderCopy(COMPILATION_DATABASE_PARSER_EXT, true);
+ assertTrue(parser.isEmpty());
+ parser.setBuildParserId(GCC_BUILD_COMMAND_PARSER_EXT);
+ parser.setCompilationDataBasePath(fCdbFile.getLocation());
+ addLanguageSettingsProvider(parser);
+
+ ICConfigurationDescription cfgDescription = getConfigurationDescription(fProject, true);
+
+ parser.processCompileCommandsFile(null, cfgDescription);
+ assertFalse(parser.isEmpty());
+ CoreModel.getDefault().setProjectDescription(cfgDescription.getProjectDescription().getProject(),
+ cfgDescription.getProjectDescription());
+ joingLanguageSettingsJobs();
+
+ ICConfigurationDescription resCfgDescription = getConfigurationDescription(fProject, false);
+ assertExpectedEntries(parser);
+
+ assertFalse(CDataUtil.isExcluded(tu.getPath(), resCfgDescription.getSourceEntries()));
+ }
+
+ public void testParseCDB_ReadonlyConfigDesc() throws Exception {
+ createTestProject();
+
+ ICProject cProject = CCorePlugin.getDefault().getCoreModel().create(fProject);
+ ICElement ce = CCorePlugin.getDefault().getCoreModel().create(fOutsideCdbSourceFile.getFullPath());
+ ITranslationUnit tu = (ITranslationUnit) ce;
+ assertFalse(
+ CDataUtil.isExcluded(tu.getPath(), getConfigurationDescription(fProject, false).getSourceEntries()));
+
+ CompilationDatabaseParser parser = (CompilationDatabaseParser) LanguageSettingsManager
+ .getExtensionProviderCopy(COMPILATION_DATABASE_PARSER_EXT, true);
+ assertTrue(parser.isEmpty());
+ parser.setBuildParserId(GCC_BUILD_COMMAND_PARSER_EXT);
+ parser.setCompilationDataBasePath(fCdbFile.getLocation());
+ addLanguageSettingsProvider(parser);
+
+ ICConfigurationDescription cfgDescription = getConfigurationDescription(fProject, false);
+
+ parser.processCompileCommandsFile(null, cfgDescription);
+ // processCompileCommandsFile restarts itself in a WorkspaceJob with a writable config desc so we have to wait for the job.
+ joingLanguageSettingsJobs();
+
+ ICConfigurationDescription resCfgDescription = getConfigurationDescription(fProject, false);
+ assertExpectedEntries(getCompilationDatabaseParser());
+
+ assertFalse(CDataUtil.isExcluded(tu.getPath(), resCfgDescription.getSourceEntries()));
+ }
+
+ public void testParseCDB_WithExclusions() throws Exception {
+ createTestProject();
+
+ ICProject cProject = CCorePlugin.getDefault().getCoreModel().create(fProject);
+ ICElement ce = CCorePlugin.getDefault().getCoreModel().create(fOutsideCdbSourceFile.getFullPath());
+ ITranslationUnit tu = (ITranslationUnit) ce;
+ assertFalse(
+ CDataUtil.isExcluded(tu.getPath(), getConfigurationDescription(fProject, false).getSourceEntries()));
+
+ CompilationDatabaseParser parser = (CompilationDatabaseParser) LanguageSettingsManager
+ .getExtensionProviderCopy(COMPILATION_DATABASE_PARSER_EXT, true);
+ assertTrue(parser.isEmpty());
+ parser.setBuildParserId(GCC_BUILD_COMMAND_PARSER_EXT);
+ parser.setCompilationDataBasePath(fCdbFile.getLocation());
+ parser.setExcludeFiles(true);
+ addLanguageSettingsProvider(parser);
+
+ ICConfigurationDescription cfgDescription = getConfigurationDescription(fProject, true);
+
+ parser.processCompileCommandsFile(null, cfgDescription);
+ CoreModel.getDefault().setProjectDescription(cfgDescription.getProjectDescription().getProject(),
+ cfgDescription.getProjectDescription());
+ joingLanguageSettingsJobs();
+
+ assertExpectedEntries(parser);
+
+ ICConfigurationDescription resCfgDescription = getConfigurationDescription(fProject, false);
+ assertTrue(CDataUtil.isExcluded(tu.getPath(), resCfgDescription.getSourceEntries()));
+ }
+
+ public void testParseCDB_ReadonlyConfigDescWithExclusions() throws Exception {
+ createTestProject();
+
+ ICProject cProject = CCorePlugin.getDefault().getCoreModel().create(fProject);
+ ICElement ce = CCorePlugin.getDefault().getCoreModel().create(fOutsideCdbSourceFile.getFullPath());
+ ITranslationUnit tu = (ITranslationUnit) ce;
+ assertFalse(
+ CDataUtil.isExcluded(tu.getPath(), getConfigurationDescription(fProject, false).getSourceEntries()));
+
+ CompilationDatabaseParser parser = (CompilationDatabaseParser) LanguageSettingsManager
+ .getExtensionProviderCopy(COMPILATION_DATABASE_PARSER_EXT, true);
+ assertTrue(parser.isEmpty());
+ parser.setBuildParserId(GCC_BUILD_COMMAND_PARSER_EXT);
+ parser.setCompilationDataBasePath(fCdbFile.getLocation());
+ parser.setExcludeFiles(true);
+ addLanguageSettingsProvider(parser);
+
+ ICConfigurationDescription cfgDescription = getConfigurationDescription(fProject, false);
+
+ parser.processCompileCommandsFile(null, cfgDescription);
+ // processCompileCommandsFile restarts itself in a WorkspaceJob with a writable config desc so we have to wait for the job.
+ joingLanguageSettingsJobs();
+
+ assertExpectedEntries(getCompilationDatabaseParser());
+
+ ICConfigurationDescription resCfgDescription = getConfigurationDescription(fProject, false);
+ assertTrue(CDataUtil.isExcluded(tu.getPath(), resCfgDescription.getSourceEntries()));
+ }
+
+ public void testParseCDB_NoBuildCommandParser() throws Exception {
+ createTestProject();
+
+ ICProject cProject = CCorePlugin.getDefault().getCoreModel().create(fProject);
+ ICElement ce = CCorePlugin.getDefault().getCoreModel().create(fOutsideCdbSourceFile.getFullPath());
+ ITranslationUnit tu = (ITranslationUnit) ce;
+ assertFalse(
+ CDataUtil.isExcluded(tu.getPath(), getConfigurationDescription(fProject, false).getSourceEntries()));
+
+ CompilationDatabaseParser parser = (CompilationDatabaseParser) LanguageSettingsManager
+ .getExtensionProviderCopy(COMPILATION_DATABASE_PARSER_EXT, true);
+ assertTrue(parser.isEmpty());
+ parser.setCompilationDataBasePath(fCdbFile.getLocation());
+ parser.setExcludeFiles(true);
+ addLanguageSettingsProvider(parser);
+
+ ICConfigurationDescription cfgDescription = getConfigurationDescription(fProject, true);
+
+ assertThrows(CoreException.class, () -> parser.processCompileCommandsFile(null, cfgDescription));
+ CoreModel.getDefault().setProjectDescription(cfgDescription.getProjectDescription().getProject(),
+ cfgDescription.getProjectDescription());
+ joingLanguageSettingsJobs();
+
+ ICConfigurationDescription resCfgDescription = getConfigurationDescription(fProject, false);
+ CompilationDatabaseParser resultParser = getCompilationDatabaseParser();
+ assertTrue(resultParser.isEmpty());
+ List<ICLanguageSettingEntry> entries = resultParser.getSettingEntries(resCfgDescription, fSourceFile,
+ GPPLanguage.ID);
+ assertTrue(entries == null);
+ assertFalse(CDataUtil.isExcluded(tu.getPath(), resCfgDescription.getSourceEntries()));
+ }
+
+ public void testParseCDB_InvalidBuildCommandParser() throws Exception {
+ createTestProject();
+
+ ICProject cProject = CCorePlugin.getDefault().getCoreModel().create(fProject);
+ ICElement ce = CCorePlugin.getDefault().getCoreModel().create(fOutsideCdbSourceFile.getFullPath());
+ ITranslationUnit tu = (ITranslationUnit) ce;
+ assertFalse(
+ CDataUtil.isExcluded(tu.getPath(), getConfigurationDescription(fProject, false).getSourceEntries()));
+
+ CompilationDatabaseParser parser = (CompilationDatabaseParser) LanguageSettingsManager
+ .getExtensionProviderCopy(COMPILATION_DATABASE_PARSER_EXT, true);
+ assertTrue(parser.isEmpty());
+ parser.setBuildParserId(GCC_BUILD_COMMAND_PARSER_EXT + "foo");
+ parser.setCompilationDataBasePath(fCdbFile.getLocation());
+ parser.setExcludeFiles(true);
+ addLanguageSettingsProvider(parser);
+
+ ICConfigurationDescription cfgDescription = getConfigurationDescription(fProject, true);
+
+ assertThrows(CoreException.class, () -> parser.processCompileCommandsFile(null, cfgDescription));
+ CoreModel.getDefault().setProjectDescription(cfgDescription.getProjectDescription().getProject(),
+ cfgDescription.getProjectDescription());
+ joingLanguageSettingsJobs();
+
+ ICConfigurationDescription resCfgDescription = getConfigurationDescription(fProject, false);
+ CompilationDatabaseParser resultParser = getCompilationDatabaseParser();
+ assertTrue(resultParser.isEmpty());
+ List<ICLanguageSettingEntry> entries = resultParser.getSettingEntries(resCfgDescription, fSourceFile,
+ GPPLanguage.ID);
+ assertTrue(entries == null);
+ assertFalse(CDataUtil.isExcluded(tu.getPath(), resCfgDescription.getSourceEntries()));
+ }
+
+ public void testParseCDB_NonExistantCDB() throws Exception {
+ createTestProject();
+
+ ICProject cProject = CCorePlugin.getDefault().getCoreModel().create(fProject);
+ ICElement ce = CCorePlugin.getDefault().getCoreModel().create(fOutsideCdbSourceFile.getFullPath());
+ ITranslationUnit tu = (ITranslationUnit) ce;
+ assertFalse(
+ CDataUtil.isExcluded(tu.getPath(), getConfigurationDescription(fProject, false).getSourceEntries()));
+
+ CompilationDatabaseParser parser = (CompilationDatabaseParser) LanguageSettingsManager
+ .getExtensionProviderCopy(COMPILATION_DATABASE_PARSER_EXT, true);
+ assertTrue(parser.isEmpty());
+ parser.setBuildParserId(GCC_BUILD_COMMAND_PARSER_EXT);
+ parser.setCompilationDataBasePath(new Path("/testParseCDB_NonExistantCDB"));
+ parser.setExcludeFiles(true);
+ addLanguageSettingsProvider(parser);
+
+ ICConfigurationDescription cfgDescription = getConfigurationDescription(fProject, true);
+
+ assertThrows(CoreException.class, () -> parser.processCompileCommandsFile(null, cfgDescription));
+ CoreModel.getDefault().setProjectDescription(cfgDescription.getProjectDescription().getProject(),
+ cfgDescription.getProjectDescription());
+ joingLanguageSettingsJobs();
+
+ ICConfigurationDescription resCfgDescription = getConfigurationDescription(fProject, false);
+ CompilationDatabaseParser resultParser = getCompilationDatabaseParser();
+ assertTrue(resultParser.isEmpty());
+ List<ICLanguageSettingEntry> entries = resultParser.getSettingEntries(resCfgDescription, fSourceFile,
+ GPPLanguage.ID);
+ assertTrue(entries == null);
+ assertFalse(CDataUtil.isExcluded(tu.getPath(), resCfgDescription.getSourceEntries()));
+ }
+
+ public void testParseCDB_EmptyCDBPath() throws Exception {
+ createTestProject();
+
+ ICProject cProject = CCorePlugin.getDefault().getCoreModel().create(fProject);
+ ICElement ce = CCorePlugin.getDefault().getCoreModel().create(fOutsideCdbSourceFile.getFullPath());
+ ITranslationUnit tu = (ITranslationUnit) ce;
+ assertFalse(
+ CDataUtil.isExcluded(tu.getPath(), getConfigurationDescription(fProject, false).getSourceEntries()));
+
+ CompilationDatabaseParser parser = (CompilationDatabaseParser) LanguageSettingsManager
+ .getExtensionProviderCopy(COMPILATION_DATABASE_PARSER_EXT, true);
+ assertTrue(parser.isEmpty());
+ parser.setBuildParserId(GCC_BUILD_COMMAND_PARSER_EXT);
+ parser.setCompilationDataBasePath(new Path(""));
+ parser.setExcludeFiles(true);
+ addLanguageSettingsProvider(parser);
+
+ ICConfigurationDescription cfgDescription = getConfigurationDescription(fProject, true);
+
+ assertThrows(CoreException.class, () -> parser.processCompileCommandsFile(null, cfgDescription));
+ CoreModel.getDefault().setProjectDescription(cfgDescription.getProjectDescription().getProject(),
+ cfgDescription.getProjectDescription());
+ joingLanguageSettingsJobs();
+
+ ICConfigurationDescription resCfgDescription = getConfigurationDescription(fProject, false);
+ CompilationDatabaseParser resultParser = getCompilationDatabaseParser();
+ assertTrue(resultParser.isEmpty());
+ List<ICLanguageSettingEntry> entries = resultParser.getSettingEntries(resCfgDescription, fSourceFile,
+ GPPLanguage.ID);
+ assertTrue(entries == null);
+ assertFalse(CDataUtil.isExcluded(tu.getPath(), resCfgDescription.getSourceEntries()));
+ }
+
+ public void testParseCDB_DirectoryCDBPath() throws Exception {
+ createTestProject();
+
+ ICProject cProject = CCorePlugin.getDefault().getCoreModel().create(fProject);
+ ICElement ce = CCorePlugin.getDefault().getCoreModel().create(fOutsideCdbSourceFile.getFullPath());
+ ITranslationUnit tu = (ITranslationUnit) ce;
+ assertFalse(
+ CDataUtil.isExcluded(tu.getPath(), getConfigurationDescription(fProject, false).getSourceEntries()));
+
+ CompilationDatabaseParser parser = (CompilationDatabaseParser) LanguageSettingsManager
+ .getExtensionProviderCopy(COMPILATION_DATABASE_PARSER_EXT, true);
+ assertTrue(parser.isEmpty());
+ parser.setBuildParserId(GCC_BUILD_COMMAND_PARSER_EXT);
+ parser.setCompilationDataBasePath(fCdbFile.getParent().getLocation());
+ parser.setExcludeFiles(true);
+ addLanguageSettingsProvider(parser);
+
+ ICConfigurationDescription cfgDescription = getConfigurationDescription(fProject, true);
+
+ assertThrows(CoreException.class, () -> parser.processCompileCommandsFile(null, cfgDescription));
+ CoreModel.getDefault().setProjectDescription(cfgDescription.getProjectDescription().getProject(),
+ cfgDescription.getProjectDescription());
+ joingLanguageSettingsJobs();
+
+ ICConfigurationDescription resCfgDescription = getConfigurationDescription(fProject, false);
+ CompilationDatabaseParser resultParser = getCompilationDatabaseParser();
+ assertTrue(resultParser.isEmpty());
+ List<ICLanguageSettingEntry> entries = resultParser.getSettingEntries(resCfgDescription, fSourceFile,
+ GPPLanguage.ID);
+ assertTrue(entries == null);
+ assertFalse(CDataUtil.isExcluded(tu.getPath(), resCfgDescription.getSourceEntries()));
+ }
+
+ public void testParseCDB_InvalidJson() throws Exception {
+ createTestProject();
+
+ ICProject cProject = CCorePlugin.getDefault().getCoreModel().create(fProject);
+ ICElement ce = CCorePlugin.getDefault().getCoreModel().create(fOutsideCdbSourceFile.getFullPath());
+ ITranslationUnit tu = (ITranslationUnit) ce;
+ assertFalse(
+ CDataUtil.isExcluded(tu.getPath(), getConfigurationDescription(fProject, false).getSourceEntries()));
+
+ //Make the Json invalid
+ String cdbOsString = fCdbFile.getLocation().toOSString();
+ Files.write(Paths.get(cdbOsString), new byte[] { 'f', 'o', 'o' });
+ try (FileReader reader = new FileReader(cdbOsString)) {
+ Gson gson = new Gson();
+ CompileCommand[] compileCommands = gson.fromJson(reader, CompileCommand[].class);
+ assertTrue("Json should have been invalid and thrown an JsonSyntaxException", false);
+ } catch (JsonSyntaxException e) {
+
+ } catch (Exception e) {
+ assertTrue("Json should have been invalid and thrown an JsonSyntaxException", false);
+ }
+
+ CompilationDatabaseParser parser = (CompilationDatabaseParser) LanguageSettingsManager
+ .getExtensionProviderCopy(COMPILATION_DATABASE_PARSER_EXT, true);
+ assertTrue(parser.isEmpty());
+ parser.setBuildParserId(GCC_BUILD_COMMAND_PARSER_EXT);
+ parser.setCompilationDataBasePath(fCdbFile.getLocation());
+ parser.setExcludeFiles(true);
+ addLanguageSettingsProvider(parser);
+
+ ICConfigurationDescription cfgDescription = getConfigurationDescription(fProject, true);
+
+ assertThrows(CoreException.class, () -> parser.processCompileCommandsFile(null, cfgDescription));
+
+ CoreModel.getDefault().setProjectDescription(cfgDescription.getProjectDescription().getProject(),
+ cfgDescription.getProjectDescription());
+ joingLanguageSettingsJobs();
+
+ ICConfigurationDescription resCfgDescription = getConfigurationDescription(fProject, false);
+ CompilationDatabaseParser resultParser = getCompilationDatabaseParser();
+ assertTrue(resultParser.isEmpty());
+ List<ICLanguageSettingEntry> entries = resultParser.getSettingEntries(resCfgDescription, fSourceFile,
+ GPPLanguage.ID);
+ assertTrue(entries == null);
+ assertFalse(CDataUtil.isExcluded(tu.getPath(), resCfgDescription.getSourceEntries()));
+ }
+
+ public void testParseCDB_RelativePaths() throws Exception {
+ createTestProject(false, true, true, true, true);
+
+ ICProject cProject = CCorePlugin.getDefault().getCoreModel().create(fProject);
+ ICElement ce = CCorePlugin.getDefault().getCoreModel().create(fOutsideCdbSourceFile.getFullPath());
+ ITranslationUnit tu = (ITranslationUnit) ce;
+ assertFalse(
+ CDataUtil.isExcluded(tu.getPath(), getConfigurationDescription(fProject, false).getSourceEntries()));
+
+ CompilationDatabaseParser parser = (CompilationDatabaseParser) LanguageSettingsManager
+ .getExtensionProviderCopy(COMPILATION_DATABASE_PARSER_EXT, true);
+ assertTrue(parser.isEmpty());
+ parser.setBuildParserId(GCC_BUILD_COMMAND_PARSER_EXT);
+ parser.setCompilationDataBasePath(fCdbFile.getLocation());
+ addLanguageSettingsProvider(parser);
+
+ ICConfigurationDescription cfgDescription = getConfigurationDescription(fProject, true);
+
+ parser.processCompileCommandsFile(null, cfgDescription);
+ assertFalse(parser.isEmpty());
+ CoreModel.getDefault().setProjectDescription(cfgDescription.getProjectDescription().getProject(),
+ cfgDescription.getProjectDescription());
+ joingLanguageSettingsJobs();
+
+ assertExpectedEntries(parser);
+
+ ICConfigurationDescription resCfgDescription = getConfigurationDescription(fProject, false);
+ assertFalse(CDataUtil.isExcluded(tu.getPath(), resCfgDescription.getSourceEntries()));
+ }
+
+ public void testParseCDB_InvalidCommandDir() throws Exception {
+ createTestProject(true, true, false, true, true);
+
+ ICProject cProject = CCorePlugin.getDefault().getCoreModel().create(fProject);
+ ICElement ce = CCorePlugin.getDefault().getCoreModel().create(fOutsideCdbSourceFile.getFullPath());
+ ITranslationUnit tu = (ITranslationUnit) ce;
+ assertFalse(
+ CDataUtil.isExcluded(tu.getPath(), getConfigurationDescription(fProject, false).getSourceEntries()));
+
+ CompilationDatabaseParser parser = (CompilationDatabaseParser) LanguageSettingsManager
+ .getExtensionProviderCopy(COMPILATION_DATABASE_PARSER_EXT, true);
+ assertTrue(parser.isEmpty());
+ parser.setBuildParserId(GCC_BUILD_COMMAND_PARSER_EXT);
+ parser.setCompilationDataBasePath(fCdbFile.getLocation());
+ addLanguageSettingsProvider(parser);
+
+ ICConfigurationDescription cfgDescription = getConfigurationDescription(fProject, true);
+
+ parser.processCompileCommandsFile(null, cfgDescription);
+ assertFalse(parser.isEmpty());
+ CoreModel.getDefault().setProjectDescription(cfgDescription.getProjectDescription().getProject(),
+ cfgDescription.getProjectDescription());
+ joingLanguageSettingsJobs();
+
+ ICConfigurationDescription resCfgDescription = getConfigurationDescription(fProject, false);
+ List<ICLanguageSettingEntry> entries = parser.getSettingEntries(resCfgDescription, fSourceFile2,
+ GPPLanguage.ID);
+
+ // Since the directory could not be used as working dir, both files CDB entries will match
+ // the same source file and only the last one will be recorder in language setting entries.
+ CIncludePathEntry expected = new CIncludePathEntry("/${ProjName}/folder",
+ CIncludePathEntry.VALUE_WORKSPACE_PATH);
+ CIncludePathEntry entry = (CIncludePathEntry) entries.get(0);
+ assertEquals(expected.getName(), entry.getName());
+ assertEquals(expected.getValue(), entry.getValue());
+ assertEquals(expected.getKind(), entry.getKind());
+ assertEquals(expected.getFlags(), entry.getFlags());
+ assertEquals(expected, entry);
+
+ assertEquals(new CMacroEntry("FOO", "3", 0), entries.get(1));
+
+ assertFalse(CDataUtil.isExcluded(tu.getPath(), resCfgDescription.getSourceEntries()));
+ }
+
+ public void testParseCDB_NoCommandDir() throws Exception {
+ createTestProject(true, false, true, true, true);
+
+ ICProject cProject = CCorePlugin.getDefault().getCoreModel().create(fProject);
+ ICElement ce = CCorePlugin.getDefault().getCoreModel().create(fOutsideCdbSourceFile.getFullPath());
+ ITranslationUnit tu = (ITranslationUnit) ce;
+ assertFalse(
+ CDataUtil.isExcluded(tu.getPath(), getConfigurationDescription(fProject, false).getSourceEntries()));
+
+ CompilationDatabaseParser parser = (CompilationDatabaseParser) LanguageSettingsManager
+ .getExtensionProviderCopy(COMPILATION_DATABASE_PARSER_EXT, true);
+ assertTrue(parser.isEmpty());
+ parser.setBuildParserId(GCC_BUILD_COMMAND_PARSER_EXT);
+ parser.setCompilationDataBasePath(fCdbFile.getLocation());
+ addLanguageSettingsProvider(parser);
+
+ ICConfigurationDescription cfgDescription = getConfigurationDescription(fProject, true);
+
+ parser.processCompileCommandsFile(null, cfgDescription);
+ assertFalse(parser.isEmpty());
+ CoreModel.getDefault().setProjectDescription(cfgDescription.getProjectDescription().getProject(),
+ cfgDescription.getProjectDescription());
+ joingLanguageSettingsJobs();
+
+ ICConfigurationDescription resCfgDescription = getConfigurationDescription(fProject, false);
+ List<ICLanguageSettingEntry> entries = parser.getSettingEntries(resCfgDescription, fSourceFile2,
+ GPPLanguage.ID);
+
+ // Since the directory could not be used as working dir, both files CDB entries will match
+ // the same source file and only the last one will be recorder in language setting entries.
+ CIncludePathEntry expected = new CIncludePathEntry("/${ProjName}/folder",
+ CIncludePathEntry.VALUE_WORKSPACE_PATH);
+ CIncludePathEntry entry = (CIncludePathEntry) entries.get(0);
+ assertEquals(expected.getName(), entry.getName());
+ assertEquals(expected.getValue(), entry.getValue());
+ assertEquals(expected.getKind(), entry.getKind());
+ assertEquals(expected.getFlags(), entry.getFlags());
+ assertEquals(expected, entry);
+
+ assertEquals(new CMacroEntry("FOO", "3", 0), entries.get(1));
+
+ assertFalse(CDataUtil.isExcluded(tu.getPath(), resCfgDescription.getSourceEntries()));
+ }
+
+ public void testParseCDB_InvalidCommandLine() throws Exception {
+ createTestProject(true, true, true, true, false);
+
+ ICProject cProject = CCorePlugin.getDefault().getCoreModel().create(fProject);
+ ICElement ce = CCorePlugin.getDefault().getCoreModel().create(fOutsideCdbSourceFile.getFullPath());
+ ITranslationUnit tu = (ITranslationUnit) ce;
+ assertFalse(
+ CDataUtil.isExcluded(tu.getPath(), getConfigurationDescription(fProject, false).getSourceEntries()));
+
+ CompilationDatabaseParser parser = (CompilationDatabaseParser) LanguageSettingsManager
+ .getExtensionProviderCopy(COMPILATION_DATABASE_PARSER_EXT, true);
+ assertTrue(parser.isEmpty());
+ parser.setBuildParserId(GCC_BUILD_COMMAND_PARSER_EXT);
+ parser.setCompilationDataBasePath(fCdbFile.getLocation());
+ addLanguageSettingsProvider(parser);
+
+ ICConfigurationDescription cfgDescription = getConfigurationDescription(fProject, true);
+
+ parser.processCompileCommandsFile(null, cfgDescription);
+ assertFalse(parser.isEmpty());
+ CoreModel.getDefault().setProjectDescription(cfgDescription.getProjectDescription().getProject(),
+ cfgDescription.getProjectDescription());
+ joingLanguageSettingsJobs();
+
+ ICConfigurationDescription resCfgDescription = getConfigurationDescription(fProject, false);
+ assertNull(parser.getSettingEntries(resCfgDescription, fSourceFile, GPPLanguage.ID));
+ assertNull(parser.getSettingEntries(resCfgDescription, fSourceFile2, GPPLanguage.ID));
+
+ assertFalse(CDataUtil.isExcluded(tu.getPath(), resCfgDescription.getSourceEntries()));
+ }
+
+ public void testParseCDB_NoCommandLine() throws Exception {
+ createTestProject(true, true, true, false, true);
+
+ ICProject cProject = CCorePlugin.getDefault().getCoreModel().create(fProject);
+ ICElement ce = CCorePlugin.getDefault().getCoreModel().create(fOutsideCdbSourceFile.getFullPath());
+ ITranslationUnit tu = (ITranslationUnit) ce;
+ assertFalse(
+ CDataUtil.isExcluded(tu.getPath(), getConfigurationDescription(fProject, false).getSourceEntries()));
+
+ CompilationDatabaseParser parser = (CompilationDatabaseParser) LanguageSettingsManager
+ .getExtensionProviderCopy(COMPILATION_DATABASE_PARSER_EXT, true);
+ assertTrue(parser.isEmpty());
+ parser.setBuildParserId(GCC_BUILD_COMMAND_PARSER_EXT);
+ parser.setCompilationDataBasePath(fCdbFile.getLocation());
+ addLanguageSettingsProvider(parser);
+
+ ICConfigurationDescription cfgDescription = getConfigurationDescription(fProject, true);
+
+ parser.processCompileCommandsFile(null, cfgDescription);
+ assertFalse(parser.isEmpty());
+ CoreModel.getDefault().setProjectDescription(cfgDescription.getProjectDescription().getProject(),
+ cfgDescription.getProjectDescription());
+ joingLanguageSettingsJobs();
+
+ ICConfigurationDescription resCfgDescription = getConfigurationDescription(fProject, false);
+ assertNull(parser.getSettingEntries(resCfgDescription, fSourceFile, GPPLanguage.ID));
+ assertNull(parser.getSettingEntries(resCfgDescription, fSourceFile2, GPPLanguage.ID));
+
+ assertFalse(CDataUtil.isExcluded(tu.getPath(), resCfgDescription.getSourceEntries()));
+ }
+
+ public void testClear() throws Exception {
+ createTestProject();
+
+ ICProject cProject = CCorePlugin.getDefault().getCoreModel().create(fProject);
+ ICElement ce = CCorePlugin.getDefault().getCoreModel().create(fOutsideCdbSourceFile.getFullPath());
+ ITranslationUnit tu = (ITranslationUnit) ce;
+ assertFalse(
+ CDataUtil.isExcluded(tu.getPath(), getConfigurationDescription(fProject, false).getSourceEntries()));
+
+ CompilationDatabaseParser parser = (CompilationDatabaseParser) LanguageSettingsManager
+ .getExtensionProviderCopy(COMPILATION_DATABASE_PARSER_EXT, true);
+ assertTrue(parser.isEmpty());
+ parser.setBuildParserId(GCC_BUILD_COMMAND_PARSER_EXT);
+ parser.setCompilationDataBasePath(fCdbFile.getLocation());
+ addLanguageSettingsProvider(parser);
+
+ ICConfigurationDescription cfgDescription = getConfigurationDescription(fProject, true);
+
+ parser.processCompileCommandsFile(null, cfgDescription);
+ assertFalse(parser.isEmpty());
+
+ parser.clear();
+ assertTrue(parser.isEmpty());
+ assertEquals(parser.getProperty(ATTR_CDB_MODIFIED_TIME), "");
+ }
+
+ public void testCloneShallow() throws Exception {
+ createTestProject();
+
+ ICProject cProject = CCorePlugin.getDefault().getCoreModel().create(fProject);
+ ICElement ce = CCorePlugin.getDefault().getCoreModel().create(fOutsideCdbSourceFile.getFullPath());
+ ITranslationUnit tu = (ITranslationUnit) ce;
+ assertFalse(
+ CDataUtil.isExcluded(tu.getPath(), getConfigurationDescription(fProject, false).getSourceEntries()));
+
+ CompilationDatabaseParser parser = (CompilationDatabaseParser) LanguageSettingsManager
+ .getExtensionProviderCopy(COMPILATION_DATABASE_PARSER_EXT, true);
+ assertTrue(parser.isEmpty());
+ parser.setBuildParserId(GCC_BUILD_COMMAND_PARSER_EXT);
+ parser.setCompilationDataBasePath(fCdbFile.getLocation());
+ addLanguageSettingsProvider(parser);
+
+ ICConfigurationDescription cfgDescription = getConfigurationDescription(fProject, true);
+
+ parser.processCompileCommandsFile(null, cfgDescription);
+ assertFalse(parser.isEmpty());
+
+ CompilationDatabaseParser clonedShallow = parser.cloneShallow();
+ assertEquals(clonedShallow.getProperty(ATTR_CDB_PATH), parser.getProperty(ATTR_CDB_PATH));
+ assertEquals(clonedShallow.getProperty(ATTR_BUILD_PARSER_ID), parser.getProperty(ATTR_BUILD_PARSER_ID));
+ assertEquals(clonedShallow.getProperty(ATTR_EXCLUDE_FILES), parser.getProperty(ATTR_EXCLUDE_FILES));
+ assertEquals(clonedShallow.getProperty(ATTR_CDB_MODIFIED_TIME), "");
+ }
+
+ public void testClone() throws Exception {
+ createTestProject();
+
+ ICProject cProject = CCorePlugin.getDefault().getCoreModel().create(fProject);
+ ICElement ce = CCorePlugin.getDefault().getCoreModel().create(fOutsideCdbSourceFile.getFullPath());
+ ITranslationUnit tu = (ITranslationUnit) ce;
+ assertFalse(
+ CDataUtil.isExcluded(tu.getPath(), getConfigurationDescription(fProject, false).getSourceEntries()));
+
+ CompilationDatabaseParser parser = (CompilationDatabaseParser) LanguageSettingsManager
+ .getExtensionProviderCopy(COMPILATION_DATABASE_PARSER_EXT, true);
+ assertTrue(parser.isEmpty());
+ parser.setBuildParserId(GCC_BUILD_COMMAND_PARSER_EXT);
+ parser.setCompilationDataBasePath(fCdbFile.getLocation());
+ addLanguageSettingsProvider(parser);
+
+ ICConfigurationDescription cfgDescription = getConfigurationDescription(fProject, true);
+
+ parser.processCompileCommandsFile(null, cfgDescription);
+ assertFalse(parser.isEmpty());
+
+ ICConfigurationDescription resCfgDescription = getConfigurationDescription(fProject, false);
+ List<ICLanguageSettingEntry> entries = parser.getSettingEntries(resCfgDescription, fSourceFile, GPPLanguage.ID);
+ assertExpectedEntries(parser);
+
+ CompilationDatabaseParser cloned = parser.clone();
+ entries = cloned.getSettingEntries(resCfgDescription, fSourceFile, GPPLanguage.ID);
+ assertExpectedEntries(cloned);
+ assertEquals(cloned.getProperty(ATTR_CDB_MODIFIED_TIME), parser.getProperty(ATTR_CDB_MODIFIED_TIME));
+ }
+
+ public void testParseCDB_testUpdateWithModifiedCDB() throws Exception {
+ createTestProject();
+
+ ICProject cProject = CCorePlugin.getDefault().getCoreModel().create(fProject);
+ ICElement ce = CCorePlugin.getDefault().getCoreModel().create(fOutsideCdbSourceFile.getFullPath());
+ ITranslationUnit tu = (ITranslationUnit) ce;
+ assertFalse(
+ CDataUtil.isExcluded(tu.getPath(), getConfigurationDescription(fProject, false).getSourceEntries()));
+
+ CompilationDatabaseParser parser = (CompilationDatabaseParser) LanguageSettingsManager
+ .getExtensionProviderCopy(COMPILATION_DATABASE_PARSER_EXT, true);
+ assertTrue(parser.isEmpty());
+ parser.setBuildParserId(GCC_BUILD_COMMAND_PARSER_EXT);
+ parser.setCompilationDataBasePath(fCdbFile.getLocation());
+ addLanguageSettingsProvider(parser);
+
+ ICConfigurationDescription cfgDescription = getConfigurationDescription(fProject, true);
+
+ parser.processCompileCommandsFile(null, cfgDescription);
+ assertFalse(parser.isEmpty());
+ CoreModel.getDefault().setProjectDescription(cfgDescription.getProjectDescription().getProject(),
+ cfgDescription.getProjectDescription());
+ joingLanguageSettingsJobs();
+
+ ICConfigurationDescription resCfgDescription = getConfigurationDescription(fProject, false);
+ assertExpectedEntries(parser);
+
+ assertFalse(CDataUtil.isExcluded(tu.getPath(), resCfgDescription.getSourceEntries()));
+
+ // Modify the CDB, only to contain one file with different macro definition.
+ String sourceFilePath = fSourceFile.getLocation().toOSString();
+ CompileCommand command = new CompileCommand();
+ command.directory = fSourceFile.getParent().getLocation().toOSString();
+ command.file = sourceFilePath;
+ command.command = "g++ -I" + fFolder.getLocation().toOSString() + " -DFOO=200 " + sourceFilePath;
+ CompileCommand[] commands = new CompileCommand[1];
+ commands[0] = command;
+ String json = new Gson().toJson(commands);
+ InputStream inputStream = new ByteArrayInputStream(json.getBytes());
+ // Make sure the timestamp is different, in case the code runs fast and
+ // in case the system doesn't support milliseconds granularity.
+ while (fCdbFile.getLocalTimeStamp() / 1000 == System.currentTimeMillis() / 1000) {
+ Thread.sleep(5);
+ }
+ fCdbFile.setContents(inputStream, IFile.FORCE, null);
+
+ parser.processCompileCommandsFile(null, cfgDescription);
+ assertFalse(parser.isEmpty());
+ CoreModel.getDefault().setProjectDescription(cfgDescription.getProjectDescription().getProject(),
+ cfgDescription.getProjectDescription());
+ joingLanguageSettingsJobs();
+
+ resCfgDescription = getConfigurationDescription(fProject, false);
+
+ assertFalse(CDataUtil.isExcluded(tu.getPath(), resCfgDescription.getSourceEntries()));
+
+ assertFalse(parser.isEmpty());
+ List<ICLanguageSettingEntry> entries = parser.getSettingEntries(resCfgDescription, fSourceFile, GPPLanguage.ID);
+
+ CIncludePathEntry expected = new CIncludePathEntry("/${ProjName}/folder",
+ CIncludePathEntry.VALUE_WORKSPACE_PATH);
+ CIncludePathEntry entry = (CIncludePathEntry) entries.get(0);
+ assertEquals(expected.getName(), entry.getName());
+ assertEquals(expected.getValue(), entry.getValue());
+ assertEquals(expected.getKind(), entry.getKind());
+ assertEquals(expected.getFlags(), entry.getFlags());
+ assertEquals(expected, entry);
+
+ assertEquals(new CMacroEntry("FOO", "200", 0), entries.get(1));
+
+ entries = parser.getSettingEntries(resCfgDescription, fSourceFile2, GPPLanguage.ID);
+ assertNull(entries);
+ }
+}
diff --git a/build/org.eclipse.cdt.managedbuilder.core/META-INF/MANIFEST.MF b/build/org.eclipse.cdt.managedbuilder.core/META-INF/MANIFEST.MF
index 12509538aad..7557234565c 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/META-INF/MANIFEST.MF
+++ b/build/org.eclipse.cdt.managedbuilder.core/META-INF/MANIFEST.MF
@@ -17,7 +17,7 @@ Export-Package: org.eclipse.cdt.build.core.scannerconfig,
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.language.settings.providers;x-friends:="org.eclipse.cdt.managedbuilder.ui",
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,
@@ -41,5 +41,6 @@ Require-Bundle: org.eclipse.cdt.core;bundle-version="[5.0.0,7.0.0)",
org.eclipse.core.filesystem;bundle-version="1.2.0"
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
-Import-Package: com.ibm.icu.text
+Import-Package: com.google.gson;version="2.8.0",
+ com.ibm.icu.text
Automatic-Module-Name: org.eclipse.cdt.managedbuilder.core
diff --git a/build/org.eclipse.cdt.managedbuilder.core/plugin.properties b/build/org.eclipse.cdt.managedbuilder.core/plugin.properties
index 5112695a91c..4c0da312928 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/plugin.properties
+++ b/build/org.eclipse.cdt.managedbuilder.core/plugin.properties
@@ -84,6 +84,7 @@ GCCBuildOutputParser.name = CDT GCC Build Output Parser
GCCBuiltinCompilerSettings.name = CDT GCC Built-in Compiler Settings
GCCBuiltinCompilerSettingsMinGW.name = CDT GCC Built-in Compiler Settings MinGW
GCCBuiltinCompilerSettingsCygwin.name = CDT GCC Built-in Compiler Settings Cygwin
+CompilationDatabaseParser.name = Compilation Database Parser
ManagedBuildSettingEntries.name = CDT Managed Build Setting Entries
extension.name.8 = C/C++ Scanner Discovery Problem
extension.name.9 = HeadlessBuilder Additional Settings \ No newline at end of file
diff --git a/build/org.eclipse.cdt.managedbuilder.core/plugin.xml b/build/org.eclipse.cdt.managedbuilder.core/plugin.xml
index 8a3c70c4966..a9ebd32a791 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/plugin.xml
+++ b/build/org.eclipse.cdt.managedbuilder.core/plugin.xml
@@ -645,6 +645,12 @@
parameter="(g?cc)|([gc]\+\+)|(clang)"
prefer-non-shared="true">
</provider>
+ <provider
+ class="org.eclipse.cdt.managedbuilder.internal.language.settings.providers.CompilationDatabaseParser"
+ id="org.eclipse.cdt.managedbuilder.core.CompilationDatabaseParser"
+ name="%CompilationDatabaseParser.name"
+ prefer-non-shared="true">
+ </provider>
</extension>
<extension
id="scanner.discovery.problem"
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/language/settings/providers/CompilationDatabaseParser.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/language/settings/providers/CompilationDatabaseParser.java
new file mode 100644
index 00000000000..e8c1e8a4a1c
--- /dev/null
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/language/settings/providers/CompilationDatabaseParser.java
@@ -0,0 +1,460 @@
+/*******************************************************************************
+ * Copyright (c) 2019 Marc-Andre Laperle.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.cdt.managedbuilder.internal.language.settings.providers;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.attribute.FileTime;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.language.settings.providers.ICListenerAgent;
+import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsEditableProvider;
+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.LanguageSettingsSerializableProvider;
+import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsStorage;
+import org.eclipse.cdt.core.model.CoreModel;
+import org.eclipse.cdt.core.model.ICElement;
+import org.eclipse.cdt.core.model.ICElementVisitor;
+import org.eclipse.cdt.core.model.ICProject;
+import org.eclipse.cdt.core.model.ITranslationUnit;
+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.ICSourceEntry;
+import org.eclipse.cdt.core.settings.model.util.CDataUtil;
+import org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin;
+import org.eclipse.cdt.managedbuilder.language.settings.providers.AbstractBuildCommandParser;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceProxy;
+import org.eclipse.core.resources.IResourceProxyVisitor;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.resources.WorkspaceJob;
+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.Path;
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubMonitor;
+
+import com.google.gson.Gson;
+import com.ibm.icu.text.MessageFormat;
+
+/**
+ * This language settings provider takes a compile_commands.json file as input (aka, Compilation Database or CDB) and parses the commands
+ * with a chosen build command parser. The command parser can be any implementation of AbstractBuildCommandParser like GCCBuildCommandParser,
+ * MSVCBuildCommandParser, etc.
+ *
+ * The file json file is re-parsed at startup through {@link #registerListener(ICConfigurationDescription)} but only if the timestamp changed.
+ * It it also parsed when the options are modified in the UI through {@link #processCompileCommandsFile(IProgressMonitor, ICConfigurationDescription)}
+ */
+public class CompilationDatabaseParser extends LanguageSettingsSerializableProvider
+ implements ICListenerAgent, ILanguageSettingsEditableProvider {
+
+ public static final String JOB_FAMILY_COMPILATION_DATABASE_PARSER = "org.eclipse.cdt.managedbuilder.internal.language.settings.providers.CompilationDatabaseParser"; //$NON-NLS-1$
+
+ private static final String ATTR_CDB_PATH = "cdb-path"; //$NON-NLS-1$
+ private static final String ATTR_BUILD_PARSER_ID = "build-parser-id"; //$NON-NLS-1$
+ private static final String ATTR_CDB_MODIFIED_TIME = "cdb-modified-time"; //$NON-NLS-1$
+ private static final String ATTR_EXCLUDE_FILES = "exclude-files"; //$NON-NLS-1$
+
+ public IPath getCompilationDataBasePath() {
+ return Path.fromOSString(getProperty(ATTR_CDB_PATH));
+ }
+
+ public void setCompilationDataBasePath(IPath compilationDataBasePath) {
+ setProperty(ATTR_CDB_PATH, compilationDataBasePath.toOSString());
+ }
+
+ public void setExcludeFiles(boolean selection) {
+ setPropertyBool(ATTR_EXCLUDE_FILES, selection);
+ }
+
+ public boolean getExcludeFiles() {
+ return getPropertyBool(ATTR_EXCLUDE_FILES);
+ }
+
+ public void setBuildParserId(String parserId) {
+ setProperty(ATTR_BUILD_PARSER_ID, parserId);
+ }
+
+ public String getBuildParserId() {
+ return getProperty(ATTR_BUILD_PARSER_ID);
+ }
+
+ public Long getCDBModifiedTime(String cdbPath) throws IOException {
+ FileTime lastModifiedTime = Files.getLastModifiedTime(Paths.get(cdbPath));
+ return lastModifiedTime.toMillis();
+ }
+
+ // Wanted to use this as a base to also count the number of translation unit
+ // for the progress monitor but it's too slow so only use it to exclude for now.
+ private abstract class SourceFilesVisitor implements ICElementVisitor {
+ @Override
+ public boolean visit(ICElement element) throws CoreException {
+ int elementType = element.getElementType();
+ if (elementType != ICElement.C_UNIT) {
+ return elementType == ICElement.C_CCONTAINER || elementType == ICElement.C_PROJECT;
+ }
+
+ ITranslationUnit tu = (ITranslationUnit) element;
+ if (tu.isSourceUnit()) {
+ handleTranslationUnit(tu);
+ }
+ return false;
+ }
+
+ abstract void handleTranslationUnit(ITranslationUnit tu) throws CoreException;
+ }
+
+ private final class ExcludeSourceFilesVisitor extends SourceFilesVisitor {
+ private final ICConfigurationDescription cfgDescription;
+ ICSourceEntry[] entries = null;
+ private final IProgressMonitor monitor;
+ private final int sourceFilesCount;
+ private int nbChecked = 0;
+
+ //Note: monitor already has ticks allocated for number of source files (not considering exclusions though)
+ private ExcludeSourceFilesVisitor(IProgressMonitor monitor, int sourceFilesCount,
+ ICConfigurationDescription cfgDescription) {
+ this.monitor = monitor;
+ this.sourceFilesCount = sourceFilesCount;
+ this.cfgDescription = cfgDescription;
+ }
+
+ public ICSourceEntry[] getSourceEntries() {
+ return entries;
+ }
+
+ @Override
+ void handleTranslationUnit(ITranslationUnit tu) throws CoreException {
+ boolean isExcluded = CDataUtil.isExcluded(tu.getPath(), cfgDescription.getSourceEntries());
+ if (!isExcluded) {
+ List<ICLanguageSettingEntry> list = getSettingEntries(cfgDescription, tu.getResource(),
+ tu.getLanguage().getId());
+ if (list == null) {
+ if (entries == null) {
+ entries = cfgDescription.getSourceEntries();
+ }
+ entries = CDataUtil.setExcluded(tu.getResource().getFullPath(), false, true, entries);
+ }
+ }
+ monitor.worked(1);
+ if (nbChecked % 100 == 0) {
+ monitor.subTask(String.format(Messages.CompilationDatabaseParser_ProgressExcludingFiles, nbChecked,
+ sourceFilesCount));
+ }
+ nbChecked++;
+ }
+ }
+
+ private static class CDBWorkingDirectoryTracker implements IWorkingDirectoryTracker {
+ URI currentDirectory = null;
+
+ @Override
+ public URI getWorkingDirectoryURI() {
+ return currentDirectory;
+ }
+
+ public void setCurrentDirectory(URI currentDirectory) {
+ this.currentDirectory = currentDirectory;
+ }
+ }
+
+ @Override
+ public void registerListener(ICConfigurationDescription cfgDescription) {
+ unregisterListener();
+ try {
+ processCompileCommandsFile(null, cfgDescription);
+ } catch (CoreException e) {
+ ManagedBuilderCorePlugin.log(e);
+ }
+ }
+
+ @Override
+ public void unregisterListener() {
+ }
+
+ /**
+ * Processes the compilation database based on the attributes previously set.
+ * Parses the commands and sets the language setting entries. If cfgDescription is a writable configuration, it is assumed that the caller will call
+ * CoreModel#setProjectDescription. Otherwise if cfgDescription is read-only, the method will restart itself with a writable configuration description and call CoreModel#setProjectDescription.
+ */
+ public boolean processCompileCommandsFile(IProgressMonitor monitor, ICConfigurationDescription cfgDescription)
+ throws CoreException {
+ if (cfgDescription.isReadOnly()) {
+ scheduleOnWritableCfgDescription(cfgDescription);
+ return false;
+ }
+
+ if (getCompilationDataBasePath().isEmpty()) {
+ throw new CoreException(new Status(Status.ERROR, ManagedBuilderCorePlugin.PLUGIN_ID,
+ Messages.CompilationDatabaseParser_CDBNotConfigured));
+ }
+
+ if (!Files.exists(Paths.get(getCompilationDataBasePath().toOSString()))) {
+ throw new CoreException(new Status(Status.ERROR, ManagedBuilderCorePlugin.PLUGIN_ID, MessageFormat.format(
+ Messages.CompilationDatabaseParser_CDBNotFound, getCompilationDataBasePath().toOSString())));
+ }
+
+ try {
+ if (!getProperty(ATTR_CDB_MODIFIED_TIME).isEmpty() && getProperty(ATTR_CDB_MODIFIED_TIME)
+ .equals(getCDBModifiedTime(getCompilationDataBasePath().toOSString()).toString())) {
+ return false;
+ }
+ } catch (IOException e) {
+ throw new CoreException(new Status(Status.ERROR, ManagedBuilderCorePlugin.PLUGIN_ID,
+ Messages.CompilationDatabaseParser_ErrorProcessingCompilationDatabase, e));
+ }
+
+ if (getBuildParserId().isEmpty()) {
+ throw new CoreException(new Status(Status.ERROR, ManagedBuilderCorePlugin.PLUGIN_ID,
+ MessageFormat.format(Messages.CompilationDatabaseParser_BuildCommandParserNotConfigured,
+ getCompilationDataBasePath().toOSString())));
+ }
+
+ if (!isEmpty()) {
+ clear();
+ }
+ String cdbPath = getCompilationDataBasePath().toOSString();
+ Long cdbModifiedTime;
+ try {
+ cdbModifiedTime = getCDBModifiedTime(cdbPath);
+ } catch (Exception e) {
+ //setProperty(ATTR_CDB_MODIFIED_TIME, Long.toString(0L));
+ throw new CoreException(new Status(Status.ERROR, ManagedBuilderCorePlugin.PLUGIN_ID,
+ Messages.CompilationDatabaseParser_ErrorProcessingCompilationDatabase, e));
+ }
+
+ int totalTicks = getExcludeFiles() ? 100 : 60;
+ SubMonitor subMonitor = SubMonitor.convert(monitor, totalTicks);
+ subMonitor.subTask(Messages.CompilationDatabaseParser_ProgressParsingJSONFile);
+ subMonitor.split(5);
+
+ CompileCommand[] compileCommands = null;
+ try (FileReader reader = new FileReader(cdbPath)) {
+ Gson gson = new Gson();
+ compileCommands = gson.fromJson(reader, CompileCommand[].class);
+ } catch (Exception e) {
+ //setProperty(ATTR_CDB_MODIFIED_TIME, Long.toString(0L));
+ throw new CoreException(new Status(Status.ERROR, ManagedBuilderCorePlugin.PLUGIN_ID,
+ Messages.CompilationDatabaseParser_ErrorProcessingCompilationDatabase, e));
+ }
+
+ AbstractBuildCommandParser outputParser;
+ try {
+ outputParser = getBuildCommandParser(cfgDescription, getBuildParserId());
+ } catch (Exception e) {
+ //setProperty(ATTR_CDB_MODIFIED_TIME, Long.toString(0L));
+ throw new CoreException(new Status(Status.ERROR, ManagedBuilderCorePlugin.PLUGIN_ID,
+ Messages.CompilationDatabaseParser_ErrorProcessingCompilationDatabase, e));
+ }
+
+ CDBWorkingDirectoryTracker workingDirectoryTracker = new CDBWorkingDirectoryTracker();
+
+ SubMonitor parseCmdsMonitor = SubMonitor.convert(subMonitor.split(50), compileCommands.length);
+ outputParser.startup(cfgDescription, workingDirectoryTracker);
+ for (int i = 0; i < compileCommands.length; i++) {
+ CompileCommand c = compileCommands[i];
+ // Don't spam the progress view too much
+ if (i % 100 == 0) {
+ parseCmdsMonitor.subTask(String.format(Messages.CompilationDatabaseParser_ProgressParsingBuildCommands,
+ i, compileCommands.length));
+ }
+ String dir = c.getDirectory();
+ workingDirectoryTracker.setCurrentDirectory(null);
+ if (dir != null) {
+ File file = new File(dir);
+ if (file.exists()) {
+ workingDirectoryTracker.setCurrentDirectory(file.toURI());
+ }
+ }
+
+ outputParser.processLine(c.getCommand());
+ parseCmdsMonitor.worked(1);
+ }
+ LanguageSettingsStorage storage = outputParser.copyStorage();
+ SubMonitor entriesMonitor = SubMonitor.convert(subMonitor.split(5), storage.getLanguages().size());
+ entriesMonitor.subTask(Messages.CompilationDatabaseParser_ProgressApplyingEntries);
+ for (String language : storage.getLanguages()) {
+ SubMonitor langMonitor = entriesMonitor.split(1);
+ Set<String> resourcePaths = storage.getResourcePaths(language);
+ SubMonitor langEntriesMonitor = SubMonitor.convert(langMonitor, resourcePaths.size());
+ for (String resourcePath : resourcePaths) {
+ IFile file = cfgDescription.getProjectDescription().getProject().getFile(new Path(resourcePath));
+ if (file.exists()) {
+ List<ICLanguageSettingEntry> settingEntries = storage.getSettingEntries(resourcePath, language);
+ setSettingEntries(cfgDescription, file, language, settingEntries);
+ }
+ langEntriesMonitor.worked(1);
+ }
+ }
+
+ if (getExcludeFiles()) {
+ excludeFiles(cfgDescription, subMonitor);
+ }
+
+ setProperty(ATTR_CDB_MODIFIED_TIME, cdbModifiedTime.toString());
+ touchProjectDes(cfgDescription.getProjectDescription());
+ return true;
+ }
+
+ private void scheduleOnWritableCfgDescription(ICConfigurationDescription cfgDescription) {
+ WorkspaceJob job = new WorkspaceJob(Messages.CompilationDatabaseParser_Job) {
+ @Override
+ public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException {
+ // If the config description we have been given is read-only, we need to get a writable one instead in order to be able to set source entries (exclusions).
+ // The tricky thing is that in that situation, the CompilationDatabaseParser instance (this) came from the read-only project description so anything that is
+ // saved that is not stored in the project description (i.e. calls to setProperties) will be saved to the wrong instance so when we call setProjectDescription, our changes will be ignored.
+ // So instead, restart the whole thing with the corresponding CompilationDatabaseParser instance in the writable config.
+ IProject project = cfgDescription.getProjectDescription().getProject();
+ ICProjectDescription projectDescription = CCorePlugin.getDefault().getCoreModel()
+ .getProjectDescription(project.getProject(), true);
+ ICConfigurationDescription writableCfg = projectDescription
+ .getConfigurationById(cfgDescription.getId());
+ if (!(writableCfg instanceof ILanguageSettingsProvidersKeeper)) {
+ return Status.CANCEL_STATUS;
+ }
+
+ CompilationDatabaseParser parser = null;
+ List<ILanguageSettingsProvider> settingProviders = ((ILanguageSettingsProvidersKeeper) writableCfg)
+ .getLanguageSettingProviders();
+ for (ILanguageSettingsProvider languageSettingsProvider : settingProviders) {
+ if (languageSettingsProvider.getId().equals(CompilationDatabaseParser.this.getId())
+ && languageSettingsProvider instanceof CompilationDatabaseParser) {
+ parser = (CompilationDatabaseParser) languageSettingsProvider;
+ break;
+ }
+ }
+
+ if (parser == null) {
+ // Seems very unlikely to get here. This should mean that the provider was disabled before the job ran.
+ return Status.CANCEL_STATUS;
+ }
+
+ try {
+ if (parser.processCompileCommandsFile(monitor, writableCfg)) {
+ CoreModel.getDefault().setProjectDescription(project.getProject(), projectDescription);
+ }
+ } catch (CoreException e) {
+ // If we are running this in a WorkspaceJob it's because the CfgDescription was read-only so we are probably loading the project.
+ // We don't want to pop-up jarring error dialogs on start-up. Ideally, CDT would have problem markers for project setup issues.
+ ManagedBuilderCorePlugin.log(e);
+ }
+
+ return Status.OK_STATUS;
+ }
+
+ @Override
+ public boolean belongsTo(Object family) {
+ return family == JOB_FAMILY_COMPILATION_DATABASE_PARSER;
+ }
+ };
+
+ // Using root rule because of call to setProjectDescription above
+ job.setRule(ResourcesPlugin.getWorkspace().getRoot());
+ job.schedule();
+ }
+
+ private void excludeFiles(ICConfigurationDescription cfgDescription, SubMonitor subMonitor) throws CoreException {
+ ICProject cProject = CCorePlugin.getDefault().getCoreModel()
+ .create(cfgDescription.getProjectDescription().getProject());
+ // Getting a approximation of the number of source files we will have to visit based on file names.
+ // Much faster than going through the CElements. Then do the real work and report progress.
+ // It's possible that the approximation will be pretty wrong if there are a lot of already excluded files
+ // then we won't visit them in the ExcludeSourceFilesVisitor and the progress monitor won't be ticked for those.
+ int sourceFilesCount[] = new int[1];
+ cProject.getProject().accept(new IResourceProxyVisitor() {
+ @Override
+ public boolean visit(IResourceProxy proxy) throws CoreException {
+ if (CoreModel.isValidSourceUnitName(cProject.getProject(), proxy.getName()))
+ sourceFilesCount[0]++;
+ return true;
+ }
+ }, IResource.DEPTH_INFINITE, IResource.NONE);
+ SubMonitor sourceMonitor = SubMonitor.convert(subMonitor.split(35), sourceFilesCount[0]);
+
+ ExcludeSourceFilesVisitor sourceFileVisitor = new ExcludeSourceFilesVisitor(sourceMonitor, sourceFilesCount[0],
+ cfgDescription);
+ cProject.accept(sourceFileVisitor);
+ ICSourceEntry[] sourceEntries = sourceFileVisitor.getSourceEntries();
+
+ subMonitor.split(5);
+ if (sourceEntries != null) {
+ cfgDescription.setSourceEntries(sourceEntries);
+ }
+ }
+
+ private void touchProjectDes(ICProjectDescription desc) {
+ // Make sure the project description is marked as modified so that language settings serialization kicks in.
+ // We need to let the setProjectDescription do the serialization because we cannot do it on a writable description
+ // and we need a writable description because we need to call setSourceEntries!
+ final QualifiedName TOUCH_PROPERTY = new QualifiedName(CCorePlugin.PLUGIN_ID, "touch-project"); //$NON-NLS-1$
+ desc.setSessionProperty(TOUCH_PROPERTY, ""); //$NON-NLS-1$
+ desc.setSessionProperty(TOUCH_PROPERTY, null);
+ }
+
+ private AbstractBuildCommandParser getBuildCommandParser(ICConfigurationDescription cfgDesc, String id)
+ throws CloneNotSupportedException {
+ ICConfigurationDescription configurationDescription = cfgDesc;
+ if (configurationDescription instanceof ILanguageSettingsProvidersKeeper) {
+ List<ILanguageSettingsProvider> settingProviders = ((ILanguageSettingsProvidersKeeper) configurationDescription)
+ .getLanguageSettingProviders();
+ for (ILanguageSettingsProvider languageSettingsProvider : settingProviders) {
+ if (languageSettingsProvider instanceof AbstractBuildCommandParser
+ && languageSettingsProvider instanceof ILanguageSettingsEditableProvider) {
+ AbstractBuildCommandParser buildParser = (AbstractBuildCommandParser) languageSettingsProvider;
+ if (buildParser.getId().equals(id))
+ return (AbstractBuildCommandParser) ((ILanguageSettingsEditableProvider) buildParser).clone();
+ }
+ }
+ }
+
+ throw new IllegalArgumentException(MessageFormat
+ .format(Messages.CompilationDatabaseParser_BuildCommandParserNotFound, id, cfgDesc.getName()));
+ }
+
+ @Override
+ public boolean isEmpty() {
+ // treat provider that has been executed as not empty
+ // to let "Clear" button to restart the provider
+ return getProperty(ATTR_CDB_MODIFIED_TIME).isEmpty() && super.isEmpty();
+ }
+
+ @Override
+ public void clear() {
+ super.clear();
+ setProperty(ATTR_CDB_MODIFIED_TIME, null);
+ }
+
+ @Override
+ public CompilationDatabaseParser cloneShallow() throws CloneNotSupportedException {
+ CompilationDatabaseParser clone = (CompilationDatabaseParser) super.cloneShallow();
+ clone.setProperty(ATTR_CDB_MODIFIED_TIME, null);
+ return clone;
+ }
+
+ @Override
+ public CompilationDatabaseParser clone() throws CloneNotSupportedException {
+ return (CompilationDatabaseParser) super.clone();
+ }
+}
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/language/settings/providers/CompileCommand.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/language/settings/providers/CompileCommand.java
new file mode 100644
index 00000000000..3675d94dc07
--- /dev/null
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/language/settings/providers/CompileCommand.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2019 QNX Software Systems and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Marc-André Laperle - Moved to managed builder
+ *******************************************************************************/
+package org.eclipse.cdt.managedbuilder.internal.language.settings.providers;
+
+public class CompileCommand {
+
+ public String directory;
+ public String command;
+ public String file;
+
+ public String getDirectory() {
+ return directory;
+ }
+
+ public String getCommand() {
+ return command;
+ }
+
+ public String getFile() {
+ return file;
+ }
+
+}
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/language/settings/providers/Messages.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/language/settings/providers/Messages.java
new file mode 100644
index 00000000000..1a15eaff8f6
--- /dev/null
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/language/settings/providers/Messages.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2019 Marc-Andre Laperle.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+
+package org.eclipse.cdt.managedbuilder.internal.language.settings.providers;
+
+import org.eclipse.osgi.util.NLS;
+
+public class Messages extends NLS {
+ private static final String BUNDLE_NAME = "org.eclipse.cdt.managedbuilder.internal.language.settings.providers.messages"; //$NON-NLS-1$
+
+ public static String CompilationDatabaseParser_BuildCommandParserNotConfigured;
+ public static String CompilationDatabaseParser_BuildCommandParserNotFound;
+ public static String CompilationDatabaseParser_CDBNotConfigured;
+ public static String CompilationDatabaseParser_CDBNotFound;
+ public static String CompilationDatabaseParser_ErrorProcessingCompilationDatabase;
+ public static String CompilationDatabaseParser_Job;
+ public static String CompilationDatabaseParser_ProgressApplyingEntries;
+ public static String CompilationDatabaseParser_ProgressExcludingFiles;
+ public static String CompilationDatabaseParser_ProgressParsingBuildCommands;
+ public static String CompilationDatabaseParser_ProgressParsingJSONFile;
+
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+ private Messages() {
+ }
+}
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/language/settings/providers/messages.properties b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/language/settings/providers/messages.properties
new file mode 100644
index 00000000000..f5b2a80d63b
--- /dev/null
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/language/settings/providers/messages.properties
@@ -0,0 +1,21 @@
+################################################################################
+# Copyright (c) 2019 Marc-Andre Laperle.
+#
+# This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License 2.0
+# which accompanies this distribution, and is available at
+# https://www.eclipse.org/legal/epl-2.0/
+#
+# SPDX-License-Identifier: EPL-2.0
+################################################################################
+
+CompilationDatabaseParser_BuildCommandParserNotConfigured=Compilation database parser does not have a build command parser configured.
+CompilationDatabaseParser_BuildCommandParserNotFound=Could not find '{0}' language settings provider in configuration '{1}'
+CompilationDatabaseParser_CDBNotConfigured=Compilation database (usually compile_commands.json) path not set.
+CompilationDatabaseParser_CDBNotFound=Compilation database (usually compile_commands.json) not found at location {0}.
+CompilationDatabaseParser_ErrorProcessingCompilationDatabase=Error processing compilation database.
+CompilationDatabaseParser_Job=Discover Compilation Database language settings
+CompilationDatabaseParser_ProgressApplyingEntries=Applying language setting entries
+CompilationDatabaseParser_ProgressExcludingFiles=Excluding files not in compilation database. Checking %d/%d (Estimate)
+CompilationDatabaseParser_ProgressParsingBuildCommands=Parsing build commands (%d/%d)
+CompilationDatabaseParser_ProgressParsingJSONFile=Parsing JSON file \ No newline at end of file
diff --git a/build/org.eclipse.cdt.managedbuilder.ui/META-INF/MANIFEST.MF b/build/org.eclipse.cdt.managedbuilder.ui/META-INF/MANIFEST.MF
index ccd25f10192..f8f7c4b19b5 100644
--- a/build/org.eclipse.cdt.managedbuilder.ui/META-INF/MANIFEST.MF
+++ b/build/org.eclipse.cdt.managedbuilder.ui/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.cdt.managedbuilder.ui; singleton:=true
-Bundle-Version: 9.1.300.qualifier
+Bundle-Version: 9.1.400.qualifier
Bundle-Activator: org.eclipse.cdt.managedbuilder.ui.properties.ManagedBuilderUIPlugin
Bundle-Vendor: %providerName
Bundle-Localization: plugin
diff --git a/build/org.eclipse.cdt.managedbuilder.ui/plugin.xml b/build/org.eclipse.cdt.managedbuilder.ui/plugin.xml
index e9df66e8a4f..198bcea8041 100644
--- a/build/org.eclipse.cdt.managedbuilder.ui/plugin.xml
+++ b/build/org.eclipse.cdt.managedbuilder.ui/plugin.xml
@@ -884,6 +884,13 @@
ui-clear-entries="true"
ui-edit-entries="false">
</class-association>
+ <class-association
+ class="org.eclipse.cdt.managedbuilder.internal.language.settings.providers.CompilationDatabaseParser"
+ icon="icons/obj16/log_obj.gif"
+ page="org.eclipse.cdt.managedbuilder.internal.ui.language.settings.providers.CompilationDatabaseParserOptionPage"
+ ui-clear-entries="true"
+ ui-edit-entries="false">
+ </class-association>
</extension>
<extension
point="org.eclipse.cdt.core.CBuildConsole">
diff --git a/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/language/settings/providers/CompilationDatabaseParserOptionPage.java b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/language/settings/providers/CompilationDatabaseParserOptionPage.java
new file mode 100644
index 00000000000..391fe05fdc8
--- /dev/null
+++ b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/language/settings/providers/CompilationDatabaseParserOptionPage.java
@@ -0,0 +1,295 @@
+/*******************************************************************************
+ * Copyright (c) 2019 Marc-Andre Laperle.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.cdt.managedbuilder.internal.ui.language.settings.providers;
+
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvider;
+import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvidersKeeper;
+import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
+import org.eclipse.cdt.internal.ui.newui.StatusMessageLine;
+import org.eclipse.cdt.managedbuilder.internal.language.settings.providers.CompilationDatabaseParser;
+import org.eclipse.cdt.managedbuilder.language.settings.providers.AbstractBuildCommandParser;
+import org.eclipse.cdt.managedbuilder.ui.properties.ManagedBuilderUIPlugin;
+import org.eclipse.cdt.ui.language.settings.providers.AbstractLanguageSettingProviderOptionPage;
+import org.eclipse.cdt.utils.ui.controls.ControlFactory;
+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.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * Options page for {@link CompilationDatabaseParser}.
+ *
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public final class CompilationDatabaseParserOptionPage extends AbstractLanguageSettingProviderOptionPage {
+ private boolean fEditable;
+ private Text fCompileCommandsPath;
+
+ @SuppressWarnings("restriction")
+ private StatusMessageLine fStatusLine;
+ private Combo fBuildOutputParserCombo;
+
+ @Override
+ public void createControl(Composite parent) {
+ fEditable = parent.isEnabled();
+ CompilationDatabaseParser provider = (CompilationDatabaseParser) getProvider();
+
+ Composite composite = createCompositeForPageArea(parent);
+ createCompileCommandsPathInputControl(composite, provider);
+ createBrowseButton(composite);
+ createOutputParserCombo(composite);
+ createExclusionOptions(composite);
+ createStatusLine(composite, provider);
+
+ setControl(composite);
+ }
+
+ private Composite createCompositeForPageArea(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 2;
+ layout.marginWidth = 1;
+ layout.marginHeight = 1;
+ layout.marginRight = 1;
+ composite.setLayout(layout);
+ composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+ Dialog.applyDialogFont(composite);
+
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalSpan = 2;
+ composite.setLayoutData(gd);
+ return composite;
+ }
+
+ private void createCompileCommandsPathInputControl(Composite composite, CompilationDatabaseParser provider) {
+ Label label = ControlFactory.createLabel(composite,
+ Messages.CompilationDatabaseParserOptionPage_CompileCommandsPath);
+ GridData gd = new GridData();
+ gd.horizontalSpan = 2;
+ label.setLayoutData(gd);
+ label.setEnabled(fEditable);
+
+ fCompileCommandsPath = ControlFactory.createTextField(composite, SWT.SINGLE | SWT.BORDER);
+ String command = provider.getCompilationDataBasePath().toOSString();
+ fCompileCommandsPath.setText(command != null ? command : ""); //$NON-NLS-1$
+ fCompileCommandsPath.setEnabled(fEditable);
+ fCompileCommandsPath.addModifyListener(new ModifyListener() {
+ @Override
+ public void modifyText(ModifyEvent e) {
+ String text = fCompileCommandsPath.getText();
+ CompilationDatabaseParser provider = (CompilationDatabaseParser) getProvider();
+ if (provider.getCompilationDataBasePath() == null
+ || !text.equals(provider.getCompilationDataBasePath().toOSString())) {
+ CompilationDatabaseParser selectedProvider = (CompilationDatabaseParser) getProviderWorkingCopy();
+ selectedProvider.setCompilationDataBasePath(Path.fromOSString(text));
+ refreshItem(selectedProvider);
+ validate();
+ }
+ }
+ });
+ }
+
+ private void createBrowseButton(Composite composite) {
+ Button button = ControlFactory.createPushButton(composite, Messages.CompilationDatabaseParserOptionPage_Browse);
+ button.setEnabled(fEditable);
+ button.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent evt) {
+ FileDialog dialog = new FileDialog(getShell(), SWT.NONE);
+ dialog.setText(Messages.CompilationDatabaseParserOptionPage_ChooseFile);
+ String fileName = fCompileCommandsPath.getText();
+ IPath folder = new Path(fileName).removeLastSegments(1);
+ dialog.setFilterPath(folder.toOSString());
+ String chosenFile = dialog.open();
+ if (chosenFile != null) {
+ fCompileCommandsPath.insert(chosenFile);
+ }
+ }
+ });
+ }
+
+ private void createOutputParserCombo(Composite composite) {
+ ICConfigurationDescription configurationDescription = getConfigurationDescription();
+ List<AbstractBuildCommandParser> buildParsers = new ArrayList<>();
+ if (configurationDescription instanceof ILanguageSettingsProvidersKeeper) {
+ List<ILanguageSettingsProvider> settingProviders = ((ILanguageSettingsProvidersKeeper) configurationDescription)
+ .getLanguageSettingProviders();
+ for (ILanguageSettingsProvider languageSettingsProvider : settingProviders) {
+ if (languageSettingsProvider instanceof AbstractBuildCommandParser) {
+ AbstractBuildCommandParser buildParser = (AbstractBuildCommandParser) languageSettingsProvider;
+ buildParsers.add(buildParser);
+ }
+ }
+ }
+
+ Label parserLabel = ControlFactory.createLabel(composite,
+ Messages.CompilationDatabaseParserOptionPage_BuildParser);
+ GridData gd = new GridData(SWT.BEGINNING);
+ gd.horizontalSpan = 2;
+ parserLabel.setLayoutData(gd);
+
+ fBuildOutputParserCombo = new Combo(composite, SWT.READ_ONLY);
+ fBuildOutputParserCombo.setEnabled(fEditable);
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalSpan = 2;
+ fBuildOutputParserCombo.setLayoutData(gd);
+ if (buildParsers.isEmpty()) {
+ fBuildOutputParserCombo.add(Messages.CompilationDatabaseParserOptionPage_NoBuildOutputParserError);
+ fBuildOutputParserCombo.select(0);
+ fBuildOutputParserCombo.setEnabled(false);
+ // Can't call getProviderWorkingCopy().setBuildParserId() while creating the page since
+ // it will try to replace the selected provider in the table which
+ // doesn't have a proper selection index until one of them is clicked.
+ // Use combo.setData to encode invalid/valid data then set it on the working copy on setVisible(true)/validate.
+ fBuildOutputParserCombo.setData(null);
+ return;
+ }
+
+ for (int i = 0; i < buildParsers.size(); i++) {
+ AbstractBuildCommandParser buildParser = buildParsers.get(i);
+ fBuildOutputParserCombo.add(buildParser.getName());
+ fBuildOutputParserCombo.setData(buildParser.getName(), buildParser);
+ if (buildParser.getId().equals(((CompilationDatabaseParser) getProvider()).getBuildParserId())) {
+ fBuildOutputParserCombo.select(i);
+ fBuildOutputParserCombo.setData(buildParser.getId());
+ }
+ }
+
+ fBuildOutputParserCombo.addModifyListener(new ModifyListener() {
+ @Override
+ public void modifyText(ModifyEvent e) {
+ AbstractBuildCommandParser parser = (AbstractBuildCommandParser) fBuildOutputParserCombo
+ .getData(fBuildOutputParserCombo.getText());
+ CompilationDatabaseParser selectedProvider = (CompilationDatabaseParser) getProviderWorkingCopy();
+ String parserId = ""; //$NON-NLS-1$
+ if (parser != null) {
+ parserId = parser.getId();
+ }
+ selectedProvider.setBuildParserId(parserId);
+ fBuildOutputParserCombo.setData(parserId);
+ validate();
+ }
+ });
+
+ }
+
+ private void createExclusionOptions(Composite parent) {
+ Button keepExclusion = new Button(parent, SWT.CHECK);
+ keepExclusion.setText(Messages.CompilationDatabaseParserOptionPage_ExcludeFiles);
+ GridData gd = new GridData(SWT.BEGINNING);
+ gd.horizontalSpan = 2;
+ keepExclusion.setLayoutData(gd);
+
+ keepExclusion.setSelection(((CompilationDatabaseParser) getProvider()).getExcludeFiles());
+ keepExclusion.addSelectionListener(new SelectionListener() {
+
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ CompilationDatabaseParser selectedProvider = (CompilationDatabaseParser) getProviderWorkingCopy();
+ selectedProvider.setExcludeFiles(keepExclusion.getSelection());
+ }
+
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ });
+ }
+
+ @SuppressWarnings("restriction")
+ private void createStatusLine(Composite composite, CompilationDatabaseParser provider) {
+ fStatusLine = new StatusMessageLine(composite, SWT.LEFT, 2);
+ }
+
+ @SuppressWarnings("restriction")
+ @Override
+ public void performApply(IProgressMonitor monitor) throws CoreException {
+ ILanguageSettingsProvider provider = providerTab.getProvider(providerId);
+ if ((provider instanceof CompilationDatabaseParser)) { // basically check for working copy
+ CompilationDatabaseParser compilationDatabaseParser = (CompilationDatabaseParser) provider;
+ ILanguageSettingsProvider initialProvider = providerTab.getInitialProvider(providerId);
+ if (!(initialProvider instanceof CompilationDatabaseParser)
+ || !((CompilationDatabaseParser) initialProvider).getCompilationDataBasePath()
+ .equals(compilationDatabaseParser.getCompilationDataBasePath())
+ || !((CompilationDatabaseParser) initialProvider).getBuildParserId()
+ .equals(compilationDatabaseParser.getBuildParserId())
+ || ((CompilationDatabaseParser) initialProvider).getExcludeFiles() != compilationDatabaseParser
+ .getExcludeFiles()) {
+ compilationDatabaseParser.clear();
+ }
+ if (compilationDatabaseParser.isEmpty()) {
+ compilationDatabaseParser.processCompileCommandsFile(monitor, getConfigurationDescription());
+ }
+ }
+
+ super.performApply(monitor);
+ }
+
+ @SuppressWarnings("restriction")
+ private void validate() {
+ if (fBuildOutputParserCombo.getData() == null) {
+ ((CompilationDatabaseParser) getProviderWorkingCopy()).setBuildParserId(null);
+ }
+
+ CompilationDatabaseParser provider = (CompilationDatabaseParser) getProvider();
+ if (provider.getCompilationDataBasePath() == null || provider.getCompilationDataBasePath().isEmpty()
+ || !Files.exists(Paths.get(provider.getCompilationDataBasePath().toOSString()))) {
+ fStatusLine.setErrorStatus(new Status(IStatus.ERROR, ManagedBuilderUIPlugin.getUniqueIdentifier(),
+ Messages.CompilationDatabaseParserOptionPage_CompileCommandsPathError));
+ return;
+ }
+
+ if (provider.getBuildParserId() == null || provider.getBuildParserId().isEmpty()) {
+ fStatusLine.setErrorStatus(new Status(IStatus.ERROR, ManagedBuilderUIPlugin.getUniqueIdentifier(),
+ Messages.CompilationDatabaseParserOptionPage_BuildOutputParserError));
+ return;
+ }
+
+ fStatusLine.setErrorStatus(Status.OK_STATUS);
+ }
+
+ private ICConfigurationDescription getConfigurationDescription() {
+ if (providerTab.page.isForPrefs()) {
+ return null;
+ }
+
+ return providerTab.getResDesc().getConfiguration().getConfiguration();
+ }
+
+ @Override
+ public void setVisible(boolean visible) {
+ super.setVisible(visible);
+ if (visible) {
+ validate();
+ }
+ }
+}
diff --git a/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/language/settings/providers/Messages.java b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/language/settings/providers/Messages.java
new file mode 100644
index 00000000000..1b0d061dc91
--- /dev/null
+++ b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/language/settings/providers/Messages.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2019 Marc-Andre Laperle.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.cdt.managedbuilder.internal.ui.language.settings.providers;
+
+import org.eclipse.osgi.util.NLS;
+
+public class Messages extends NLS {
+ private static final String BUNDLE_NAME = "org.eclipse.cdt.managedbuilder.internal.ui.language.settings.providers.messages"; //$NON-NLS-1$
+ public static String CompilationDatabaseParserOptionPage_Browse;
+ public static String CompilationDatabaseParserOptionPage_BuildOutputParserError;
+ public static String CompilationDatabaseParserOptionPage_BuildParser;
+ public static String CompilationDatabaseParserOptionPage_ChooseFile;
+ public static String CompilationDatabaseParserOptionPage_CompileCommandsPath;
+ public static String CompilationDatabaseParserOptionPage_CompileCommandsPathError;
+ public static String CompilationDatabaseParserOptionPage_ExcludeFiles;
+ public static String CompilationDatabaseParserOptionPage_NoBuildOutputParserError;
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+ private Messages() {
+ }
+}
diff --git a/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/language/settings/providers/messages.properties b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/language/settings/providers/messages.properties
new file mode 100644
index 00000000000..c9657a74420
--- /dev/null
+++ b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/language/settings/providers/messages.properties
@@ -0,0 +1,19 @@
+################################################################################
+# Copyright (c) 2019 Marc-Andre Laperle.
+#
+# This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License 2.0
+# which accompanies this distribution, and is available at
+# https://www.eclipse.org/legal/epl-2.0/
+#
+# SPDX-License-Identifier: EPL-2.0
+################################################################################
+
+CompilationDatabaseParserOptionPage_Browse=Browse...
+CompilationDatabaseParserOptionPage_BuildOutputParserError=Invalid build parser
+CompilationDatabaseParserOptionPage_BuildParser=Build parser:
+CompilationDatabaseParserOptionPage_ChooseFile=Choose File
+CompilationDatabaseParserOptionPage_CompileCommandsPath=Compilation Database path (compile_commands.json):
+CompilationDatabaseParserOptionPage_CompileCommandsPathError=Compilation Database path does not exist
+CompilationDatabaseParserOptionPage_ExcludeFiles=Exclude files not in the Compilation Database
+CompilationDatabaseParserOptionPage_NoBuildOutputParserError=No build output parser enabled in "Providers"
diff --git a/releng/CDT.setup b/releng/CDT.setup
index 9df0b1396f6..9430d61d0b3 100644
--- a/releng/CDT.setup
+++ b/releng/CDT.setup
@@ -123,6 +123,10 @@
<requirement
name="org.junit.source"/>
<requirement
+ name="org.junit.jupiter.api"/>
+ <requirement
+ name="org.junit.jupiter.api.source"/>
+ <requirement
name="org.mockito"/>
<requirement
name="org.hamcrest"/>
diff --git a/releng/org.eclipse.cdt.target/cdt.target b/releng/org.eclipse.cdt.target/cdt.target
index 3be416a720f..c644ae01289 100644
--- a/releng/org.eclipse.cdt.target/cdt.target
+++ b/releng/org.eclipse.cdt.target/cdt.target
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?><?pde version="3.8"?><target name="cdt" sequenceNumber="62">
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><?pde version="3.8"?><target name="cdt" sequenceNumber="63">
<locations>
<location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="planner" includeSource="true" type="InstallableUnit">
<unit id="com.google.gson" version="0.0.0"/>
@@ -17,6 +17,8 @@
<unit id="org.hamcrest.core" version="0.0.0"/>
<unit id="org.junit" version="0.0.0"/>
<unit id="org.junit.source" version="0.0.0"/>
+<unit id="org.junit.jupiter.api" version="0.0.0"/>
+<unit id="org.junit.jupiter.api.source" version="0.0.0"/>
<unit id="org.mockito" version="0.0.0"/>
<unit id="org.slf4j.impl.log4j12" version="0.0.0"/>
<repository location="https://download.eclipse.org/tools/orbit/downloads/drops/R20190827152740/repository/"/>

Back to the top